diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 9517e8dd9..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,91 +0,0 @@ -version: 2 - -jobs: - python_2_7_15: - shell: /bin/bash --login - macos: - xcode: '9.0' - steps: - - checkout - - run: | - brew update - python --version - sudo -H pip install --upgrade virtualenv - brew install pyenv - echo 'eval "$(pyenv init -)"' >> ~/.bash_profile - source ~/.bash_profile - pyenv install 2.7.15 - pyenv versions - pyenv global 2.7.15 - python --version - - run: python setup.py install - - run: python setup.py test - - python_3_4_8: - shell: /bin/bash --login - macos: - xcode: '9.0' - steps: - - checkout - - run: | - brew update - python --version - sudo -H pip install --upgrade virtualenv - brew install pyenv - echo 'eval "$(pyenv init -)"' >> ~/.bash_profile - source ~/.bash_profile - pyenv install 3.4.8 - pyenv versions - pyenv global 3.4.8 - python --version - - run: python setup.py install - - run: python setup.py test - - python_3_5_5: - shell: /bin/bash --login - macos: - xcode: '9.0' - steps: - - checkout - - run: | - brew update - python --version - sudo -H pip install --upgrade virtualenv - brew install pyenv - echo 'eval "$(pyenv init -)"' >> ~/.bash_profile - source ~/.bash_profile - pyenv install 3.5.5 - pyenv versions - pyenv global 3.5.5 - python --version - - run: python setup.py install - - run: python setup.py test - - python_3_6_5: - shell: /bin/bash --login - macos: - xcode: '9.0' - steps: - - checkout - - run: | - brew update - python --version - sudo -H pip install --upgrade virtualenv - brew install pyenv - echo 'eval "$(pyenv init -)"' >> ~/.bash_profile - source ~/.bash_profile - pyenv install 3.6.5 - pyenv versions - pyenv global 3.6.5 - python --version - - run: python setup.py install - - run: python setup.py test - -workflows: - version: 2 - python_matrix_build: - jobs: - - python_2_7_15 - - python_3_4_8 - - python_3_5_5 - - python_3_6_5 diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 9c27e202e..000000000 --- a/.coveragerc +++ /dev/null @@ -1,3 +0,0 @@ -[run] -branch = True -source = spdx diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..38558bf37 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +end_of_line = lf + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..e2c6e5910 --- /dev/null +++ b/.flake8 @@ -0,0 +1,4 @@ +[flake8] +max-line-length = 119 +exclude = src/spdx_tools/spdx/parser/tagvalue/parsetab.py, __init__.py +extend-ignore = E203 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..91abb11fd --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "pip" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/workflows/check_codestyle.yml b/.github/workflows/check_codestyle.yml new file mode 100644 index 000000000..4cc16b9c1 --- /dev/null +++ b/.github/workflows/check_codestyle.yml @@ -0,0 +1,43 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +name: Run Linter + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + check_code_style: + runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash + strategy: + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11" ] + exclude: # see https://github.com/actions/runner-images/issues/9770#issuecomment-2085623315 + - python-version: "3.7" + os: macos-latest + include: + - python-version: "3.7" + os: macos-13 + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Installation + run: pip install ".[code_style]" + - name: Check code with isort + run: | + isort src tests --check + black src tests --check + flake8 src tests diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..095f9ec7a --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +name: Generate API docs + +on: + push: + branches: + - main + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Install dependencies + run: | + sudo apt-get install graphviz-dev + pip install -e ".[test,graph_generation]" + pip install pdoc + - name: Generate docs + run: pdoc spdx_tools -o docs/ + - name: Upload docs as artifact + uses: actions/upload-pages-artifact@v1 + with: + path: docs/ + + deploy: + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + name: Deploy docs to GitHub pages + uses: actions/deploy-pages@v2 diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml new file mode 100644 index 000000000..0f66cc73f --- /dev/null +++ b/.github/workflows/install_and_test.yml @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +name: Install and Test + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + install_and_test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11" ] + exclude: # see https://github.com/actions/runner-images/issues/9770#issuecomment-2085623315 + - python-version: "3.7" + os: macos-latest + include: + - python-version: "3.7" + os: macos-13 + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Installation + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools wheel setuptools_scm build + python -m build -nwx . + python -m pip install --upgrade ./dist/*.whl + python -m pip install pytest + python -m pip install pyshacl + python -m pip install tzdata + python -m pip install networkx + shell: bash + - name: Run tests + run: pytest + - name: Run CLI + run: pyspdxtools -i ./tests/spdx/data/SPDXJSONExample-v2.3.spdx.json diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml new file mode 100644 index 000000000..2a37fa7a6 --- /dev/null +++ b/.github/workflows/integration_test.yml @@ -0,0 +1,43 @@ +name: Circle conversion test + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + install_and_test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.11 + uses: actions/setup-python@v4 + with: + python-version: 3.11 + - name: Installation + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools wheel setuptools_scm build + python -m build -nwx . + python -m pip install --upgrade ./dist/*.whl + shell: bash + - name: Install jd + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: # Grab the latest version + repo: josephburnett/jd + platform: linux + extension-matching: disable + rename-to: jd + chmod: 0755 + - name: Run CLI + run: | + pyspdxtools -i ./tests/spdx/data/circleConversionTestInitialDocument.json -o circleTest.yaml + pyspdxtools -i circleTest.yaml -o circleTest.xml + pyspdxtools -i circleTest.xml -o circleTest.rdf + pyspdxtools -i circleTest.rdf -o circleTest.spdx + pyspdxtools -i circleTest.spdx -o circleTest.json + - name: Compare initial and final json document of the circle conversion test + run: jd -set ./tests/spdx/data/circleConversionTestInitialDocument.json circleTest.json diff --git a/.github/workflows/prepare_release.yml b/.github/workflows/prepare_release.yml new file mode 100644 index 000000000..1197a3d1d --- /dev/null +++ b/.github/workflows/prepare_release.yml @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +name: Prepare release + +on: + push: + tags: [ 'v*.*.*'] + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.7' + - name: Set up dependencies + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools wheel setuptools_scm build twine + python -m pip install -e . + shell: bash + - name: Build wheel + run: python -m build + - name: Verify build + run: twine check dist/* + - name: Create build archive + uses: a7ul/tar-action@v1.1.0 + with: + command: c + files: dist + outPath: spdx_tools_dist.tar.gz + - name: Create GitHub release + uses: softprops/action-gh-release@v1 + with: + files: spdx_tools_dist.tar.gz + generate_release_notes: true + draft: true diff --git a/.gitignore b/.gitignore index cc02c2461..d82f5bc0d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,9 @@ __pycache__/ *.py[cod] *.out /build/ -/dist/ +/dist*/ /tmp/ -spdx/parsers/parsetab.py +src/spdx_tools/spdx/parser/tagvalue/parsetab.py /.cache/ .tox diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 207ab70c2..000000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: python - -python: - - "2.7" - - "3.4" - - "3.5" - -install: - - ./setup.py install - -script: - - ./setup.py test diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..f17ee022c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,198 @@ +# Changelog + +## v0.8.3 (2024-09-27) + +### New features and changes + +* tag-value parser: + * fixed license expression error handling + * fixed parsing Tool or Organization as annotator + * allow "NONE" and "NOASSERTION" as strings for fields requiring text +* CLI tool: + * shortened the output of the FileNotFoundError + * now catches decoding errors while parsing +* fixed tag-value output when the ID of a related SPDX element is "NONE" or "NOASSERTION" +* spdx3: + * added REQUIREMENT type to software_purpose + * unindent creation information in element_writer +* internal: + * replaced remaining occurrences of Licensing() with spdx_licensing + * fixed CI not working for Python 3.7 on latest MacOS + +### Contributors + +This release was made possible by the following contributors. Thank you very much! + +* Stanislav Pankevich @stanislaw +* Meret Behrens @meretp +* Maximilian Huber @maxhbr +* Armin Tänzer @armintaenzertng + +## v0.8.2 (2023-10-12) + +### New features and changes + +* added optional encoding parameter for parsing files +* fixed handling of the FilesAnalyzed field in Tag-Value format +* fixed the validation of the DownloadLocation field +* fixed the error handling while parsing license expressions +* fixed output of timezone-sensitive datetimes +* added code architecture documentation + +### Contributors + +This release was made possible by the following contributors. Thank you very much! + +* Christian Decker @chrisdecker1201 +* Jeff Licquia @licquia +* Maximilian Huber @maxhbr +* Armin Tänzer @armintaenzertng + + +## v0.8.1 (2023-08-24) + +### New features and changes + +* massive speed-up in the validation process of large SBOMs +* validation now detects and checks license references from external documents +* allow for userinfo in git+ssh download location +* more efficient relationship parsing in JSON/YAML/XML + +### Contributors + +This release was made possible by the following contributors. Thank you very much! + +* Brian DeHamer @bdehamer +* Brandon Lum @lumjjb +* Maximilian Huber @maxhbr +* Armin Tänzer @armintaenzertng + + +## v0.8.0 (2023-07-25) + +### New features and changes + +* major refactoring of the library + * new and improved data model + * type hints and type checks have been added to the model classes + * license expressions and SPDX license list are now handled by the `license-expression` package + * to update your existing code, refer to the [migration guide](https://github.com/spdx/tools-python/wiki/How-to-migrate-from-0.7-to-0.8) +* experimental support for the upcoming SPDX v3 specification (note, however, that support is neither complete nor + stable at this point, as the spec is still evolving) +* full validation of SPDX documents against the v2.2 and v2.3 specification +* support for SPDX's RDF format with all v2.3 features +* unified `pysdpxtools` CLI tool replaces separate `pyspdxtools_parser` and `pyspdxtools_convertor` +* [online API documentation](https://spdx.github.io/tools-python) +* replaced CircleCI with GitHub Actions + +### Contributors + +This release was made possible by the following contributors. Thank you very much! + +* Armin Tänzer @armintaenzertng +* Gary O'Neall @goneall +* Gaurav Mishra @GMishx +* HarshvMahawar @HarshvMahawar +* Holger Frydrych @fholger +* Jeff Licquia @licquia +* Kate Stewart @kestewart +* Maximilian Huber @maxhbr +* Meret Behrens @meretp +* Nicolaus Weidner @nicoweidner +* William Armiros @willarmiros + + +## v0.7.1 (2023-03-14) + +### New features and changes + +* added GitHub Actions workflow +* added requirements.txt +* added uritools for URI validation +* Python >= 3.7 is now required +* json/yaml/xml: added support for empty arrays for hasFiles and licenseInfoFromFiles +* rdf: fixed writing of multiple packages +* tag-value: enhanced parsing of snippet ranges to not mix it up with package version +* tag-value: fixed parsing of whitespaces +* tag-value: duplicates in LicenseInfoInFile are now removed during writing +* account for supplier and originator to be NOASSERTION +* checksum validation now requires lowercase values +* during writing of a file, the encoding can be set (default is utf-8) +* license list updated to version 3.20 + +### Contributors + +This release was made possible by the following contributors. Thank you very much! + +* Christian Decker @chrisdecker1201 +* Marc-Etienne Vargenau @vargenau +* John Vandenberg @jayvdb +* Nicolaus Weidner @nicoweidner +* Meret Behrens @meretp +* Armin Tänzer @armintaenzertng +* Maximilian Huber @maxhbr + + +## v0.7.0 (2022-12-08) + +Starting a Changelog. + +### New features and changes + +* Dropped Python 2 support. Python >= 3.6 is now required. +* Added `pyspdxtools_convertor` and `pyspdxtools_parser` CLI scripts. See [the readme](README.md) for usage instructions. +* Updated the tools to support SPDX versions up to 2.3 and to conform with the specification. Apart from many bugfixes + and new properties, some of the more significant changes include: + * Support for multiple packages per document + * Support for multiple checksums for packages and files + * Support for files outside a package +* **Note**: Validation was updated to follow the 2.3 specification. Since there is currently no support for + version-specific handling, some details may be handled incorrectly for documents using lower + versions. The changes are mostly restricted to properties becoming optional and new property values becoming + available, and should be of limited impact. See https://spdx.github.io/spdx-spec/v2.3/diffs-from-previous-editions/ + for a list of changes between the versions. +* **Note**: RDF support for 2.3 is not completed, see https://github.com/spdx/tools-python/issues/295 +* Removed example documents from production code. Added additional up-to-date examples to test files. +* Introduced pytest as the preferred test framework. +* Improved error message handling and display. +* Extended the contribution guidelines. +* Improved tag/value output structure. +* Added .editorconfig and pyproject.toml. +* Improved handling of JSON-specific properties `documentDescribes` and `hasFiles`. +* Added new LicenseListVersion tag. +* Fixed annotation handling for the JSON and Tag/Value formats. +* Free form text values in Tag/Value no longer require `` tags if they don't span multiple lines. + +### Contributors + +This release was made possible by the following contributors. Thank you very much! + +* Meret Behrens @meretp +* Philippe Ombredanne @pombredanne +* Pierre Tardy @tardyp +* Nicolaus Weidner @nicoweidner +* Jeff Licquia @licquia +* Armin Tänzer @armintaenzertng +* Alberto Pianon @alpianon +* Rodney Richardson @RodneyRichardson +* Lon Hohberger @lhh +* Nathan Voss @njv299 +* Gary O'Neall @goneall +* Jeffrey Otterson @jotterson +* KOLANICH @KOLANICH +* Yash Varshney @Yash-Varshney +* HARDIK @HARDIK-TSH1392 +* Jose Quaresma @quaresmajose +* Santiago Torres @SantiagoTorres +* Shubham Kumar Jha @ShubhamKJha +* Steven Kalt @SKalt +* Cole Helbling @cole-h +* Daniel Holth @dholth +* John Vandenberg @jayvdb +* Kate Stewart @kestewart +* Alexios Zavras @zvr +* Maximilian Huber @maxhbr +* Kyle Altendorf @altendky +* alpianon @alpianon +* kbermude @kbermude +* mzfr @mzfr diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD deleted file mode 100644 index ad7f27b33..000000000 --- a/CONTRIBUTING.MD +++ /dev/null @@ -1,19 +0,0 @@ -# Contributing - -Thank you for your interest in `tools-python`. The project is open-source software, and bug reports, suggestions, and most especially patches are welcome. - -## Issues - -`tools-python` has a [project page on GitHub](https://github.com/spdx/tools-python/) where you can [create an issue](https://github.com/spdx/tools-python/issues/new) to report a bug, make a suggestion, or propose a substantial change or improvement that you might like to make. You may also wish to contact the SPDX working group technical team through its mailing list, [spdx-tech@lists.spdx.org](mailto:spdx-tech@lists.spdx.org). - -If you would like to work on a fix for any issue, please assign the issue to yourself prior to creating a patch. - -## Patches - -The source code for `tools-python` is hosted on [github.com/spdx/tools-python](https://github.com/spdx/tools-python). Please review [open pull requests](https://github.com/spdx/tools-python/pulls) before committing time to a substantial revision. Work along similar lines may already be in progress. - -To submit a patch via GitHub, fork the repository, create a topic branch from `master` for your work, and send a pull request when your local tests pass (`./setup.py test`). - -## Licensing - -However you choose to contribute, please sign-off in each of your commits that you license your contributions under the terms of [the Developer Certificate of Origin](https://developercertificate.org/). Git has utilities for signing off on commits: `git commit -s` signs a current commit, and `git rebase --signoff ` retroactively signs a range of past commits. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..4c4a04341 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,94 @@ +# Contributing + +Thank you for your interest in `tools-python`. The project is open-source software, and bug reports, suggestions, and +most especially patches are welcome. + +## Issues + +`tools-python` has a [project page on GitHub](https://github.com/spdx/tools-python/) where you +can [create an issue](https://github.com/spdx/tools-python/issues/new) to report a bug, make a suggestion, or propose a +substantial change or improvement. You may also wish to contact the SPDX working group technical team through its +mailing list, [spdx-tech@lists.spdx.org](mailto:spdx-tech@lists.spdx.org). + +If you would like to work on a fix for any issue, please assign the issue to yourself or write a comment indicating your +intention prior to creating a patch. + +## Development process + +We use the GitHub flow that is described here: https://guides.github.com/introduction/flow/ + +Here's the process to make changes to the codebase: + +1. Find or [file an issue](#issues) you'd like to address. Every change should be made to fix or close an issue. Please + try to keep issues reasonably small, focusing on one aspect, or split off sub-issues if possible. Large pull requests + that fix many things at the same time tend to cause a lot of conflicts. + +2. Review [open pull requests](https://github.com/spdx/tools-python/pulls) before committing time to a substantial + revision. Work along similar lines may already be in progress. + +3. Fork the repository as described [here](https://docs.github.com/en/get-started/quickstart/fork-a-repo#forking-a-repository) + and optionally follow the further steps described to sync your fork and the original repository. + +4. Create a new branch in your fork and set up environment: + ```sh + git checkout -b fix-or-improve-something + python -m venv ./venv + ./venv/bin/activate + pip install -e ".[development]" + ``` + Note: By using the group `[development]` for the installation, all dependencies (including optional ones) will be + installed. This way we make sure that all tests are executed. +5. Make some changes and commit them to the branch: + ```sh + git commit --signoff -m 'description of my changes' + ``` + + #### Licensing + + Please sign off in each of your commits that you license your contributions under the terms + of [the Developer Certificate of Origin](https://developercertificate.org/). Git has utilities for signing off on + commits: `git commit -s` or `--signoff` signs a current commit, and `git rebase --signoff ` + retroactively signs a range of past commits. +6. Test your changes: + ```sh + pytest -vvs # in the repo root + ``` + +7. Check your code style. When opening a pull request, your changes will automatically be checked with `isort`, `black` + and `flake8` to make sure your changes fit with the rest of the code style. + ```sh + # run the following commands in the repo root + isort src tests + black src tests + flake8 src tests + ``` + `black` and `isort` will automatically format the code and sort the imports. The configuration for these linters + can be found in the `pyproject.toml`. `flake8` lists all problems found which then need to be resolved manually. + The configuration for the linter can be found in the `.flake8` file. + +8. Push the branch to your fork on GitHub: + ```sh + git push origin fix-or-improve-something + ``` +9. Make a pull request on GitHub. +10. Continue making more changes and commits on the branch, with `git commit --signoff` and `git push`. +11. When done, write a comment on the PR asking for a code review. +12. Some other developer will review your changes and accept your PR. The merge should be done with `rebase`, if + possible, or with `squash`. +13. The temporary branch on GitHub should be deleted (there is a button for deleting it). +14. Delete the local branch as well: + ```sh + git checkout master + git pull -p + git branch -a + git branch -d fix-or-improve-something + ``` + +# How to run tests + +The tests framework is using pytest: + +``` +pip install pytest +pytest -vvs +``` diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md new file mode 100644 index 000000000..f8c7e274b --- /dev/null +++ b/DOCUMENTATION.md @@ -0,0 +1,109 @@ +# Code architecture documentation + +## Package Overview +Beneath the top-level package `spdx_tools` you will find three sub-packages: +- `spdx`, which contains the code to create, parse, write and validate SPDX documents of versions 2.2 and 2.3 +- `spdx3`, which will contain the same feature set for versions 3.x once they are released +- `common`, which contains code that is shared between the different versions, such as type-checking and `spdx_licensing`. + +## `spdx` +The `spdx` package contains the code dealing with SPDX-2 documents. +The subpackages serve the purpose to divide the code into logically independent chunks. Shared code can be found in the top-level modules here. +`model`, `parser`, `validation` and `writer` constitute the four main components of this library and are further described below. +`clitools` serves as the entrypoint for the command `pyspdxtools`. +`jsonschema` and `rdfschema` contain code specific to the corresponding serialization format. + +### `model` +The internal data model closely follows the [official SPDX-2.3 specification](https://spdx.github.io/spdx-spec/v2.3/). + +Entrypoint to the model is the `Document` class, which has the following attributes: +- `creation_info`: a single instance of the `CreationInfo` class +- `packages`: a list of `Package` objects +- `files`: a list of `File` objects +- `snippets`: a list of `Snippet` objects +- `relationships`: a list of `Relationship` objects +- `annotations`: a list of `Annotation` objects +- `extracted_licensing_info`: a list of `ExtractedLicensingInfo` objects + +For a complete overview of the model classes and their respective attributes, please refer to [the API documentation](https://spdx.github.io/tools-python/spdx_tools/spdx/model.html). + +For licensing attributes, i.e. those of type `LicenseExpression`, the `license-expression` library is used. +The function mainly used here is `get_spdx_licensing().parse(some_license_expression_string)`. +While `get_spdx_licensing()` takes very long to call, its return value can be reused across the code, which is why it is centrally provided by the `spdx_licensing` module in the `common` package. + +A custom extension of the `@dataclass` annotation is used that is called `@dataclass_with_properties`. +Apart from all the usual `dataclass` functionality, this implements fields of a class as properties with their own getter and setter methods. +This is used in particular to implement type checking when properties are set. +Source of truth for these checks are the attribute definitions at the start of the respective class that must specify the correct type hint. +The `beartype` library is used to check type conformity (`typeguard` was used in the past but has been replaced since due to performance issues). +In case of a type mismatch a `TypeError` is raised. To ensure that all possible type errors are found during the construction of an object, +a custom `__init__()` that calls `check_types_and_set_values()` is part of every class. +This function tries to set all values provided by the constructor and collects all occurrences of `TypeError` into a single error of type `ConstructorTypeErrors`. + +For the SPDX values `NONE` and `NOASSERTION` the classes `SpdxNone` and `SpdxNoAssertion` are used, respectively. Both can be instantiated without any arguments. + +### `parser` +The parsing and writing modules are split into subpackages according to the serialization formats: `json`, `yaml`, `xml`, `tagvalue` and `rdf`. +As the first three share the same tree structure that can be parsed into a dictionary, their shared logic is contained in the `jsonlikedict` package. +One overarching concept of all parsers is the goal of dealing with parsing errors (like faulty types or missing mandatory fields) as long as possible before failing. +Thus, the `SPDXParsingError` that is finally raised collects as much information as possible about all parsing errors that occurred. + +#### `tagvalue` +Since Tag-Value is an SPDX-specific format, there exist no readily available parsers for it. +This library implements its own deserialization code using the `ply` library's `lex` module for lexing and the `yacc` module for parsing. + +#### `rdf` +The `rdflib` library is used to deserialize RDF graphs from XML format. +The graph is then being parsed and translated into the internal data model. + +#### `json`, `yaml`, `xml` +In a first step, all three of JSON, YAML and XML formats are deserialized into a dictionary representing their tree structure. +This is achieved via the `json`, `yaml` and `xmltodict` packages, respectively. +Special note has to be taken in the XML case which does not support lists and numbers. +The logic concerning the translation from these dicts to the internal data model can be found in the `jsonlikedict` package. + +### `writer` +For serialization purposes, only non-null fields are written out. +All writers expect a valid SPDX document from the internal model as input. +To ensure this is actually the case, the standard behaviour of every writer function is to call validation before the writing process. +This can be disabled by setting the `validate` boolean to false. +Also by default, all list properties in the model are scanned for duplicates which are being removed. +This can be disabled by setting the `drop_duplicates` boolean to false. + +#### `tagvalue` +The ordering of the tags follows the [example in the official specification](https://github.com/spdx/spdx-spec/blob/development/v2.3.1/examples/SPDXTagExample-v2.3.spdx). + +#### `rdf` +The RDF graph is constructed from the internal data model and serialized to XML format afterward, using the `rdflib` library. + +#### `json`, `yaml`, `xml` +As all three of JSON, YAML and XML formats share the same tree structure, the first step is to generate the dictionary representing that tree. +This is achieved by the `DocumentConverter` class in the `jsonschema` package. +Subsequently, the dictionary is serialized using the `json`, `yaml` and `xmltodict` packages, respectively. + + +### `validation` +The `validation` package takes care of all nonconformities with the SPDX specification that are not due to incorrect typing. +This mainly includes checks for correctly formatted strings or the actual existence of references SPDXIDs. +Entrypoint is the `document_validator` module with the `validate_full_spdx_document()` function. +This library supports SPDX versions "SPDX-2.2" and "SPDX-2.3", which differ slightly in the validation process so that the version has to be specified here. +This main validator calls subvalidators for all packages, files etc. that are contained in the document. +Validators are split into two parts, where applicable: The first part validates the object on its own while the second validates it in the context of the whole document. +Validation and reference checking of SPDXIDs (and possibly external document references) is done in the `spdx_id_validators` module. +For the validation of license expressions we utilise the `license-expression` library's `validate` and `parse` functions, which take care of checking license symbols against the [SPDX license list](https://spdx.org/licenses/). + +Invalidities are captured in instances of a custom `ValidationMessage` class. This has two attributes: +- `validation_message` is a string that describes the actual problem +- `validation_context` is a `ValidationContext` object that helps to pinpoint the source of the problem by providing the faulty element's SPDXID (if it has one), the parent SPDXID (if that is known), the element's type and finally the full element itself. +It is left open to the implementer which of this information to use in the following evaluation of the validation process. + +Every validation function returns a list of `ValidationMessage` objects, which are gradually concatenated until the final list is returned. +That is, if an empty list is returned, the document is valid. + +## `spdx3` +Due to the SPDX-3 model still being in development, this package is still a work in progress. +However, as the basic building blocks of parsing, writing, creation and validation are still important in the new version, +the `spdx3` package is planned to be structured similarly to the `spdx` package. + +Additionally, the `bump_from_spdx2` package takes care of converting SPDX-2 documents to SPDX-3. +Guideline for this is the [migration guide](https://docs.google.com/document/d/1-olHRnX1CssUS67Psv_sAq9Vd-pc81HF8MM0hA7M0hg). diff --git a/README.md b/README.md index 69578b587..99112ea02 100644 --- a/README.md +++ b/README.md @@ -1,131 +1,215 @@ -# Python SPDX Library to parse, validate and create SPDX documents +# Python library to parse, validate and create SPDX documents -| Linux | macOS | Windows | -| :---- | :------ | :---- | -[ ![Linux build status][1]][2] | [![macOS build status][3]][4] | [![Windows build status][5]][6] | +CI status (Linux, macOS and Windows): [![Install and Test][1]][2] -[1]: https://travis-ci.org/spdx/tools-python.svg?branch=master -[2]: https://travis-ci.org/spdx/tools-python -[3]: https://circleci.com/gh/spdx/tools-python/tree/master.svg?style=shield&circle-token=36cca2dfa3639886fc34e22d92495a6773bdae6d -[4]: https://circleci.com/gh/spdx/tools-python/tree/master -[5]: https://ci.appveyor.com/api/projects/status/0bf9glha2yg9x8ef/branch/master?svg=true -[6]: https://ci.appveyor.com/project/spdx/tools-python/branch/master +[1]: https://github.com/spdx/tools-python/actions/workflows/install_and_test.yml/badge.svg -This library implements an SPDX tag/value and RDF parser, validator and handler in Python. -This is the result of an initial GSoC contribution by @[ah450](https://github.com/ah450) (or https://github.com/a-h-i) and -is maintained by a community of SPDX adopters and enthusiasts. +[2]: https://github.com/spdx/tools-python/actions/workflows/install_and_test.yml -Home: https://github.com/spdx/tools-python -Issues: https://github.com/spdx/tools-python/issues +# Breaking changes v0.7 -> v0.8 -Pypi: https://pypi.python.org/pypi/spdx-tools +Please be aware that the upcoming 0.8 release has undergone a significant refactoring in preparation for the upcoming +SPDX v3.0 release, leading to breaking changes in the API. +Please refer to the [migration guide](https://github.com/spdx/tools-python/wiki/How-to-migrate-from-0.7-to-0.8) +to update your existing code. +The main features of v0.8 are: +- full validation of SPDX documents against the v2.2 and v2.3 specification +- support for SPDX's RDF format with all v2.3 features +- experimental support for the upcoming SPDX v3 specification. Note, however, that support is neither complete nor + stable at this point, as the spec is still evolving. SPDX3-related code is contained in a separate subpackage "spdx3" + and its use is optional. We do not recommend using it in production code yet. -# License - -[Apache-2.0](LICENSE) +# Information -# Features +This library implements SPDX parsers, convertors, validators and handlers in Python. -* API to create and manipulate SPDX documents. -* Parse and create Tag/Value, RDF, JSON, YAML, XML format SPDX files +- Home: https://github.com/spdx/tools-python +- Issues: https://github.com/spdx/tools-python/issues +- PyPI: https://pypi.python.org/pypi/spdx-tools +- Browse the API: https://spdx.github.io/tools-python +Important updates regarding this library are shared via the SPDX tech mailing list: https://lists.spdx.org/g/Spdx-tech. -# TODOs -* Update to full SPDX v2.1 -* Add to full license expression support - - -# How to use - -Example tag/value parsing usage: -```Python - from spdx.parsers.tagvalue import Parser - from spdx.parsers.tagvaluebuilders import Builder - from spdx.parsers.loggers import StandardLogger - p = Parser(Builder(), StandardLogger()) - p.build() - # data is a string containing the SPDX file. - document, error = p.parse(data) - -``` - -The `examples` directory contains several code samples. Here some of them: - -* `parse_tv.py` is an example tag/value parsing usage. - Try running `python parse_tv.py ../data/SPDXSimpleTag.tag ` +# License -* `write_tv.py` provides an example of writing tag/value files. - Run `python write_tv.py sample.tag` to test it. +[Apache-2.0](LICENSE) -* `pp_tv.py` demonstrates how to pretty-print a tag/value file. - To test it run `python pp_tv.py ../data/SPDXTagExample.tag pretty.tag`. +# Features -* `parse_rdf.py` demonstrates how to parse an RDF file and print out document - information. To test it run `python parse_rdf.py ../data/SPDXRdfExample.rdf` +* API to create and manipulate SPDX v2.2 and v2.3 documents +* Parse, convert, create and validate SPDX files +* supported formats: Tag/Value, RDF, JSON, YAML, XML +* visualize the structure of a SPDX document by creating an `AGraph`. Note: This is an optional feature and requires +additional installation of optional dependencies -* `rdf_to_tv.py` demonstrates how to convert an RDF file to a tag/value one. - To test it run `python rdf_to_tv.py ../data/SPDXRdfExample.rdf converted.tag` +## Experimental support for SPDX 3.0 +* Create v3.0 elements and payloads +* Convert v2.2/v2.3 documents to v3.0 +* Serialize to JSON-LD -* `pp_rdf.py` demonstrates how to pretty-print an RDF file, to test it run - `python pp_rdf.py ../data/SPDXRdfExample.rdf pretty.rdf` +See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: a5372a3c145dbdfc1381fc1f791c68889aafc7ff). # Installation -As always you should work in a virtualenv or venv. You can install a local clone -of this repo with `yourenv/bin/pip install .` or install from PyPI with -`yourenv/bin/pip install spdx-tools`. Note that on Windows it would be `Scripts` +As always you should work in a virtualenv (venv). You can install a local clone +of this repo with `yourenv/bin/pip install .` or install it from PyPI +(check for the [newest release](https://pypi.org/project/spdx-tools/#history) and install it like +`yourenv/bin/pip install spdx-tools==0.8.0a2`). Note that on Windows it would be `Scripts` instead of `bin`. +# How to use -# How to run tests - -From the project root directory run: `python setup.py test`. -You can use another test runner such as pytest or nose at your preference. - - -# Development process - -We use the GitHub flow that is described here: https://guides.github.com/introduction/flow/ +## Command-line usage + +1. **PARSING/VALIDATING** (for parsing any format): + +* Use `pyspdxtools -i ` where `` is the location of the file. The input format is inferred automatically from the file ending. + +* If you are using a source distribution, try running: + `pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json` + +2. **CONVERTING** (for converting one format to another): + +* Use `pyspdxtools -i -o ` where `` is the location of the file to be converted + and `` is the location of the output file. The input and output formats are inferred automatically from the file endings. + +* If you are using a source distribution, try running: + `pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json -o output.tag` + +* If you want to skip the validation process, provide the `--novalidation` flag, like so: + `pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json -o output.tag --novalidation` + (use this with caution: note that undetected invalid documents may lead to unexpected behavior of the tool) + +* For help use `pyspdxtools --help` + +3. **GRAPH GENERATION** (optional feature) + +* This feature generates a graph representing all elements in the SPDX document and their connections based on the provided + relationships. The graph can be rendered to a picture. Below is an example for the file `tests/data/SPDXJSONExample-v2.3.spdx.json`: +![SPDXJSONExample-v2.3.spdx.png](assets/SPDXJSONExample-v2.3.spdx.png) +* Make sure you install the optional dependencies `networkx` and `pygraphviz`. To do so run `pip install ".[graph_generation]"`. +* Use `pyspdxtools -i --graph -o ` where `` is an output file name with valid format for `pygraphviz` (check + the documentation [here](https://pygraphviz.github.io/documentation/stable/reference/agraph.html#pygraphviz.AGraph.draw)). +* If you are using a source distribution, try running + `pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json --graph -o SPDXJSONExample-v2.3.spdx.png` to generate + a png with an overview of the structure of the example file. + +## Library usage +1. **DATA MODEL** + * The `spdx_tools.spdx.model` package constitutes the internal SPDX v2.3 data model (v2.2 is simply a subset of this). All relevant classes for SPDX document creation are exposed in the `__init__.py` found [here](src%2Fspdx_tools%2Fspdx%2Fmodel%2F__init__.py). + * SPDX objects are implemented via `@dataclass_with_properties`, a custom extension of `@dataclass`. + * Each class starts with a list of its properties and their possible types. When no default value is provided, the property is mandatory and must be set during initialization. + * Using the type hints, type checking is enforced when initializing a new instance or setting/getting a property on an instance + (wrong types will raise `ConstructorTypeError` or `TypeError`, respectively). This makes it easy to catch invalid properties early and only construct valid documents. + * Note: in-place manipulations like `list.append(item)` will circumvent the type checking (a `TypeError` will still be raised when reading `list` again). We recommend using `list = list + [item]` instead. + * The main entry point of an SPDX document is the `Document` class from the [document.py](src%2Fspdx_tools%2Fspdx%2Fmodel%2Fdocument.py) module, which links to all other classes. + * For license handling, the [license_expression](https://github.com/nexB/license-expression) library is used. + * Note on `documentDescribes` and `hasFiles`: These fields will be converted to relationships in the internal data model. As they are deprecated, these fields will not be written in the output. +2. **PARSING** + * Use `parse_file(file_name)` from the `parse_anything.py` module to parse an arbitrary file with one of the supported file endings. + * Successful parsing will return a `Document` instance. Unsuccessful parsing will raise `SPDXParsingError` with a list of all encountered problems. +3. **VALIDATING** + * Use `validate_full_spdx_document(document)` to validate an instance of the `Document` class. + * This will return a list of `ValidationMessage` objects, each consisting of a String describing the invalidity and a `ValidationContext` to pinpoint the source of the validation error. + * Validation depends on the SPDX version of the document. Note that only versions `SPDX-2.2` and `SPDX-2.3` are supported by this tool. +4. **WRITING** + * Use `write_file(document, file_name)` from the `write_anything.py` module to write a `Document` instance to the specified file. + The serialization format is determined from the filename ending. + * Validation is performed per default prior to the writing process, which is cancelled if the document is invalid. You can skip the validation via `write_file(document, file_name, validate=False)`. + Caution: Only valid documents can be serialized reliably; serialization of invalid documents is not supported. + +## Example +Here are some examples of possible use cases to quickly get you started with the spdx-tools. +If you want more examples, like how to create an SPDX document from scratch, have a look [at the examples folder](examples). +```python +import logging + +from license_expression import get_spdx_licensing + +from spdx_tools.spdx.model import (Checksum, ChecksumAlgorithm, File, + FileType, Relationship, RelationshipType) +from spdx_tools.spdx.parser.parse_anything import parse_file +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.writer.write_anything import write_file + +# read in an SPDX document from a file +document = parse_file("spdx_document.json") + +# change the document's name +document.creation_info.name = "new document name" + +# define a file and a DESCRIBES relationship between the file and the document +checksum = Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") + +file = File(name="./fileName.py", spdx_id="SPDXRef-File", checksums=[checksum], + file_types=[FileType.TEXT], + license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), + license_comment="licenseComment", copyright_text="copyrightText") + +relationship = Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File") + +# add the file and the relationship to the document +# (note that we do not use "document.files.append(file)" as that would circumvent the type checking) +document.files = document.files + [file] +document.relationships = document.relationships + [relationship] + +# validate the edited document and log the validation messages +# (depending on your use case, you might also want to utilize the validation_message.context) +validation_messages = validate_full_spdx_document(document) +for validation_message in validation_messages: + logging.warning(validation_message.validation_message) + +# if there are no validation messages, the document is valid +# and we can safely serialize it without validating again +if not validation_messages: + write_file(document, "new_spdx_document.rdf", validate=False) +``` -So, whenever we have to make some changes to the code, we should follow these steps: -1. Create a new branch: - `git checkout -b fix-or-improve-something` -2. Make some changes and the first commit(s) to the branch: - `git commit -m 'What changes we did'` -3. Push the branch to GitHub: - `git push origin fix-or-improve-something` -4. Make a pull request on GitHub. -5. Continue making more changes and commits on the branch, with `git commit` and `git push`. -6. When done, write a comment on the PR asking for a code review. -7. Some other developer will review your changes and accept your PR. The merge should be done with `rebase`, if possible, or with `squash`. -8. The temporary branch on GitHub should be deleted (there is a button for deleting it). -9. Delete the local branch as well: - ``` - git checkout master - git pull -p - git branch -a - git branch -d fix-or-improve-something - ``` +# Quickstart to SPDX 3.0 +In contrast to SPDX v2, all elements are now subclasses of the central `Element` class. +This includes packages, files, snippets, relationships, annotations, but also SBOMs, SpdxDocuments, and more. +For serialization purposes, all Elements that are to be serialized into the same file are collected in a `Payload`. +This is just a dictionary that maps each Element's SpdxId to itself. +Use the `write_payload()` functions to serialize a payload. +There currently are two options: +* The `spdx_tools.spdx3.writer.json_ld.json_ld_writer` module generates a JSON-LD file of the payload. +* The `spdx_tools.spdx3.writer.console.payload_writer` module prints a debug output to console. Note that this is not an official part of the SPDX specification and will probably be dropped as soon as a better standard emerges. -Besides this, another requirement is that every change should be made to fix or close an issue: https://guides.github.com/features/issues/ -If there is no issue for the changes that you want to make, create first an issue about it that describes what needs to be done, assign it to yourself, and then start working for closing it. +You can convert an SPDX v2 document to v3 via the `spdx_tools.spdx3.bump_from_spdx2.spdx_document` module. +The `bump_spdx_document()` function will return a payload containing an `SpdxDocument` Element and one Element for each package, file, snippet, relationship, or annotation contained in the v2 document. # Dependencies -* PLY : https://pypi.python.org/pypi/ply/ used for parsing. -* rdflib : https://pypi.python.org/pypi/rdflib/ for handling RDF. * PyYAML: https://pypi.org/project/PyYAML/ for handling YAML. * xmltodict: https://pypi.org/project/xmltodict/ for handling XML. - +* rdflib: https://pypi.python.org/pypi/rdflib/ for handling RDF. +* ply: https://pypi.org/project/ply/ for handling tag-value. +* click: https://pypi.org/project/click/ for creating the CLI interface. +* beartype: https://pypi.org/project/beartype/ for type checking. +* uritools: https://pypi.org/project/uritools/ for validation of URIs. +* license-expression: https://pypi.org/project/license-expression/ for handling SPDX license expressions. # Support -* Submit issues, questions or feedback at: https://github.com/spdx/tools-python/issues -* Join the dicussion on https://lists.spdx.org/mailman/listinfo/spdx-tech and - https://spdx.org/WorkgroupTechnical +* Submit issues, questions or feedback at https://github.com/spdx/tools-python/issues +* Join the chat at https://gitter.im/spdx-org/Lobby +* Join the discussion on https://lists.spdx.org/g/spdx-tech and + https://spdx.dev/participate/tech/ + +# Contributing + +Contributions are very welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for instructions on how to contribute to the +codebase. + +# History + +This is the result of an initial GSoC contribution by @[ah450](https://github.com/ah450) +(or https://github.com/a-h-i) and is maintained by a community of SPDX adopters and enthusiasts. +In order to prepare for the release of SPDX v3.0, the repository has undergone a major refactoring during the time from 11/2022 to 07/2023. diff --git a/appveyor.yml b/appveyor.yml index b8f6c7e53..6a4df0854 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,19 +1,20 @@ version: "{build}" - +image: + - Visual Studio 2019 environment: matrix: - - PYTHON_EXE: "C:\\Python27\\python.exe" - - PYTHON_EXE: "C:\\Python27-x64\\python.exe" - - PYTHON_EXE: "C:\\Python36\\python.exe" - - PYTHON_EXE: "C:\\Python36-x64\\python.exe" - - PYTHON_EXE: "C:\\Python37\\python.exe" - PYTHON_EXE: "C:\\Python37-x64\\python.exe" + - PYTHON_EXE: "C:\\Python38-x64\\python.exe" + - PYTHON_EXE: "C:\\Python39-x64\\python.exe" + - PYTHON_EXE: "C:\\Python310-x64\\python.exe" install: - "%PYTHON_EXE% --version" - - "%PYTHON_EXE% setup.py install" + - "%PYTHON_EXE% -m pip install --upgrade pip" + - "%PYTHON_EXE% -m pip install --upgrade setuptools setuptools_scm wheel build pytest" + - "%PYTHON_EXE% -m pip install --upgrade -e ." build: off test_script: - - "%PYTHON_EXE% setup.py test" + - "%PYTHON_EXE% -m pytest" diff --git a/assets/SPDXJSONExample-v2.3.spdx.png b/assets/SPDXJSONExample-v2.3.spdx.png new file mode 100644 index 000000000..1d050a166 Binary files /dev/null and b/assets/SPDXJSONExample-v2.3.spdx.png differ diff --git a/data/SPDXJsonExample.json b/data/SPDXJsonExample.json deleted file mode 100644 index ff624d40a..000000000 --- a/data/SPDXJsonExample.json +++ /dev/null @@ -1,185 +0,0 @@ -{ - "Document": { - "comment": "This is a sample spreadsheet", - "name": "Sample_Document-V2.1", - "documentDescribes": [ - { - "Package": { - "id": "SPDXRef-Package", - "originator": "Organization: SPDX", - "files": [ - { - "File": { - "comment": "This file belongs to Jena", - "licenseInfoFromFiles": [ - "LicenseRef-1" - ], - "sha1": "3ab4e1c67a2d28fced849ee1bb76e7391b93f125", - "name": "Jenna-2.6.3/jena-2.6.3-sources.jar", - "copyrightText": "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP", - "artifactOf" : [ - { - "name" : "Jena", - "homePage" : "http://www.openjena.org/", - "projectUri" : "http://subversion.apache.org/doap.rdf" - } - ], - "licenseConcluded": "LicenseRef-1", - "licenseComments": "This license is used by Jena", - "checksums": [ - { - "value": "3ab4e1c67a2d28fced849ee1bb76e7391b93f125", - "algorithm": "checksumAlgorithm_sha1" - } - ], - "fileTypes": [ - "fileType_archive" - ], - "id": "SPDXRef-File1" - } - }, - { - "File": { - "licenseInfoFromFiles": [ - "Apache-2.0" - ], - "sha1": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "name": "src/org/spdx/parser/DOAPProject.java", - "copyrightText": "Copyright 2010, 2011 Source Auditor Inc.", - "licenseConcluded": "Apache-2.0", - "checksums": [ - { - "value": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "algorithm": "checksumAlgorithm_sha1" - } - ], - "fileTypes": [ - "fileType_source" - ], - "id": "SPDXRef-File2" - } - } - ], - "licenseInfoFromFiles": [ - "Apache-1.0", - "LicenseRef-3", - "MPL-1.1", - "LicenseRef-2", - "LicenseRef-4", - "Apache-2.0", - "LicenseRef-1" - ], - "sha1": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "name": "SPDX Translator", - "packageFileName": "spdxtranslator-1.0.zip", - "licenseComments": "The declared license information can be found in the NOTICE file at the root of the archive file", - "summary": "SPDX Translator utility", - "sourceInfo": "Version 1.0 of the SPDX Translator application", - "copyrightText": " Copyright 2010, 2011 Source Auditor Inc.", - "packageVerificationCode": { - "value": "4e3211c67a2d28fced849ee1bb76e7391b93feba", - "excludedFilesNames": [ - "SpdxTranslatorSpdx.rdf", - "SpdxTranslatorSpdx.txt" - ] - }, - "licenseConcluded": "(Apache-1.0 AND LicenseRef-2 AND MPL-1.1 AND LicenseRef-3 AND LicenseRef-4 AND Apache-2.0 AND LicenseRef-1)", - "supplier": "Organization: Linux Foundation", - "checksums": [ - { - "value": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "algorithm": "checksumAlgorithm_sha1" - } - ], - "versionInfo": "Version 0.9.2", - "licenseDeclared": "(LicenseRef-4 AND LicenseRef-3 AND Apache-2.0 AND LicenseRef-2 AND MPL-1.1 AND LicenseRef-1)", - "downloadLocation": "http://www.spdx.org/tools", - "description": "This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document." - } - } - ], - "creationInfo": { - "comment": "This is an example of an SPDX spreadsheet format", - "creators": [ - "Tool: SourceAuditor-V1.2", - "Person: Gary O'Neall", - "Organization: Source Auditor Inc." - ], - "licenseListVersion": "3.6", - "created": "2010-02-03T00:00:00Z" - }, - "externalDocumentRefs": [ - { - "checksum": { - "value": "d6a770ba38583ed4bb4525bd96e50461655d2759", - "algorithm": "checksumAlgorithm_sha1" - }, - "spdxDocumentNamespace": "https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301", - "externalDocumentId": "DocumentRef-spdx-tool-2.1" - } - ], - "namespace": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", - "annotations": [ - { - "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses", - "annotationType": "REVIEW", - "id": "SPDXRef-45", - "annotationDate": "2012-06-13T00:00:00Z", - "annotator": "Person: Jim Reviewer" - } - ], - "dataLicense": "CC0-1.0", - "reviewers": [ - { - "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses", - "reviewer": "Person: Joe Reviewer", - "reviewDate": "2010-02-10T00:00:00Z" - }, - { - "comment": "Another example reviewer.", - "reviewer": "Person: Suzanne Reviewer", - "reviewDate": "2011-03-13T00:00:00Z" - } - ], - "extractedLicenseInfos": [ - { - "extractedText": "This package includes the GRDDL parser developed by Hewlett Packard under the following license:\n\u00a9 Copyright 2007 Hewlett-Packard Development Company, LP\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: \n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \nThe name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ", - "licenseId": "LicenseRef-2" - }, - { - "extractedText": "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the\n distribution.\n\n3. The end-user documentation included with the redistribution,\n if any, must include the following acknowledgment: \n \"This product includes software developed by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software itself,\n if and wherever such third-party acknowledgments normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n or promote products derived from this software without prior \n written permission. For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", - "comment": "This is tye CyperNeko License", - "licenseId": "LicenseRef-3", - "name": "CyberNeko License", - "seeAlso": [ - "http://justasample.url.com", - "http://people.apache.org/~andyc/neko/LICENSE" - ] - }, - { - "extractedText": "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */ ", - "licenseId": "LicenseRef-4" - }, - { - "extractedText": "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */", - "licenseId": "LicenseRef-1" - } - ], - "specVersion": "SPDX-2.1", - "id": "SPDXRef-DOCUMENT", - "snippets": [ - { - "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later.", - "name": "from linux kernel", - "copyrightText": "Copyright 2008-2010 John Smith", - "licenseConcluded": "Apache-2.0", - "licenseInfoFromSnippet": [ - "Apache-2.0" - ], - "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz.", - "id": "SPDXRef-Snippet", - "fileId": "SPDXRef-DoapSource" - } - ] - } -} \ No newline at end of file diff --git a/data/SPDXRdfExample.rdf b/data/SPDXRdfExample.rdf deleted file mode 100644 index f954a0aa0..000000000 --- a/data/SPDXRdfExample.rdf +++ /dev/null @@ -1,299 +0,0 @@ - - - - - - from linux kernel - Copyright 2008-2010 John Smith - The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. - This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later. - - - - - Sample_Document-V2.1 - - - 2010-02-03T00:00:00Z - This is an example of an SPDX spreadsheet format - Tool: SourceAuditor-V1.2 - Organization: Source Auditor Inc. - Person: Gary O'Neall - - - SPDX-2.1 - - - DocumentRef-spdx-tool-2.1 - - - - d6a770ba38583ed4bb4525bd96e50461655d2759 - - - - - - - > - - - /* - * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - LicenseRef-1 - - - - - http://www.openjena.org/ - Jena - - - This license is used by Jena - Jenna-2.6.3/jena-2.6.3-sources.jar - - (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - - This file belongs to Jena - - - 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - - - - - - - - This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - 2010-02-10T00:00:00Z - Person: Joe Reviewer - - - - - - - Another example reviewer. - 2011-03-13T00:00:00Z - Person: Suzanne Reviewer - - - - - - This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - 2012-06-13T00:00:00Z - Person: Jim Reviewer - - - - - Copyright 2010, 2011 Source Auditor Inc. - - - - - - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - - - - src/org/spdx/parser/DOAPProject.java - - - - - - http://www.spdx.org/tools - false - Organization:Linux Foundation - - - - - 4e3211c67a2d28fced849ee1bb76e7391b93feba - SpdxTranslatorSpdx.txt - SpdxTranslatorSpdx.rdf - - - - - - - This package includes the GRDDL parser developed by Hewlett Packard under the following license: -© Copyright 2007 Hewlett-Packard Development Company, LP - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - LicenseRef-2 - - - - - - - - - /* - * (c) Copyright 2009 University of Bristol - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - LicenseRef-4 - - - - - http://justasample.url.com - http://people.apache.org/~andyc/neko/LICENSE - CyberNeko License - This is tye CyperNeko License - The CyberNeko Software License, Version 1.0 - - -(C) Copyright 2002-2005, Andy Clark. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -3. The end-user documentation included with the redistribution, - if any, must include the following acknowledgment: - "This product includes software developed by Andy Clark." - Alternately, this acknowledgment may appear in the software itself, - if and wherever such third-party acknowledgments normally appear. - -4. The names "CyberNeko" and "NekoHTML" must not be used to endorse - or promote products derived from this software without prior - written permission. For written permission, please contact - andyc@cyberneko.net. - -5. Products derived from this software may not be called "CyberNeko", - nor may "CyberNeko" appear in their name, without prior written - permission of the author. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - LicenseRef-3 - - - - - Version 1.0 of the SPDX Translator application - - - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - - - - spdxtranslator-1.0.zip - This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document. - - SPDX Translator - Version 0.9.2 - - - - Copyright 2010, 2011 Source Auditor Inc. - - - - - - - - - - - - Organization:SPDX - The declared license information can be found in the NOTICE file at the root of the archive file - SPDX Translator utility - - - - - - org.apache.commons:commons-lang:3.2.1 - NIST National Vulnerability Database (NVD) describes security vulnerabilities (CVEs) which affect Vendor Product Version acmecorp:acmenator:6.6.6 - - - - - This is a sample spreadsheet - - - - - diff --git a/data/SPDXSimpleTag.tag b/data/SPDXSimpleTag.tag deleted file mode 100644 index 72b2f0322..000000000 --- a/data/SPDXSimpleTag.tag +++ /dev/null @@ -1,63 +0,0 @@ -# Document info -SPDXVersion: SPDX-2.1 -DataLicense: CC0-1.0 -DocumentName: Sample_Document-V2.1 -SPDXID: SPDXRef-DOCUMENT -DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 -DocumentComment: Sample Comment -ExternalDocumentRef:DocumentRef-spdx-tool-2.1 https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759 - -# Creation info -Creator: Person: Bob (bob@example.com) -Creator: Organization: Acme -Created: 2014-02-03T00:00:00Z -CreatorComment: Sample Comment - -# Review #1 -Reviewer: Person: Bob the Reviewer -ReviewDate: 2014-02-10T00:00:00Z -ReviewComment: Bob was Here. - -# Review #2 -Reviewer: Person: Alice the Reviewer -ReviewDate: 2014-04-10T00:00:00Z -ReviewComment: Alice was also here. - - -# Package info -PackageName: Test -SPDXID: SPDXRef-Package -PackageVersion: Version 0.9.2 -PackageDownloadLocation: http://example.com/test -PackageSummary: Test package -PackageSourceInfo: Version 1.0 of test -PackageFileName: test-1.0.zip -PackageSupplier: Organization:ACME -PackageOriginator: Organization:ACME -PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 -PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt) -PackageDescription: A package. -PackageCopyrightText: Copyright 2010, 2011 Acme Inc. -PackageLicenseDeclared: Apache-2.0 -PackageLicenseConcluded: (LicenseRef-2.0 and Apache-2.0) -PackageLicenseInfoFromFiles: Apache-1.0 -PackageLicenseInfoFromFiles: Apache-2.0 -PackageLicenseComments: License Comments - -# File Info - -FileName: testfile.java -SPDXID: SPDXRef-File -FileType: SOURCE -FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 -LicenseConcluded: Apache-2.0 -LicenseInfoInFile: Apache-2.0 -FileCopyrightText: Copyright 2014 Acme Inc. -ArtifactOfProjectName: AcmeTest -ArtifactOfProjectHomePage: http://www.acme.org/ -ArtifactOfProjectURI: http://www.acme.org/ -FileComment: Very long file - - - - diff --git a/data/SPDXTagExample.tag b/data/SPDXTagExample.tag deleted file mode 100644 index 713a3fc97..000000000 --- a/data/SPDXTagExample.tag +++ /dev/null @@ -1,212 +0,0 @@ -SPDXVersion: SPDX-2.1 -DataLicense: CC0-1.0 -DocumentName: Sample_Document-V2.1 -SPDXID: SPDXRef-DOCUMENT -DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 -DocumentComment: This is a sample spreadsheet - -## Creation Information -Creator: Person: Gary O'Neall -Creator: Organization: Source Auditor Inc. -Creator: Tool: SourceAuditor-V1.2 -Created: 2010-02-03T00:00:00Z -CreatorComment: This is an example of an SPDX spreadsheet format - -## Review Information -Reviewer: Person: Joe Reviewer -ReviewDate: 2010-02-10T00:00:00Z -ReviewComment: This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - -Reviewer: Person: Suzanne Reviewer -ReviewDate: 2011-03-13T00:00:00Z -ReviewComment: Another example reviewer. - -## Annotation Information -Annotator: Person: Jim Annotator -AnnotationType: REVIEW -AnnotationDate: 2012-03-11T00:00:00Z -AnnotationComment: An example annotation comment. -SPDXREF: SPDXRef-45 - -## Package Information -PackageName: SPDX Translator -SPDXID: SPDXRef-Package -PackageVersion: Version 0.9.2 -PackageDownloadLocation: http://www.spdx.org/tools -PackageHomePage: http://www.spdx.org/tools -PackageSummary: SPDX Translator utility -PackageSourceInfo: Version 1.0 of the SPDX Translator application -PackageFileName: spdxtranslator-1.0.zip -PackageSupplier: Organization:Linux Foundation -PackageOriginator: Organization:SPDX -PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 -PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (SpdxTranslatorSpdx.rdf, SpdxTranslatorSpdx.txt) -PackageDescription: This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document. -PackageComment: This package includes several sub-packages. - -PackageCopyrightText: Copyright 2010, 2011 Source Auditor Inc. - -PackageLicenseDeclared: (LicenseRef-3 AND LicenseRef-4 AND Apache-2.0 AND MPL-1.1 AND LicenseRef-1 AND LicenseRef-2) -PackageLicenseConcluded: (LicenseRef-3 AND LicenseRef-4 AND Apache-1.0 AND Apache-2.0 AND MPL-1.1 AND LicenseRef-1 AND LicenseRef-2) - -PackageLicenseInfoFromFiles: Apache-1.0 -PackageLicenseInfoFromFiles: LicenseRef-3 -PackageLicenseInfoFromFiles: Apache-2.0 -PackageLicenseInfoFromFiles: LicenseRef-4 -PackageLicenseInfoFromFiles: LicenseRef-2 -PackageLicenseInfoFromFiles: LicenseRef-1 -PackageLicenseInfoFromFiles: MPL-1.1 -PackageLicenseComments: The declared license information can be found in the NOTICE file at the root of the archive file - -ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*: -ExternalRefComment: NIST National Vulnerability Database (NVD) describes security vulnerabilities (CVEs) which affect Vendor Product Version acmecorp:acmenator:6.6.6. - -## File Information -FileName: src/org/spdx/parser/DOAPProject.java -SPDXID: SPDXRef-File1 -FileType: SOURCE -FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 -LicenseConcluded: Apache-2.0 -LicenseInfoInFile: Apache-2.0 -FileCopyrightText: Copyright 2010, 2011 Source Auditor Inc. - -FileName: Jenna-2.6.3/jena-2.6.3-sources.jar -SPDXID: SPDXRef-File2 -FileType: ARCHIVE -FileChecksum: SHA1: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 -LicenseConcluded: LicenseRef-1 -LicenseInfoInFile: LicenseRef-1 -LicenseComments: This license is used by Jena -FileCopyrightText: (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP -ArtifactOfProjectName: Jena -ArtifactOfProjectHomePage: http://www.openjena.org/ -ArtifactOfProjectURI: UNKNOWN -FileComment: This file belongs to Jena - -## Snippet Information -SnippetSPDXID: SPDXRef-Snippet -SnippetFromFileSPDXID: SPDXRef-DoapSource -SnippetLicenseComments: The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. -SnippetCopyrightText: Copyright 2008-2010 John Smith -SnippetComment: This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later. -SnippetName: from linux kernel -SnippetLicenseConcluded: Apache-2.0 -LicenseInfoInSnippet: Apache-2.0 - -## License Information -LicenseID: LicenseRef-3 -ExtractedText: The CyberNeko Software License, Version 1.0 - - -(C) Copyright 2002-2005, Andy Clark. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -3. The end-user documentation included with the redistribution, - if any, must include the following acknowledgment: - "This product includes software developed by Andy Clark." - Alternately, this acknowledgment may appear in the software itself, - if and wherever such third-party acknowledgments normally appear. - -4. The names "CyberNeko" and "NekoHTML" must not be used to endorse - or promote products derived from this software without prior - written permission. For written permission, please contact - andyc@cyberneko.net. - -5. Products derived from this software may not be called "CyberNeko", - nor may "CyberNeko" appear in their name, without prior written - permission of the author. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -LicenseName: CyberNeko License -LicenseCrossReference: http://people.apache.org/~andyc/neko/LICENSE -LicenseCrossReference: http://justasample.url.com -LicenseComment: This is tye CyperNeko License - -LicenseID: LicenseRef-1 -ExtractedText: /* - * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -LicenseID: LicenseRef-2 -ExtractedText: This package includes the GRDDL parser developed by Hewlett Packard under the following license: -© Copyright 2007 Hewlett-Packard Development Company, LP - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -LicenseID: LicenseRef-4 -ExtractedText: /* - * (c) Copyright 2009 University of Bristol - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - diff --git a/data/SPDXXmlExample.xml b/data/SPDXXmlExample.xml deleted file mode 100644 index f74859355..000000000 --- a/data/SPDXXmlExample.xml +++ /dev/null @@ -1,247 +0,0 @@ - - - - This is a sample spreadsheet - Sample_Document-V2.1 - - - SPDXRef-Package - Organization: SPDX - - - Apache-2.0 - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - src/org/spdx/parser/DOAPProject.java - Copyright 2010, 2011 Source Auditor Inc. - Apache-2.0 - - - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - checksumAlgorithm_sha1 - - fileType_source - SPDXRef-File2 - - - - - This file belongs to Jena - LicenseRef-1 - 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - Jenna-2.6.3/jena-2.6.3-sources.jar - (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - - Jena - http://www.openjena.org/ - http://subversion.apache.org/doap.rdf - - LicenseRef-1 - This license is used by Jena - - 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - checksumAlgorithm_sha1 - - fileType_archive - SPDXRef-File1 - - - LicenseRef-3 - LicenseRef-1 - Apache-1.0 - LicenseRef-4 - Apache-2.0 - LicenseRef-2 - MPL-1.1 - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - SPDX Translator - spdxtranslator-1.0.zip - The declared license information can be found in the NOTICE file at the root of the archive file - SPDX Translator utility - Version 1.0 of the SPDX Translator application - Copyright 2010, 2011 Source Auditor Inc. - - 4e3211c67a2d28fced849ee1bb76e7391b93feba - SpdxTranslatorSpdx.rdf - SpdxTranslatorSpdx.txt - - (LicenseRef-1 AND MPL-1.1 AND LicenseRef-2 AND LicenseRef-3 AND Apache-2.0 AND LicenseRef-4 AND Apache-1.0) - Organization: Linux Foundation - - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - checksumAlgorithm_sha1 - - Version 0.9.2 - (LicenseRef-3 AND LicenseRef-2 AND Apache-2.0 AND MPL-1.1 AND LicenseRef-1 AND LicenseRef-4) - http://www.spdx.org/tools - This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document. - - - - This is an example of an SPDX spreadsheet format - Tool: SourceAuditor-V1.2 - Person: Gary O'Neall - Organization: Source Auditor Inc. - 3.6 - 2010-02-03T00:00:00Z - - - - d6a770ba38583ed4bb4525bd96e50461655d2759 - checksumAlgorithm_sha1 - - https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 - DocumentRef-spdx-tool-2.1 - - https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 - - This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - REVIEW - SPDXRef-45 - 2012-06-13T00:00:00Z - Person: Jim Reviewer - - CC0-1.0 - - This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - Person: Joe Reviewer - 2010-02-10T00:00:00Z - - - Another example reviewer. - Person: Suzanne Reviewer - 2011-03-13T00:00:00Z - - - /* - * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - LicenseRef-1 - - - This package includes the GRDDL parser developed by Hewlett Packard under the following license: -© Copyright 2007 Hewlett-Packard Development Company, LP - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - LicenseRef-2 - - - The CyberNeko Software License, Version 1.0 - - -(C) Copyright 2002-2005, Andy Clark. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -3. The end-user documentation included with the redistribution, - if any, must include the following acknowledgment: - "This product includes software developed by Andy Clark." - Alternately, this acknowledgment may appear in the software itself, - if and wherever such third-party acknowledgments normally appear. - -4. The names "CyberNeko" and "NekoHTML" must not be used to endorse - or promote products derived from this software without prior - written permission. For written permission, please contact - andyc@cyberneko.net. - -5. Products derived from this software may not be called "CyberNeko", - nor may "CyberNeko" appear in their name, without prior written - permission of the author. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - This is tye CyperNeko License - LicenseRef-3 - CyberNeko License - http://justasample.url.com - http://people.apache.org/~andyc/neko/LICENSE - - - /* - * (c) Copyright 2009 University of Bristol - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - LicenseRef-4 - - SPDX-2.1 - SPDXRef-DOCUMENT - - This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later. - from linux kernel - Copyright 2008-2010 John Smith - Apache-2.0 - Apache-2.0 - The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. - SPDXRef-Snippet - SPDXRef-DoapSource - - - \ No newline at end of file diff --git a/data/SPDXYamlExample.yaml b/data/SPDXYamlExample.yaml deleted file mode 100644 index afd6791f7..000000000 --- a/data/SPDXYamlExample.yaml +++ /dev/null @@ -1,221 +0,0 @@ ---- -Document: - annotations: - - annotationDate: '2012-06-13T00:00:00Z' - annotationType: REVIEW - annotator: 'Person: Jim Reviewer' - comment: This is just an example. Some of the non-standard licenses look like - they are actually BSD 3 clause licenses - id: SPDXRef-45 - comment: This is a sample spreadsheet - creationInfo: - comment: This is an example of an SPDX spreadsheet format - created: '2010-02-03T00:00:00Z' - creators: - - 'Tool: SourceAuditor-V1.2' - - 'Organization: Source Auditor Inc.' - - 'Person: Gary O''Neall' - licenseListVersion: '3.6' - dataLicense: CC0-1.0 - documentDescribes: - - Package: - id: SPDXRef-Package - checksums: - - algorithm: checksumAlgorithm_sha1 - value: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - copyrightText: ' Copyright 2010, 2011 Source Auditor Inc.' - description: This utility translates and SPDX RDF XML document to a spreadsheet, - translates a spreadsheet to an SPDX RDF XML document and translates an SPDX - RDFa document to an SPDX RDF XML document. - downloadLocation: http://www.spdx.org/tools - files: - - File: - checksums: - - algorithm: checksumAlgorithm_sha1 - value: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - comment: This file belongs to Jena - copyrightText: (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009 Hewlett-Packard Development Company, LP - artifactOf: - - name: "Jena" - homePage: "http://www.openjena.org/" - projectUri: "http://subversion.apache.org/doap.rdf" - fileTypes: - - fileType_archive - id: SPDXRef-File1 - licenseComments: This license is used by Jena - licenseConcluded: LicenseRef-1 - licenseInfoFromFiles: - - LicenseRef-1 - name: Jenna-2.6.3/jena-2.6.3-sources.jar - sha1: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - - File: - checksums: - - algorithm: checksumAlgorithm_sha1 - value: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - copyrightText: Copyright 2010, 2011 Source Auditor Inc. - fileTypes: - - fileType_source - id: SPDXRef-File2 - licenseConcluded: Apache-2.0 - licenseInfoFromFiles: - - Apache-2.0 - name: src/org/spdx/parser/DOAPProject.java - sha1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - licenseComments: The declared license information can be found in the NOTICE - file at the root of the archive file - licenseConcluded: (LicenseRef-3 AND LicenseRef-1 AND MPL-1.1 AND Apache-2.0 - AND LicenseRef-2 AND Apache-1.0 AND LicenseRef-4) - licenseDeclared: (MPL-1.1 AND LicenseRef-4 AND LicenseRef-2 AND LicenseRef-1 - AND Apache-2.0 AND LicenseRef-3) - licenseInfoFromFiles: - - Apache-2.0 - - MPL-1.1 - - LicenseRef-3 - - LicenseRef-1 - - LicenseRef-4 - - Apache-1.0 - - LicenseRef-2 - name: SPDX Translator - originator: 'Organization: SPDX' - packageFileName: spdxtranslator-1.0.zip - packageVerificationCode: - excludedFilesNames: - - SpdxTranslatorSpdx.txt - - SpdxTranslatorSpdx.rdf - value: 4e3211c67a2d28fced849ee1bb76e7391b93feba - sha1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - sourceInfo: Version 1.0 of the SPDX Translator application - summary: SPDX Translator utility - supplier: 'Organization: Linux Foundation' - versionInfo: Version 0.9.2 - externalDocumentRefs: - - checksum: - algorithm: checksumAlgorithm_sha1 - value: d6a770ba38583ed4bb4525bd96e50461655d2759 - externalDocumentId: DocumentRef-spdx-tool-2.1 - spdxDocumentNamespace: https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 - extractedLicenseInfos: - - comment: This is tye CyperNeko License - extractedText: "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright\ - \ 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in\ - \ source and binary forms, with or without\nmodification, are permitted provided\ - \ that the following conditions\nare met:\n\n1. Redistributions of source code\ - \ must retain the above copyright\n notice, this list of conditions and the\ - \ following disclaimer. \n\n2. Redistributions in binary form must reproduce\ - \ the above copyright\n notice, this list of conditions and the following\ - \ disclaimer in\n the documentation and/or other materials provided with the\n\ - \ distribution.\n\n3. The end-user documentation included with the redistribution,\n\ - \ if any, must include the following acknowledgment: \n \"This product\ - \ includes software developed by Andy Clark.\"\n Alternately, this acknowledgment\ - \ may appear in the software itself,\n if and wherever such third-party acknowledgments\ - \ normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be\ - \ used to endorse\n or promote products derived from this software without\ - \ prior \n written permission. For written permission, please contact \n \ - \ andyc@cyberneko.net.\n\n5. Products derived from this software may not be\ - \ called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without\ - \ prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS\ - \ IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED\ - \ TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\ - \ PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\n\ - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL\ - \ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS\ - \ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER\ - \ CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY,\ - \ OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ - \ USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." - licenseId: LicenseRef-3 - name: CyberNeko License - seeAlso: - - http://justasample.url.com - - http://people.apache.org/~andyc/neko/LICENSE - - extractedText: "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006,\ - \ 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n\ - \ *\n * Redistribution and use in source and binary forms, with or without\n\ - \ * modification, are permitted provided that the following conditions\n * are\ - \ met:\n * 1. Redistributions of source code must retain the above copyright\n\ - \ * notice, this list of conditions and the following disclaimer.\n * 2.\ - \ Redistributions in binary form must reproduce the above copyright\n * notice,\ - \ this list of conditions and the following disclaimer in the\n * documentation\ - \ and/or other materials provided with the distribution.\n * 3. The name of\ - \ the author may not be used to endorse or promote products\n * derived from\ - \ this software without specific prior written permission.\n *\n * THIS SOFTWARE\ - \ IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES,\ - \ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY\ - \ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL\ - \ THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY,\ - \ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF\ - \ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS\ - \ INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN\ - \ CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE)\ - \ ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF\ - \ THE POSSIBILITY OF SUCH DAMAGE.\n */" - licenseId: LicenseRef-1 - - extractedText: "This package includes the GRDDL parser developed by Hewlett Packard\ - \ under the following license:\n\xA9 Copyright 2007 Hewlett-Packard Development\ - \ Company, LP\n\nRedistribution and use in source and binary forms, with or\ - \ without modification, are permitted provided that the following conditions\ - \ are met: \n\nRedistributions of source code must retain the above copyright\ - \ notice, this list of conditions and the following disclaimer. \nRedistributions\ - \ in binary form must reproduce the above copyright notice, this list of conditions\ - \ and the following disclaimer in the documentation and/or other materials provided\ - \ with the distribution. \nThe name of the author may not be used to endorse\ - \ or promote products derived from this software without specific prior written\ - \ permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS\ - \ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\ - \ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN\ - \ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\ - \ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\ - \ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\ - \ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\ - \ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\ - \ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\ - \ POSSIBILITY OF SUCH DAMAGE. " - licenseId: LicenseRef-2 - - extractedText: "/*\n * (c) Copyright 2009 University of Bristol\n * All rights\ - \ reserved.\n *\n * Redistribution and use in source and binary forms, with\ - \ or without\n * modification, are permitted provided that the following conditions\n\ - \ * are met:\n * 1. Redistributions of source code must retain the above copyright\n\ - \ * notice, this list of conditions and the following disclaimer.\n * 2.\ - \ Redistributions in binary form must reproduce the above copyright\n * notice,\ - \ this list of conditions and the following disclaimer in the\n * documentation\ - \ and/or other materials provided with the distribution.\n * 3. The name of\ - \ the author may not be used to endorse or promote products\n * derived from\ - \ this software without specific prior written permission.\n *\n * THIS SOFTWARE\ - \ IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES,\ - \ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY\ - \ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL\ - \ THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY,\ - \ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF\ - \ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS\ - \ INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN\ - \ CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE)\ - \ ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF\ - \ THE POSSIBILITY OF SUCH DAMAGE.\n */ " - licenseId: LicenseRef-4 - id: SPDXRef-DOCUMENT - name: Sample_Document-V2.1 - namespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 - reviewers: - - comment: Another example reviewer. - reviewDate: '2011-03-13T00:00:00Z' - reviewer: 'Person: Suzanne Reviewer' - - comment: This is just an example. Some of the non-standard licenses look like - they are actually BSD 3 clause licenses - reviewDate: '2010-02-10T00:00:00Z' - reviewer: 'Person: Joe Reviewer' - snippets: - - comment: This snippet was identified as significant and highlighted in this Apache-2.0 - file, when a commercial scanner identified it as being derived from file foo.c - in package xyz which is licensed under GPL-2.0-or-later. - copyrightText: Copyright 2008-2010 John Smith - fileId: SPDXRef-DoapSource - id: SPDXRef-Snippet - licenseComments: The concluded license was taken from package xyz, from which - the snippet was copied into the current file. The concluded license information - was found in the COPYING.txt file in package xyz. - licenseConcluded: Apache-2.0 - licenseInfoFromSnippet: - - Apache-2.0 - name: from linux kernel - specVersion: SPDX-2.1 diff --git a/dev/publish_from_tag.sh b/dev/publish_from_tag.sh new file mode 100755 index 000000000..eb367d781 --- /dev/null +++ b/dev/publish_from_tag.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +set -euo pipefail + +if [ $# -eq 0 ]; then + cat< /dev/null; then + echo "twine could not be found" + echo "maybe load venv with" + echo " . ./venv/bin/activate" + echo " . ./venv/bin/activate.fish" + echo + + if [[ -d ./venv/bin/ ]]; then + echo "will try to activate ./venv ..." + + source ./venv/bin/activate + + if ! command -v twine &> /dev/null; then + echo "twine still could not be found" + exit 1 + fi + else + exit 1 + fi +fi + + +if [[ -d "$tag_dir" ]]; then + echo "the dir \"$tag_dir\" already exists, exiting for safety" + exit 1 +fi + +mkdir -p "$tag_dir" +(cd "$tag_dir" && wget -c "$tar_gz" -O - | tar --strip-components=1 -xz) + +twine check "${tag_dir}/spdx-tools-${version}.tar.gz" "${tag_dir}/spdx_tools-${version}-py3-none-any.whl" +read -r -p "Do you want to upload? [y/N] " response +case "$response" in + [yY][eE][sS]|[yY]) + twine upload -r pypi "${tag_dir}/spdx-tools-${version}.tar.gz" "${tag_dir}/spdx_tools-${version}-py3-none-any.whl" + ;; +esac diff --git a/examples/parse_json.py b/examples/parse_json.py deleted file mode 100644 index b1b291f17..000000000 --- a/examples/parse_json.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python - -# Parses an JSON file and prints out some basic information. -# Usage: parse_json.py - -if __name__ == '__main__': - import sys - import spdx.file as spdxfile - from spdx.parsers.jsonparser import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.jsonyamlxmlbuilders import Builder - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - with open(file) as f: - doc, error = p.parse(f) - if not error: - print('doc comment: {0}'.format(doc.comment)) - print('Creators:') - for c in doc.creation_info.creators: - print('\t{0}'.format(c)) - print('Document review information:') - for review in doc.reviews: - print('\tReviewer: {0}'.format(review.reviewer)) - print('\tDate: {0}'.format(review.review_date)) - print('\tComment: {0}'.format(review.comment)) - print('Creation comment: {0}'.format(doc.creation_info.comment)) - print('Package Name: {0}'.format(doc.package.name)) - print('Package Version: {0}'.format(doc.package.version)) - print('Package Download Location: {0}'.format(doc.package.download_location)) - print('Package Homepage: {0}'.format(doc.package.homepage)) - print('Package Checksum: {0}'.format(doc.package.check_sum.value)) - print('Package verification code: {0}'.format(doc.package.verif_code)) - print('Package excluded from verif: {0}'.format(','.join(doc.package.verif_exc_files))) - print('Package license concluded: {0}'.format(doc.package.conc_lics)) - print('Package license declared: {0}'.format(doc.package.license_declared)) - print('Package licenses from files:') - for lics in doc.package.licenses_from_files: - print('\t{0}'.format(lics)) - print('Package Copyright text: {0}'.format(doc.package.cr_text)) - print('Package summary: {0}'.format(doc.package.summary)) - print('Package description: {0}'.format(doc.package.description)) - print('Package Files:') - VALUES = { - spdxfile.FileType.SOURCE: 'SOURCE', - spdxfile.FileType.OTHER: 'OTHER', - spdxfile.FileType.BINARY: 'BINARY', - spdxfile.FileType.ARCHIVE: 'ARCHIVE' - } - for f in doc.files: - print('\tFile name: {0}'.format(f.name)) - print('\tFile type: {0}'.format(VALUES[f.type])) - print('\tFile Checksum: {0}'.format(f.chk_sum.value)) - print('\tFile license concluded: {0}'.format(f.conc_lics)) - print('\tFile license info in file: {0}'.format(','.join( - map(lambda l: l.identifier, f.licenses_in_file)))) - print('\tFile artifact of project name: {0}'.format(','.join(f.artifact_of_project_name))) - - print('Document Extracted licenses:') - for lics in doc.extracted_licenses: - print('\tIdentifier: {0}'.format(lics.identifier)) - print('\tName: {0}'.format(lics.full_name)) - print('Annotations:') - for an in doc.annotations: - print('\tAnnotator: {0}'.format(an.annotator)) - print('\tAnnotation Date: {0}'.format(an.annotation_date)) - print('\tAnnotation Comment: {0}'.format(an.comment)) - print('\tAnnotation Type: {0}'.format(an.annotation_type)) - print('\tAnnotation SPDX Identifier: {0}'.format(an.spdx_id)) - - else: - print('Errors while parsing') diff --git a/examples/parse_rdf.py b/examples/parse_rdf.py deleted file mode 100755 index 3303ee986..000000000 --- a/examples/parse_rdf.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python - -# Parses an RDF file and prints out some basic information. -# Usage: parse_rdf.py -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -if __name__ == '__main__': - import sys - import spdx.file as spdxfile - from spdx.parsers.rdf import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.rdfbuilders import Builder - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - with open(file) as f: - doc, error = p.parse(f) - if not error: - print('doc comment: {0}'.format(doc.comment)) - print('Creators:') - for c in doc.creation_info.creators: - print('\t{0}'.format(c)) - print('Document review information:') - for review in doc.reviews: - print('\tReviewer: {0}'.format(review.reviewer)) - print('\tDate: {0}'.format(review.review_date)) - print('\tComment: {0}'.format(review.comment)) - print('Creation comment: {0}'.format(doc.creation_info.comment)) - print('Package Name: {0}'.format(doc.package.name)) - print('Package Version: {0}'.format(doc.package.version)) - print('Package Download Location: {0}'.format(doc.package.download_location)) - print('Package Homepage: {0}'.format(doc.package.homepage)) - print('Package Checksum: {0}'.format(doc.package.check_sum.value)) - print('Package verification code: {0}'.format(doc.package.verif_code)) - print('Package excluded from verif: {0}'.format(','.join(doc.package.verif_exc_files))) - print('Package license concluded: {0}'.format(doc.package.conc_lics)) - print('Package license declared: {0}'.format(doc.package.license_declared)) - print('Package licenses from files:') - for lics in doc.package.licenses_from_files: - print('\t{0}'.format(lics)) - print('Package Copyright text: {0}'.format(doc.package.cr_text)) - print('Package summary: {0}'.format(doc.package.summary)) - print('Package description: {0}'.format(doc.package.description)) - print('Package Files:') - VALUES = { - spdxfile.FileType.SOURCE: 'SOURCE', - spdxfile.FileType.OTHER: 'OTHER', - spdxfile.FileType.BINARY: 'BINARY', - spdxfile.FileType.ARCHIVE: 'ARCHIVE' - } - for f in doc.files: - print('\tFile name: {0}'.format(f.name)) - print('\tFile type: {0}'.format(VALUES[f.type])) - print('\tFile Checksum: {0}'.format(f.chk_sum.value)) - print('\tFile license concluded: {0}'.format(f.conc_lics)) - print('\tFile license info in file: {0}'.format(','.join( - map(lambda l: l.identifier, f.licenses_in_file)))) - print('\tFile artifact of project name: {0}'.format(','.join(f.artifact_of_project_name))) - - print('Document Extracted licenses:') - for lics in doc.extracted_licenses: - print('\tIdentifier: {0}'.format(lics.identifier)) - print('\tName: {0}'.format(lics.full_name)) - - print('Annotations:') - for an in doc.annotations: - print('\tAnnotator: {0}'.format(an.annotator)) - print('\tAnnotation Date: {0}'.format(an.annotation_date)) - print('\tAnnotation Comment: {0}'.format(an.comment)) - print('\tAnnotation Type: {0}'.format(an.annotation_type)) - print('\tAnnotation SPDX Identifier: {0}'.format(an.spdx_id)) - - else: - print('Errors while parsing') diff --git a/examples/parse_tv.py b/examples/parse_tv.py deleted file mode 100755 index bc857bd78..000000000 --- a/examples/parse_tv.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python - -# Parses a tag/value file and prints out some basic information. -# Usage: parse_tv.py -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -if __name__ == '__main__': - import sys - from spdx.parsers.tagvalue import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.tagvaluebuilders import Builder - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - p.build() - with open(file) as f: - data = f.read() - document, error = p.parse(data) - if not error: - print('Parsing Successful') - print('Document Version {0}.{1}'.format(document.version.major, - document.version.minor)) - print('Package name : {0}'.format(document.package.name)) - print('Creators : ') - for creator in document.creation_info.creators: - print(creator.name) - else: - print('Errors encountered while parsing') diff --git a/examples/parse_xml.py b/examples/parse_xml.py deleted file mode 100644 index 8961c2cca..000000000 --- a/examples/parse_xml.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python - -# Parses an XML file and prints out some basic information. -# Usage: parse_xml.py - -if __name__ == '__main__': - import sys - import spdx.file as spdxfile - from spdx.parsers.xmlparser import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.jsonyamlxmlbuilders import Builder - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - with open(file) as f: - doc, error = p.parse(f) - if not error: - print('doc comment: {0}'.format(doc.comment)) - print('Creators:') - for c in doc.creation_info.creators: - print('\t{0}'.format(c)) - print('Document review information:') - for review in doc.reviews: - print('\tReviewer: {0}'.format(review.reviewer)) - print('\tDate: {0}'.format(review.review_date)) - print('\tComment: {0}'.format(review.comment)) - print('Creation comment: {0}'.format(doc.creation_info.comment)) - print('Package Name: {0}'.format(doc.package.name)) - print('Package Version: {0}'.format(doc.package.version)) - print('Package Download Location: {0}'.format(doc.package.download_location)) - print('Package Homepage: {0}'.format(doc.package.homepage)) - print('Package Checksum: {0}'.format(doc.package.check_sum.value)) - print('Package verification code: {0}'.format(doc.package.verif_code)) - print('Package excluded from verif: {0}'.format(','.join(doc.package.verif_exc_files))) - print('Package license concluded: {0}'.format(doc.package.conc_lics)) - print('Package license declared: {0}'.format(doc.package.license_declared)) - print('Package licenses from files:') - for lics in doc.package.licenses_from_files: - print('\t{0}'.format(lics)) - print('Package Copyright text: {0}'.format(doc.package.cr_text)) - print('Package summary: {0}'.format(doc.package.summary)) - print('Package description: {0}'.format(doc.package.description)) - print('Package Files:') - VALUES = { - spdxfile.FileType.SOURCE: 'SOURCE', - spdxfile.FileType.OTHER: 'OTHER', - spdxfile.FileType.BINARY: 'BINARY', - spdxfile.FileType.ARCHIVE: 'ARCHIVE' - } - for f in doc.files: - print('\tFile name: {0}'.format(f.name)) - print('\tFile type: {0}'.format(VALUES[f.type])) - print('\tFile Checksum: {0}'.format(f.chk_sum.value)) - print('\tFile license concluded: {0}'.format(f.conc_lics)) - print('\tFile license info in file: {0}'.format(','.join( - map(lambda l: l.identifier, f.licenses_in_file)))) - print('\tFile artifact of project name: {0}'.format(','.join(f.artifact_of_project_name))) - - print('Document Extracted licenses:') - for lics in doc.extracted_licenses: - print('\tIdentifier: {0}'.format(lics.identifier)) - print('\tName: {0}'.format(lics.full_name)) - print('Annotations:') - for an in doc.annotations: - print('\tAnnotator: {0}'.format(an.annotator)) - print('\tAnnotation Date: {0}'.format(an.annotation_date)) - print('\tAnnotation Comment: {0}'.format(an.comment)) - print('\tAnnotation Type: {0}'.format(an.annotation_type)) - print('\tAnnotation SPDX Identifier: {0}'.format(an.spdx_id)) - - else: - print('Errors while parsing') diff --git a/examples/parse_yaml.py b/examples/parse_yaml.py deleted file mode 100644 index 22cb6a0ce..000000000 --- a/examples/parse_yaml.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python - -# Parses an YAML file and prints out some basic information. -# Usage: parse_yaml.py - -if __name__ == '__main__': - import sys - import spdx.file as spdxfile - from spdx.parsers.yamlparser import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.jsonyamlxmlbuilders import Builder - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - with open(file) as f: - doc, error = p.parse(f) - if not error: - print('doc comment: {0}'.format(doc.comment)) - print('Creators:') - for c in doc.creation_info.creators: - print('\t{0}'.format(c)) - print('Document review information:') - for review in doc.reviews: - print('\tReviewer: {0}'.format(review.reviewer)) - print('\tDate: {0}'.format(review.review_date)) - print('\tComment: {0}'.format(review.comment)) - print('Creation comment: {0}'.format(doc.creation_info.comment)) - print('Package Name: {0}'.format(doc.package.name)) - print('Package Version: {0}'.format(doc.package.version)) - print('Package Download Location: {0}'.format(doc.package.download_location)) - print('Package Homepage: {0}'.format(doc.package.homepage)) - print('Package Checksum: {0}'.format(doc.package.check_sum.value)) - print('Package verification code: {0}'.format(doc.package.verif_code)) - print('Package excluded from verif: {0}'.format(','.join(doc.package.verif_exc_files))) - print('Package license concluded: {0}'.format(doc.package.conc_lics)) - print('Package license declared: {0}'.format(doc.package.license_declared)) - print('Package licenses from files:') - for lics in doc.package.licenses_from_files: - print('\t{0}'.format(lics)) - print('Package Copyright text: {0}'.format(doc.package.cr_text)) - print('Package summary: {0}'.format(doc.package.summary)) - print('Package description: {0}'.format(doc.package.description)) - print('Package Files:') - VALUES = { - spdxfile.FileType.SOURCE: 'SOURCE', - spdxfile.FileType.OTHER: 'OTHER', - spdxfile.FileType.BINARY: 'BINARY', - spdxfile.FileType.ARCHIVE: 'ARCHIVE' - } - for f in doc.files: - print('\tFile name: {0}'.format(f.name)) - print('\tFile type: {0}'.format(VALUES[f.type])) - print('\tFile Checksum: {0}'.format(f.chk_sum.value)) - print('\tFile license concluded: {0}'.format(f.conc_lics)) - print('\tFile license info in file: {0}'.format(','.join( - map(lambda l: l.identifier, f.licenses_in_file)))) - print('\tFile artifact of project name: {0}'.format(','.join(f.artifact_of_project_name))) - - print('Document Extracted licenses:') - for lics in doc.extracted_licenses: - print('\tIdentifier: {0}'.format(lics.identifier)) - print('\tName: {0}'.format(lics.full_name)) - print('Annotations:') - for an in doc.annotations: - print('\tAnnotator: {0}'.format(an.annotator)) - print('\tAnnotation Date: {0}'.format(an.annotation_date)) - print('\tAnnotation Comment: {0}'.format(an.comment)) - print('\tAnnotation Type: {0}'.format(an.annotation_type)) - print('\tAnnotation SPDX Identifier: {0}'.format(an.spdx_id)) - - else: - print('Errors while parsing') diff --git a/examples/pp_rdf.py b/examples/pp_rdf.py deleted file mode 100755 index c46f5574b..000000000 --- a/examples/pp_rdf.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python - -# Parses an RDF file and writes it out pretty-printed. -# Usage: pp_rdf - -if __name__ == '__main__': - import sys - import spdx.file as spdxfile - from spdx.parsers.rdf import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.rdfbuilders import Builder - from spdx.writers.rdf import write_document - infile = sys.argv[1] - outfile = sys.argv[2] - p = Parser(Builder(), StandardLogger()) - with open(infile) as f: - doc, error = p.parse(f) - if not error: - with open(outfile, mode='wb') as out: - write_document(doc, out) - - else: - print('Errors while parsing') diff --git a/examples/pp_tv.py b/examples/pp_tv.py deleted file mode 100755 index 7a44802ec..000000000 --- a/examples/pp_tv.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python - -# Parses a tag/value file and writes it out pretty-printed. -# Usage: pp_tv -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -if __name__ == '__main__': - import sys - import codecs - from spdx.writers.tagvalue import write_document, InvalidDocumentError - from spdx.parsers.tagvalue import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.tagvaluebuilders import Builder - source = sys.argv[1] - target = sys.argv[2] - p = Parser(Builder(), StandardLogger()) - p.build() - with open(source, 'r') as f: - data = f.read() - document, error = p.parse(data) - if not error: - print('Parsing Successful') - with codecs.open(target, mode='w', encoding='utf-8') as out: - try: - write_document(document, out) - except InvalidDocumentError: - print('Document is Invalid') - messages = [] - document.validate(messages) - print('\n'.join(messages)) - else: - print('Errors encountered while parsing') diff --git a/examples/rdf_to_json.py b/examples/rdf_to_json.py deleted file mode 100644 index 104aeafb7..000000000 --- a/examples/rdf_to_json.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python - -if __name__ == '__main__': - import sys - from spdx.parsers.rdf import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.rdfbuilders import Builder - from spdx.writers.json import write_document - - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - with open(file) as f: - document, error = p.parse(f) - - if not error: - with open('json_from_rdf_example.json', 'w') as out: - write_document(document, out) - else: - print('Errors encountered while parsing') diff --git a/examples/rdf_to_tv.py b/examples/rdf_to_tv.py deleted file mode 100755 index b6371f13d..000000000 --- a/examples/rdf_to_tv.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python - -# Converts an RDF file to tag/value format. -# Usage: rdf_to_tv -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -if __name__ == '__main__': - import sys - import codecs - from spdx.parsers.rdf import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.rdfbuilders import Builder - from spdx.writers.tagvalue import write_document, InvalidDocumentError - infile_name = sys.argv[1] - outfile_name = sys.argv[2] - rdfparser = Parser(Builder(), StandardLogger()) - with open(infile_name) as infile: - document, error = rdfparser.parse(infile) - if not error: - # print(map(lambda c: c.name, document.creation_info.creators)) - print('Parsing Successful') - with codecs.open(outfile_name, mode='w', encoding='utf-8') as outfile: - try: - write_document(document, outfile) - except InvalidDocumentError: - # Note document is valid if error is False - print('Document is Invalid') - else: - print('Errors encountered while parsing RDF file.') - messages = [] - document.validate(messages) - print('\n'.join(messages)) diff --git a/examples/rdf_to_xml.py b/examples/rdf_to_xml.py deleted file mode 100644 index c1b7ab614..000000000 --- a/examples/rdf_to_xml.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python - -if __name__ == '__main__': - import sys - from spdx.parsers.rdf import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.rdfbuilders import Builder - from spdx.writers.xml import write_document - - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - with open(file) as f: - document, error = p.parse(f) - - if not error: - with open('xml_from_rdf_example.xml', 'w') as out: - write_document(document, out) - else: - print('Errors encountered while parsing') diff --git a/examples/rdf_to_yaml.py b/examples/rdf_to_yaml.py deleted file mode 100644 index 26400d634..000000000 --- a/examples/rdf_to_yaml.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python - -if __name__ == '__main__': - import sys - from spdx.parsers.rdf import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.rdfbuilders import Builder - from spdx.writers.yaml import write_document - - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - with open(file) as f: - document, error = p.parse(f) - - if not error: - with open('yaml_from_rdf_example.yml', 'w') as out: - write_document(document, out) - else: - print('Errors encountered while parsing') diff --git a/examples/spdx2_convert_format.py b/examples/spdx2_convert_format.py new file mode 100644 index 000000000..63cb4a67a --- /dev/null +++ b/examples/spdx2_convert_format.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from os import path + +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.writer.write_anything import write_file +from spdx_tools.spdx.parser.parse_anything import parse_file + +# This example demonstrates how to load an existing SPDX2 file and convert it to a different SPDX2 format + +# Provide a path to the input file in the originating format +input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx") +# Parse the original input file (format is deduced automatically from the file extension) +document: Document = parse_file(input_path) +# Write to a different file format (e.g. XML, format is deduced automatically from the file extension) +write_file(document, "converted_format.xml") diff --git a/examples/spdx2_convert_to_spdx3.py b/examples/spdx2_convert_to_spdx3.py new file mode 100644 index 000000000..ebbbbc7c7 --- /dev/null +++ b/examples/spdx2_convert_to_spdx3.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from os import path + +from spdx_tools.spdx.model import Document +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx_tools.spdx.parser.parse_anything import parse_file + +# This example demonstrates how to load an existing SPDX2 file and convert it to the SPDX3 format + +# Provide a path to the input file +input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx") +# Parse the original SPDX2 input file +spdx2_document: Document = parse_file(input_path) +# Convert original document to an SPDX3 payload +spdx3_payload: Payload = bump_spdx_document(spdx2_document) +# Write SPDX3 payload in json-ld format +write_payload(spdx3_payload, "spdx2_to_3") diff --git a/examples/spdx2_document_from_scratch.py b/examples/spdx2_document_from_scratch.py new file mode 100644 index 000000000..bc92175a8 --- /dev/null +++ b/examples/spdx2_document_from_scratch.py @@ -0,0 +1,145 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import logging +from datetime import datetime +from typing import List + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, + CreationInfo, + Document, + ExternalPackageRef, + ExternalPackageRefCategory, + File, + FileType, + Package, + PackagePurpose, + PackageVerificationCode, + Relationship, + RelationshipType, +) +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.writer.write_anything import write_file + +# This example shows how to use the spdx-tools to create an SPDX document from scratch, +# validate it and write it to a file. + +# First up, we need general information about the creation of the document, summarised by the CreationInfo class. +creation_info = CreationInfo( + spdx_version="SPDX-2.3", + spdx_id="SPDXRef-DOCUMENT", + name="document name", + data_license="CC0-1.0", + document_namespace="https://some.namespace", + creators=[Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com")], + created=datetime(2022, 1, 1), +) + +# creation_info is the only required property of the Document class (have a look there!), the rest are optional lists. +# So, we are set up to create a new document instance. +document = Document(creation_info) + +# The document currently does not describe anything. Let's create a package that we can add to it. +# The Package class has quite a few properties (have a look there!), +# but only name, spdx_id and download_location are mandatory in SPDX v2.3. +package = Package( + name="package name", + spdx_id="SPDXRef-Package", + download_location="https://download.com", + version="2.2.1", + file_name="./foo.bar", + supplier=Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com"), + originator=Actor(ActorType.ORGANIZATION, "some organization", "contact@example.com"), + files_analyzed=True, + verification_code=PackageVerificationCode( + value="d6a770ba38583ed4bb4525bd96e50461655d2758", excluded_files=["./some.file"] + ), + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + license_concluded=spdx_licensing.parse("GPL-2.0-only OR MIT"), + license_info_from_files=[spdx_licensing.parse("GPL-2.0-only"), spdx_licensing.parse("MIT")], + license_declared=spdx_licensing.parse("GPL-2.0-only AND MIT"), + license_comment="license comment", + copyright_text="Copyright 2022 Jane Doe", + description="package description", + attribution_texts=["package attribution"], + primary_package_purpose=PackagePurpose.LIBRARY, + release_date=datetime(2015, 1, 1), + external_references=[ + ExternalPackageRef( + category=ExternalPackageRefCategory.OTHER, + reference_type="http://reference.type", + locator="reference/locator", + comment="external reference comment", + ) + ], +) + +# Now that we have a package defined, we can add it to the document's package property. +document.packages = [package] + +# A DESCRIBES relationship asserts that the document indeed describes the package. +describes_relationship = Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package") +document.relationships = [describes_relationship] + +# Let's add two files. Have a look at the file class for all possible properties a file can have. +file1 = File( + name="./package/file1.py", + spdx_id="SPDXRef-File1", + file_types=[FileType.SOURCE], + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + license_concluded=spdx_licensing.parse("MIT"), + license_info_in_file=[spdx_licensing.parse("MIT")], + copyright_text="Copyright 2022 Jane Doe", +) +file2 = File( + name="./package/file2.py", + spdx_id="SPDXRef-File2", + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"), + ], + license_concluded=spdx_licensing.parse("GPL-2.0-only"), +) + +# Assuming the package contains those two files, we create two CONTAINS relationships. +contains_relationship1 = Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File1") +contains_relationship2 = Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File2") + +# This library uses run-time type checks when assigning properties. +# Because in-place alterations like .append() circumvent these checks, we don't use them here. +document.relationships += [contains_relationship1, contains_relationship2] +document.files += [file1, file2] + +# We now have created a document with basic creation information, describing a package that contains two files. +# You can also add Annotations, Snippets and ExtractedLicensingInfo to the document in an analogous manner to the above. +# Have a look at their respective classes if you are unsure about their properties. + + +# This library provides comprehensive validation against the SPDX specification. +# Note that details of the validation depend on the SPDX version of the document. +validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + +# You can have a look at each entry's message and context (like spdx_id, parent_id, full_element) +# which will help you pinpoint the location of the invalidity. +for message in validation_messages: + logging.warning(message.validation_message) + logging.warning(message.context) + +# If the document is valid, validation_messages will be empty. +assert validation_messages == [] + +# Finally, we can serialize the document to any of the five supported formats. +# Using the write_file() method from the write_anything module, +# the format will be determined by the file ending: .spdx (tag-value), .json, .xml, .yaml. or .rdf (or .rdf.xml) +write_file(document, "my_spdx_document.spdx.json") diff --git a/examples/spdx2_generate_graph.py b/examples/spdx2_generate_graph.py new file mode 100644 index 000000000..dad7dcfce --- /dev/null +++ b/examples/spdx2_generate_graph.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from os import path + +from spdx_tools.spdx.graph_generation import export_graph_from_document +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.parser.parse_anything import parse_file + +# This example demonstrates how to generate a relationship graph for an SPDX2 document + +# Provide a path to the input file +input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXJSONExample-v2.3.spdx.json") +# Parse the file +document: Document = parse_file(input_path) +# Generate the graph (note: you need to have installed the optional dependencies networkx and pygraphviz) +export_graph_from_document(document, "graph.png") diff --git a/examples/spdx2_parse_file.py b/examples/spdx2_parse_file.py new file mode 100644 index 000000000..a6564e127 --- /dev/null +++ b/examples/spdx2_parse_file.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import logging +from os import path + +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.parse_anything import parse_file + +# This example demonstrates how to parse an existing spdx file. + +# Provide a path to the input file +input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx") +try: + # Try to parse the input file. If successful, returns a Document, otherwise raises an SPDXParsingError + document: Document = parse_file(input_path) +except SPDXParsingError: + logging.exception("Failed to parse spdx file") + +# We can now access attributes from the parsed document +print(f"Parsed document name: {document.creation_info.name}") +creators_as_str = ", ".join([creator.to_serialized_string() for creator in document.creation_info.creators]) +print(f"Created on {document.creation_info.created} by {creators_as_str}") diff --git a/examples/tv_to_json.py b/examples/tv_to_json.py deleted file mode 100644 index a6b974702..000000000 --- a/examples/tv_to_json.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python - -if __name__ == '__main__': - import sys - from spdx.parsers.tagvalue import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.tagvaluebuilders import Builder - from spdx.writers.json import write_document - - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - p.build() - with open(file) as f: - data = f.read() - document, error = p.parse(data) - if not error: - with open('json_from_tv_example.json', 'w') as out: - write_document(document, out) - else: - print('Errors encountered while parsing') diff --git a/examples/tv_to_rdf.py b/examples/tv_to_rdf.py deleted file mode 100644 index 2b47c8651..000000000 --- a/examples/tv_to_rdf.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python - -""" -Converts an tag/value file to RDF format. -Usage: tv_to_rdf -""" -import sys -import codecs -from spdx.parsers.tagvalue import Parser -from spdx.parsers.loggers import StandardLogger -from spdx.parsers.tagvaluebuilders import Builder -from spdx.writers.rdf import write_document, InvalidDocumentError - -def convert(infile_name, outfile_name): - tagvalueparser = Parser(Builder(), StandardLogger()) - tagvalueparser.build() - with open(infile_name) as infile: - data = infile.read() - document, error = tagvalueparser.parse(data) - if not error: - # print(map(lambda c: c.name, document.creation_info.creators)) - print('Parsing Successful') - with open(outfile_name, mode='w') as out: - write_document(document,out,validate = True) - else: - print('Errors encountered while parsing tag value file.') - messages = [] - document.validate(messages) - print('\n'.join(messages)) - - -if __name__ == '__main__': - infile_name = sys.argv[1] - outfile_name = sys.argv[2] - convert(infile_name, outfile_name) \ No newline at end of file diff --git a/examples/tv_to_xml.py b/examples/tv_to_xml.py deleted file mode 100644 index 79c7c1af9..000000000 --- a/examples/tv_to_xml.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python - -if __name__ == '__main__': - import sys - from spdx.parsers.tagvalue import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.tagvaluebuilders import Builder - from spdx.writers.xml import write_document - - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - p.build() - with open(file) as f: - data = f.read() - document, error = p.parse(data) - if not error: - with open('xml_from_tv_example.xml', 'w') as out: - write_document(document, out) - else: - print('Errors encountered while parsing') diff --git a/examples/tv_to_yaml.py b/examples/tv_to_yaml.py deleted file mode 100644 index e0b3ac0ba..000000000 --- a/examples/tv_to_yaml.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python - -if __name__ == '__main__': - import sys - from spdx.parsers.tagvalue import Parser - from spdx.parsers.loggers import StandardLogger - from spdx.parsers.tagvaluebuilders import Builder - from spdx.writers.yaml import write_document - - file = sys.argv[1] - p = Parser(Builder(), StandardLogger()) - p.build() - with open(file) as f: - data = f.read() - document, error = p.parse(data) - if not error: - with open('yaml_from_tv_example.yaml', 'w') as out: - write_document(document, out) - else: - print('Errors encountered while parsing') diff --git a/examples/write_tv.py b/examples/write_tv.py deleted file mode 100755 index fc04fbe57..000000000 --- a/examples/write_tv.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python - -# Writes a new tag/value file from scratch. -# Usage: write_tv -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -if __name__ == '__main__': - import sys - import codecs - from spdx.writers.tagvalue import write_document, InvalidDocumentError - from spdx.document import Document, License, LicenseConjunction, ExtractedLicense - from spdx.version import Version - from spdx.creationinfo import Person - from spdx.review import Review - from spdx.package import Package - from spdx.file import File, FileType - from spdx.checksum import Algorithm - from spdx.utils import SPDXNone, NoAssert, UnKnown - - doc = Document() - doc.version = Version(1, 2) - doc.comment = 'Example Document' - doc.data_license = License.from_identifier('CC0-1.0') - doc.creation_info.add_creator(Person('Alice', 'alice@example.com')) - doc.creation_info.set_created_now() - review = Review(Person('Joe', None)) - review.set_review_date_now() - review.comment = 'Joe reviewed this document' - doc.add_review(review) - # File - testfile1 = File('TestFile1') - testfile1.type = FileType.BINARY - testfile1.comment = 'This is a test file.' - testfile1.chk_sum = Algorithm('SHA1', 'c537c5d99eca5333f23491d47ededd083fefb7ad') - testfile1.conc_lics = License.from_identifier('BSD-2-Clause') - testfile1.add_lics(License.from_identifier('BSD-2-Clause')) - testfile1.copyright = SPDXNone() - testfile1.add_artifact('name', 'TagWriteTest') - testfile1.add_artifact('home', UnKnown()) - testfile1.add_artifact('uri', 'http://tagwritetest.test') - - testfile2 = File('TestFile2') - testfile2.type = FileType.SOURCE - testfile2.comment = 'This is a test file.' - testfile2.chk_sum = Algorithm('SHA1', 'bb154f28d1cf0646ae21bb0bec6c669a2b90e113') - testfile2.conc_lics = License.from_identifier('Apache-2.0') - testfile2.add_lics(License.from_identifier('Apache-2.0')) - testfile2.copyright = NoAssert() - - - # Package - package = Package() - package.name = 'TagWriteTest' - package.version = '1.0' - package.file_name = 'twt.jar' - package.download_location = 'http://www.tagwritetest.test/download' - package.homepage = SPDXNone() - package.verif_code = '4e3211c67a2d28fced849ee1bb76e7391b93feba' - license_set = LicenseConjunction(License.from_identifier('Apache-2.0'), - License.from_identifier('BSD-2-Clause')) - package.conc_lics = license_set - package.license_declared = license_set - package.add_lics_from_file(License.from_identifier('Apache-2.0')) - package.add_lics_from_file(License.from_identifier('BSD-2-Clause')) - package.cr_text = NoAssert() - package.summary = 'Simple package.' - package.description = 'Really simple package.' - package.add_file(testfile1) - package.add_file(testfile2) - - doc.package = package - - # An extracted license - - lic = ExtractedLicense('LicenseRef-1') - lic.text = 'Some non legal legal text..' - doc.add_extr_lic(lic) - - file = sys.argv[1] - with codecs.open(file, mode='w', encoding='utf-8') as out: - try: - write_document(doc, out) - except InvalidDocumentError: - print('Document is Invalid') - messages = [] - doc.validate(messages) - print('\n'.join(messages)) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..aff57e36b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,68 @@ +[build-system] +requires = ["setuptools>=61.2", "setuptools_scm[toml]>=3.4.3"] +build-backend = "setuptools.build_meta" + +[project] +name = "spdx-tools" +authors = [{ name = "Ahmed H. Ismail", email = "ahm3d.hisham@gmail.com" }] +maintainers = [ + { name = "Philippe Ombredanne", email = "pombredanne@gmail.com" }, + { name = "SPDX group at the Linux Foundation and others" }, +] +license = { text = "Apache-2.0" } +description = "SPDX parser and tools." +readme = "README.md" +classifiers = [ + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", +] +urls = { Homepage = "https://github.com/spdx/tools-python" } +requires-python = ">=3.7" +dependencies = ["click", "pyyaml", "xmltodict", "rdflib", "beartype", "uritools", "license_expression", "ply", "semantic_version"] +dynamic = ["version"] + +[project.optional-dependencies] +test = ["pytest", "pyshacl", "tzdata"] +code_style = ["isort", "black", "flake8"] +graph_generation = ["pygraphviz", "networkx"] +development = ["black", "flake8", "isort", "networkx", "pytest"] + +[project.scripts] +pyspdxtools = "spdx_tools.spdx.clitools.pyspdxtools:main" +pyspdxtools3 = "spdx_tools.spdx3.clitools.pyspdxtools3:main" + +[tool.setuptools] +zip-safe = false # because of the uses of __file__: https://github.com/spdx/tools-python/issues/257 +include-package-data = true + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.setuptools.package-data] +"*" = ["py.typed"] + +# the default git describe resolves to the tag `python3.6` because the current release tag is not on main +# by adding "v" the command resolves to the alpha release of 0.7.0 which leads to the desired name spdx-tools-0.7.0 +[tool.setuptools_scm] +git_describe_command = ["git", "describe", "--dirty", "--tags", "--long", "--match", "v[0-9]*"] + +[tool.aliases] +release = "clean --all sdist --formats=gztar bdist_wheel" + +[tool.black] +line-length = 119 +include = "(^/src/.*.py|^/tests/.*.py)" + +[tool.isort] +profile = "black" +line_length = 119 +skip = ["__init__.py"] + +[tool.pytest.ini_options] +norecursedirs = [] # overwrite the default to not skip tests/build folder which is needed in spdx3 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 8ba2b06da..000000000 --- a/setup.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[metadata] -license_file = LICENSE - -[bdist_wheel] -universal=1 - -[aliases] -release = clean --all sdist --formats=gztar bdist_wheel diff --git a/setup.py b/setup.py index 58c66cae7..c3ba8ba72 100755 --- a/setup.py +++ b/setup.py @@ -1,55 +1,6 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function +#!/usr/bin/python from setuptools import setup -import unittest - -def test_suite(): - return unittest.TestLoader().discover('tests', pattern='test_*.py') - -with open('README.md', 'r') as fh: - long_description = fh.read() - -setup( - name='spdx-tools', - version='0.6.1', - description='SPDX parser and tools.', - long_description=long_description, - long_description_content_type='text/markdown', - packages=[ - 'spdx', - 'spdx.parsers', - 'spdx.parsers.lexers', - 'spdx.writers', - ], - include_package_data=True, - zip_safe=False, - test_suite='setup.test_suite', - install_requires=[ - 'ply', - 'rdflib', - 'six', - 'pyyaml', - 'xmltodict', - ], - entry_points={ - 'console_scripts': [ - 'spdx-tv2rdf = spdx.tv_to_rdf:main', - ], - }, - - author='Ahmed H. Ismail', - author_email='ahm3d.hisham@gmail.com', - maintainer='Philippe Ombredanne, SPDX group at the Linux Foundation and others', - maintainer_email='pombredanne@gmail.com', - url='https://github.com/spdx/tools-python', - license='Apache-2.0', - classifiers=[ - 'Intended Audience :: Developers', - 'License :: OSI Approved :: Apache Software License', - 'Programming Language :: Python :: 2.7' - ] -) +if __name__ == "__main__": + setup() diff --git a/spdx/__init__.py b/spdx/__init__.py deleted file mode 100644 index de40ea7ca..000000000 --- a/spdx/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__import__('pkg_resources').declare_namespace(__name__) diff --git a/spdx/annotation.py b/spdx/annotation.py deleted file mode 100644 index ee4e9405f..000000000 --- a/spdx/annotation.py +++ /dev/null @@ -1,110 +0,0 @@ - -# Copyright (c) 2018 Yash M. Nisar -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from datetime import datetime -from functools import total_ordering - -from spdx.utils import datetime_iso_format - - -@total_ordering -class Annotation(object): - - """ - Document annotation information. - Fields: - - annotator: Person, Organization or tool that has commented on a file, - package, or the entire document. Conditional (Mandatory, one), if there - is an Annotation. - - annotation_date: To identify when the comment was made. Conditional - (Mandatory, one), if there is an Annotation. Type: datetime. - - comment: Annotation comment. Conditional (Mandatory, one), if there is - an Annotation. Type: str. - - annotation_type: Annotation type. Conditional (Mandatory, one), if there is an - Annotation. Type: str. - - spdx_id: Uniquely identify the element in an SPDX document which is being - referenced. Conditional (Mandatory, one), if there is an Annotation. - Type: str. - """ - - def __init__(self, annotator=None, annotation_date=None, comment=None, - annotation_type=None, spdx_id=None): - self.annotator = annotator - self.annotation_date = annotation_date - self.comment = comment - self.annotation_type = annotation_type - self.spdx_id = spdx_id - - def __eq__(self, other): - return ( - isinstance(other, Annotation) and self.annotator == other.annotator - and self.annotation_date == other.annotation_date - and self.comment == other.comment - ) - - def __lt__(self, other): - return ( - (self.annotator, self.annotation_date, self.comment) < - (other.annotator, other.annotation_date, other.comment,) - ) - - def set_annotation_date_now(self): - self.annotation_date = datetime.utcnow() - - @property - def annotation_date_iso_format(self): - return datetime_iso_format(self.annotation_date) - - @property - def has_comment(self): - return self.comment is not None - - def validate(self, messages): - """Returns True if all the fields are valid. - Appends any error messages to messages parameter. - """ - messages = self.validate_annotator(messages) - messages = self.validate_annotation_date(messages) - messages = self.validate_annotation_type(messages) - messages = self.validate_spdx_id(messages) - - return messages - - def validate_annotator(self, messages): - if self.annotator is None: - messages = messages + ['Annotation missing annotator.'] - - return messages - - def validate_annotation_date(self, messages): - if self.annotation_date is None: - messages = messages + ['Annotation missing annotation date.'] - - return messages - - def validate_annotation_type(self, messages): - if self.annotation_type is None: - messages = messages + ['Annotation missing annotation type.'] - - return messages - - def validate_spdx_id(self, messages): - if self.spdx_id is None: - messages = messages + [ - 'Annotation missing SPDX Identifier Reference.' - ] - - return messages diff --git a/spdx/checksum.py b/spdx/checksum.py deleted file mode 100644 index 3c976fb71..000000000 --- a/spdx/checksum.py +++ /dev/null @@ -1,25 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - - -class Algorithm(object): - """Generic checksum algorithm.""" - def __init__(self, identifier, value): - self.identifier = identifier - self.value = value - - def to_tv(self): - return "{0}: {1}".format(self.identifier, self.value) diff --git a/spdx/config.py b/spdx/config.py deleted file mode 100644 index 87d2ef8c6..000000000 --- a/spdx/config.py +++ /dev/null @@ -1,74 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import codecs -import json -import os - -from spdx.version import Version - - -_base_dir = os.path.dirname(__file__) -_licenses = os.path.join(_base_dir, 'licenses.json') -_exceptions = os.path.join(_base_dir, 'exceptions.json') - - -def _load_list(file_name, object_type='licenses', id_attribute='licenseId'): - """ - Return a list version tuple and a mapping of licenses - name->id and id->name loaded from a JSON file - from https://github.com/spdx/license-list-data - """ - licenses_map = {} - with codecs.open(file_name, 'rb', encoding='utf-8') as lics: - licenses = json.load(lics) - version = tuple(licenses['licenseListVersion'].split('.')) - for lic in licenses[object_type]: - if lic.get('isDeprecatedLicenseId'): - continue - name = lic['name'] - identifier = lic[id_attribute] - licenses_map[name] = identifier - licenses_map[identifier] = name - return version, licenses_map - - -def load_license_list(file_name): - """ - Return the licenses list version tuple and a mapping of licenses - name->id and id->name loaded from a JSON file - from https://github.com/spdx/license-list-data - """ - return _load_list(file_name, object_type='licenses', id_attribute='licenseId') - - -def load_exception_list(file_name): - """ - Return the exceptions list version tuple and a mapping of exceptions - name->id and id->name loaded from a JSON file - from https://github.com/spdx/license-list-data - """ - return _load_list(file_name, object_type='exceptions', id_attribute='licenseExceptionId') - - -(_lmajor, _lminor), LICENSE_MAP = load_license_list(_licenses) -LICENSE_LIST_VERSION = Version(major=_lmajor, minor=_lminor) - -(_emajor, _eminor), EXCEPTION_MAP = load_exception_list(_exceptions) -EXCEPTION_LIST_VERSION = Version(major=_emajor, minor=_eminor) - -assert LICENSE_LIST_VERSION == EXCEPTION_LIST_VERSION -del _emajor, _eminor, EXCEPTION_LIST_VERSION diff --git a/spdx/creationinfo.py b/spdx/creationinfo.py deleted file mode 100644 index c29b6cf11..000000000 --- a/spdx/creationinfo.py +++ /dev/null @@ -1,175 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from datetime import datetime -from functools import total_ordering - -from spdx import config -from spdx import utils - - -@total_ordering -class Creator(object): - """ - Creator enity. - Fields: - - name: creator's name/identifier - """ - def __init__(self, name): - self.name = name - - # FIXME: do not overrride eq and not hash - def __eq__(self, other): - return isinstance(other, Creator) and self.name == other.name - - def __lt__(self, other): - return isinstance(other, Creator) and self.name < other.name - - -@total_ordering -class Organization(Creator): - """ - Organization entity. - Fields: - - name: Org's name/identifier. Mandatory. Type: str. - - email: Org's email address. Optional. Type: str. - """ - - def __init__(self, name, email): - super(Organization, self).__init__(name) - self.email = email - - # FIXME: do not overrride eq and not hash - def __eq__(self, other): - return isinstance(other, Organization) and (self.name, self.email) == (other.name, other.email) - - def __lt__(self, other): - return isinstance(other, Organization) and (self.name, self.email) < (other.name, other.email) - - def to_value(self): - if self.email: - return 'Organization: {0} ({1})'.format(self.name, self.email) - else: - return 'Organization: {0}'.format(self.name) - - def __str__(self): - return self.to_value() - - -@total_ordering -class Person(Creator): - """ - Person entity. - Fields: - - name: person's name/identifier. Mandatory. Type: str. - - email: person's email address. Optional. Type: str. - """ - - def __init__(self, name, email): - super(Person, self).__init__(name) - self.email = email - - # FIXME: do not overrride eq and not hash - def __eq__(self, other): - return isinstance(other, Person) and (self.name, self.email) == (other.name, other.email) - - def __lt__(self, other): - return isinstance(other, Person) and (self.name, self.email) < (other.name, other.email) - - def to_value(self): - if self.email is not None: - return 'Person: {0} ({1})'.format(self.name, self.email) - else: - return 'Person: {0}'.format(self.name) - - def __str__(self): - return self.to_value() - - -class Tool(Creator): - """ - Tool entity. - Fields: - - name: tool identifier, with version. Type: str. - """ - - def __init__(self, name): - super(Tool, self).__init__(name) - - def to_value(self): - return 'Tool: {0}'.format(self.name) - - def __str__(self): - return self.to_value() - - -class CreationInfo(object): - """ - Represent a document creation info. - Fields: - - creators: List of creators. At least one required. - Type: Creator. - - comment: Creation comment, optional. Type: str. - - license_list_version: version of SPDX license used in creation of SPDX - document. One, optional. Type: spdx.version.Version - - created: Creation date. Mandatory one. Type: datetime. - """ - - def __init__(self, created=None, comment=None, - license_list_version=config.LICENSE_LIST_VERSION): - self.creators = [] - self.created = created - self.comment = comment - self.license_list_version = license_list_version - - def add_creator(self, creator): - self.creators.append(creator) - - def remove_creator(self, creator): - self.creators.remove(creator) - - def set_created_now(self): - self.created = datetime.utcnow() - - @property - def created_iso_format(self): - return utils.datetime_iso_format(self.created) - - @property - def has_comment(self): - return self.comment is not None - - def validate(self, messages): - """Returns True if the fields are valid according to the SPDX standard. - Appends user friendly messages to the messages parameter. - """ - messages = self.validate_creators(messages) - messages = self.validate_created(messages) - - return messages - - def validate_creators(self, messages): - if len(self.creators) == 0: - messages = messages + [ - 'No creators defined, must have at least one.'] - - return messages - - def validate_created(self, messages): - if self.created is None: - messages = messages + ['Creation info missing created date.'] - - return messages diff --git a/spdx/document.py b/spdx/document.py deleted file mode 100644 index 62708999f..000000000 --- a/spdx/document.py +++ /dev/null @@ -1,429 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from functools import total_ordering - -from spdx import config - - -@total_ordering -class ExternalDocumentRef(object): - """ - External Document References entity that contains the following fields : - - external_document_id: A unique string containing letters, numbers, '.', - '-' or '+'. - - spdx_document_uri: The unique ID of the SPDX document being referenced. - - check_sum: The checksum of the referenced SPDX document. - """ - - def __init__(self, external_document_id=None, spdx_document_uri=None, - check_sum=None): - self.external_document_id = external_document_id - self.spdx_document_uri = spdx_document_uri - self.check_sum = check_sum - - def __eq__(self, other): - return ( - isinstance(other, ExternalDocumentRef) - and self.external_document_id == other.external_document_id - and self.spdx_document_uri == other.spdx_document_uri - and self.check_sum == other.check_sum - ) - - def __lt__(self, other): - return ( - (self.external_document_id, self.spdx_document_uri, - self.check_sum) < - (other.external_document_id, other.spdx_document_uri, - other.check_sum,) - ) - - def validate(self, messages): - """ - Validate all fields of the ExternalDocumentRef class and update the - messages list with user friendly error messages for display. - """ - messages = self.validate_ext_doc_id(messages) - messages = self.validate_spdx_doc_uri(messages) - messages = self.validate_checksum(messages) - - return messages - - def validate_ext_doc_id(self, messages): - if not self.external_document_id: - messages = messages + [ - 'ExternalDocumentRef has no External Document ID.' - ] - - return messages - - def validate_spdx_doc_uri(self, messages): - if not self.spdx_document_uri: - messages = messages + [ - 'ExternalDocumentRef has no SPDX Document URI.' - ] - - return messages - - def validate_checksum(self, messages): - if not self.check_sum: - messages = messages + ['ExternalDocumentRef has no Checksum.'] - - return messages - - -def _add_parens(required, text): - """ - Add parens around a license expression if `required` is True, otherwise - return `text` unmodified. - """ - return '({})'.format(text) if required else text - - -@total_ordering -class License(object): - def __init__(self, full_name, identifier): - self._full_name = full_name - self._identifier = identifier - - @classmethod - def from_identifier(cls, identifier): - """If identifier exists in config.LICENSE_MAP - the full_name is retrieved from it. Otherwise - the full_name is the same as the identifier. - """ - if identifier in config.LICENSE_MAP.keys(): - return cls(config.LICENSE_MAP[identifier], identifier) - else: - return cls(identifier, identifier) - - @classmethod - def from_full_name(cls, full_name): - """ - Returna new License for a full_name. If the full_name exists in - config.LICENSE_MAP the identifier is retrieved from it. - Otherwise the identifier is the same as the full_name. - """ - if full_name in config.LICENSE_MAP.keys(): - return cls(full_name, config.LICENSE_MAP[full_name]) - else: - return cls(full_name, full_name) - - @property - def url(self): - return "http://spdx.org/licenses/{0}".format(self.identifier) - - @property - def full_name(self): - return self._full_name - - @full_name.setter - def full_name(self, value): - self._full_name = value - - @property - def identifier(self): - return self._identifier - - def __eq__(self, other): - return ( - isinstance(other, License) - and self.identifier == other.identifier - and self.full_name == other.full_name) - - def __lt__(self, other): - return isinstance(other, License) and self.identifier < other.identifier - - def __str__(self): - return self.identifier - - def __hash__(self): - return self.identifier.__hash__() - - -class LicenseConjunction(License): - """ - A conjunction of two licenses. - """ - - def __init__(self, license_1, license_2): - self.license_1 = license_1 - self.license_2 = license_2 - super(LicenseConjunction, self).__init__(self.full_name, self.identifier) - - @property - def full_name(self): - license_1_complex = type(self.license_1) == LicenseDisjunction - license_2_complex = type(self.license_2) == LicenseDisjunction - - return '{0} AND {1}'.format( - _add_parens(license_1_complex, self.license_1.full_name), - _add_parens(license_2_complex, self.license_2.full_name)) - - @property - def identifier(self): - license_1_complex = type(self.license_1) == LicenseDisjunction - license_2_complex = type(self.license_2) == LicenseDisjunction - - return '{0} AND {1}'.format( - _add_parens(license_1_complex, self.license_1.identifier), - _add_parens(license_2_complex, self.license_2.identifier)) - - -class LicenseDisjunction(License): - """ - A disjunction of two licenses. - """ - - def __init__(self, license_1, license_2): - self.license_1 = license_1 - self.license_2 = license_2 - super(LicenseDisjunction, self).__init__(self.full_name, self.identifier) - - @property - def full_name(self): - license_1_complex = type(self.license_1) == LicenseConjunction - license_2_complex = type(self.license_2) == LicenseConjunction - - return '{0} OR {1}'.format( - _add_parens(license_1_complex, self.license_1.full_name), - _add_parens(license_2_complex, self.license_2.full_name)) - - @property - def identifier(self): - license_1_complex = type(self.license_1) == LicenseConjunction - license_2_complex = type(self.license_2) == LicenseConjunction - - return '{0} OR {1}'.format( - _add_parens(license_1_complex, self.license_1.identifier), - _add_parens(license_2_complex, self.license_2.identifier)) - - -@total_ordering -class ExtractedLicense(License): - """ - Represent an ExtractedLicense with its additional attributes: - - text: Extracted text, str. Mandatory. - - cross_ref: list of cross references. - - comment: license comment, str. - - full_name: license name. str or utils.NoAssert. - """ - def __init__(self, identifier): - super(ExtractedLicense, self).__init__(None, identifier) - self.text = None - self.cross_ref = [] - self.comment = None - - def __eq__(self, other): - return ( - isinstance(other, ExtractedLicense) - and self.identifier == other.identifier - and self.full_name == other.full_name) - - def __lt__(self, other): - return isinstance(other, ExtractedLicense) and self.identifier < other.identifier - - def add_xref(self, ref): - self.cross_ref.append(ref) - - def validate(self, messages): - if self.text is None: - messages = messages + ['ExtractedLicense text can not be None'] - - return messages - - -class Document(object): - """ - Represent an SPDX document with these fields: - - version: Spec version. Mandatory, one - Type: Version. - - data_license: SPDX-Metadata license. Mandatory, one. Type: License. - - name: Name of the document. Mandatory, one. Type: str. - - spdx_id: SPDX Identifier for the document to refer to itself in - relationship to other elements. Mandatory, one. Type: str. - - ext_document_references: External SPDX documents referenced within the - given SPDX document. Optional, one or many. Type: ExternalDocumentRef - - comment: Comments on the SPDX file, optional one. Type: str - - namespace: SPDX document specific namespace. Mandatory, one. Type: str - - creation_info: SPDX file creation info. Mandatory, one. Type: CreationInfo - - package: Package described by this document. Mandatory, one. Type: Package - - extracted_licenses: List of licenses extracted that are not part of the - SPDX license list. Optional, many. Type: ExtractedLicense. - - reviews: SPDX document review information, Optional zero or more. - Type: Review. - - annotations: SPDX document annotation information, Optional zero or more. - Type: Annotation. - - snippet: Snippet information. Optional zero or more. Type: Snippet. - """ - - def __init__(self, version=None, data_license=None, name=None, spdx_id=None, - namespace=None, comment=None, package=None): - # avoid recursive impor - from spdx.creationinfo import CreationInfo - self.version = version - self.data_license = data_license - self.name = name - self.spdx_id = spdx_id - self.ext_document_references = [] - self.comment = comment - self.namespace = namespace - self.creation_info = CreationInfo() - self.package = package - self.extracted_licenses = [] - self.reviews = [] - self.annotations = [] - self.snippet = [] - - def add_review(self, review): - self.reviews.append(review) - - def add_annotation(self, annotation): - self.annotations.append(annotation) - - def add_extr_lic(self, lic): - self.extracted_licenses.append(lic) - - def add_ext_document_reference(self, ext_doc_ref): - self.ext_document_references.append(ext_doc_ref) - - def add_snippet(self, snip): - self.snippet.append(snip) - - @property - def files(self): - return self.package.files - - @files.setter - def files(self, value): - self.package.files = value - - @property - def has_comment(self): - return self.comment is not None - - def validate(self, messages): - """ - Validate all fields of the document and update the - messages list with user friendly error messages for display. - """ - messages = self.validate_version(messages) - messages = self.validate_data_lics(messages) - messages = self.validate_name(messages) - messages = self.validate_spdx_id(messages) - messages = self.validate_namespace(messages) - messages = self.validate_ext_document_references(messages) - messages = self.validate_creation_info(messages) - messages = self.validate_package(messages) - messages = self.validate_extracted_licenses(messages) - messages = self.validate_reviews(messages) - messages = self.validate_snippet(messages) - - return messages - - def validate_version(self, messages): - if self.version is None: - messages = messages + ['Document has no version.'] - - return messages - - def validate_data_lics(self, messages): - if self.data_license is None: - messages = messages + ['Document has no data license.'] - else: - # FIXME: REALLY? what if someone wants to use something else? - if self.data_license.identifier != 'CC0-1.0': - messages = messages + ['Document data license must be CC0-1.0.'] - - return messages - - def validate_name(self, messages): - if self.name is None: - messages = messages + ['Document has no name.'] - - return messages - - def validate_namespace(self, messages): - if self.namespace is None: - messages = messages + ['Document has no namespace.'] - - return messages - - def validate_spdx_id(self, messages): - if self.spdx_id is None: - messages = messages + ['Document has no SPDX Identifier.'] - else: - if not self.spdx_id.endswith('SPDXRef-DOCUMENT'): - messages = messages + [ - 'Invalid Document SPDX Identifier value.' - ] - - return messages - - def validate_ext_document_references(self, messages): - for doc in self.ext_document_references: - if isinstance(doc, ExternalDocumentRef): - messages = doc.validate(messages) - else: - messages = list(messages) + [ - 'External document references must be of the type ' - 'spdx.document.ExternalDocumentRef and not ' + str(type(doc)) - ] - return messages - - def validate_reviews(self, messages): - for review in self.reviews: - messages = review.validate(messages) - - return messages - - def validate_annotations(self, messages): - for annotation in self.annotations: - messages = annotation.validate(messages) - - return messages - - def validate_snippet(self, messages=None): - for snippet in self.snippet: - messages = snippet.validate(messages) - - return messages - - def validate_creation_info(self, messages): - if self.creation_info is not None: - messages = self.creation_info.validate(messages) - else: - messages = messages + ['Document has no creation information.'] - - return messages - - def validate_package(self, messages): - if self.package is not None: - messages = self.package.validate(messages) - else: - messages = messages + ['Document has no package.'] - - return messages - - def validate_extracted_licenses(self, messages): - for lic in self.extracted_licenses: - if isinstance(lic, ExtractedLicense): - messages = lic.validate(messages) - else: - messages = messages + [ - 'Document extracted licenses must be of type ' - 'spdx.document.ExtractedLicense and not ' + type(lic) - ] - return messages diff --git a/spdx/exceptions.json b/spdx/exceptions.json deleted file mode 100644 index 0f77cd372..000000000 --- a/spdx/exceptions.json +++ /dev/null @@ -1,408 +0,0 @@ -{ - "licenseListVersion": "3.6", - "releaseDate": "2019-07-10", - "exceptions": [ - { - "reference": "./Libtool-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Libtool-exception.json", - "referenceNumber": "1", - "name": "Libtool Exception", - "seeAlso": [ - "http://git.savannah.gnu.org/cgit/libtool.git/tree/m4/libtool.m4" - ], - "licenseExceptionId": "Libtool-exception" - }, - { - "reference": "./Linux-syscall-note.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Linux-syscall-note.json", - "referenceNumber": "2", - "name": "Linux Syscall Note", - "seeAlso": [ - "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/COPYING" - ], - "licenseExceptionId": "Linux-syscall-note" - }, - { - "reference": "./Autoconf-exception-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-3.0.json", - "referenceNumber": "3", - "name": "Autoconf exception 3.0", - "seeAlso": [ - "http://www.gnu.org/licenses/autoconf-exception-3.0.html" - ], - "licenseExceptionId": "Autoconf-exception-3.0" - }, - { - "reference": "./OCCT-exception-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OCCT-exception-1.0.json", - "referenceNumber": "4", - "name": "Open CASCADE Exception 1.0", - "seeAlso": [ - "http://www.opencascade.com/content/licensing" - ], - "licenseExceptionId": "OCCT-exception-1.0" - }, - { - "reference": "./openvpn-openssl-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/openvpn-openssl-exception.json", - "referenceNumber": "5", - "name": "OpenVPN OpenSSL Exception", - "seeAlso": [ - "http://openvpn.net/index.php/license.html" - ], - "licenseExceptionId": "openvpn-openssl-exception" - }, - { - "reference": "./gnu-javamail-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/gnu-javamail-exception.json", - "referenceNumber": "6", - "name": "GNU JavaMail exception", - "seeAlso": [ - "http://www.gnu.org/software/classpathx/javamail/javamail.html" - ], - "licenseExceptionId": "gnu-javamail-exception" - }, - { - "reference": "./OpenJDK-assembly-exception-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OpenJDK-assembly-exception-1.0.json", - "referenceNumber": "7", - "name": "OpenJDK Assembly exception 1.0", - "seeAlso": [ - "http://openjdk.java.net/legal/assembly-exception.html" - ], - "licenseExceptionId": "OpenJDK-assembly-exception-1.0" - }, - { - "reference": "./Bison-exception-2.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Bison-exception-2.2.json", - "referenceNumber": "8", - "name": "Bison exception 2.2", - "seeAlso": [ - "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141" - ], - "licenseExceptionId": "Bison-exception-2.2" - }, - { - "reference": "./i2p-gpl-java-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/i2p-gpl-java-exception.json", - "referenceNumber": "9", - "name": "i2p GPL+Java Exception", - "seeAlso": [ - "http://geti2p.net/en/get-involved/develop/licenses#java_exception" - ], - "licenseExceptionId": "i2p-gpl-java-exception" - }, - { - "reference": "./Universal-FOSS-exception-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Universal-FOSS-exception-1.0.json", - "referenceNumber": "10", - "name": "Universal FOSS Exception, Version 1.0", - "seeAlso": [ - "https://oss.oracle.com/licenses/universal-foss-exception/" - ], - "licenseExceptionId": "Universal-FOSS-exception-1.0" - }, - { - "reference": "./Qt-LGPL-exception-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Qt-LGPL-exception-1.1.json", - "referenceNumber": "11", - "name": "Qt LGPL exception 1.1", - "seeAlso": [ - "http://code.qt.io/cgit/qt/qtbase.git/tree/LGPL_EXCEPTION.txt" - ], - "licenseExceptionId": "Qt-LGPL-exception-1.1" - }, - { - "reference": "./389-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/389-exception.json", - "referenceNumber": "12", - "name": "389 Directory Server Exception", - "seeAlso": [ - "http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text" - ], - "licenseExceptionId": "389-exception" - }, - { - "reference": "./Classpath-exception-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Classpath-exception-2.0.json", - "referenceNumber": "13", - "name": "Classpath exception 2.0", - "seeAlso": [ - "http://www.gnu.org/software/classpath/license.html", - "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception" - ], - "licenseExceptionId": "Classpath-exception-2.0" - }, - { - "reference": "./Fawkes-Runtime-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Fawkes-Runtime-exception.json", - "referenceNumber": "14", - "name": "Fawkes Runtime Exception", - "seeAlso": [ - "http://www.fawkesrobotics.org/about/license/" - ], - "licenseExceptionId": "Fawkes-Runtime-exception" - }, - { - "reference": "./PS-or-PDF-font-exception-20170817.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/PS-or-PDF-font-exception-20170817.json", - "referenceNumber": "15", - "name": "PS/PDF font exception (2017-08-17)", - "seeAlso": [ - "https://github.com/ArtifexSoftware/urw-base35-fonts/blob/65962e27febc3883a17e651cdb23e783668c996f/LICENSE" - ], - "licenseExceptionId": "PS-or-PDF-font-exception-20170817" - }, - { - "reference": "./Qt-GPL-exception-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Qt-GPL-exception-1.0.json", - "referenceNumber": "16", - "name": "Qt GPL exception 1.0", - "seeAlso": [ - "http://code.qt.io/cgit/qt/qtbase.git/tree/LICENSE.GPL3-EXCEPT" - ], - "licenseExceptionId": "Qt-GPL-exception-1.0" - }, - { - "reference": "./LZMA-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LZMA-exception.json", - "referenceNumber": "17", - "name": "LZMA exception", - "seeAlso": [ - "http://nsis.sourceforge.net/Docs/AppendixI.html#I.6" - ], - "licenseExceptionId": "LZMA-exception" - }, - { - "reference": "./freertos-exception-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/freertos-exception-2.0.json", - "referenceNumber": "18", - "name": "FreeRTOS Exception 2.0", - "seeAlso": [ - "https://web.archive.org/web/20060809182744/http://www.freertos.org/a00114.html" - ], - "licenseExceptionId": "freertos-exception-2.0" - }, - { - "reference": "./Qwt-exception-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Qwt-exception-1.0.json", - "referenceNumber": "19", - "name": "Qwt exception 1.0", - "seeAlso": [ - "http://qwt.sourceforge.net/qwtlicense.html" - ], - "licenseExceptionId": "Qwt-exception-1.0" - }, - { - "reference": "./CLISP-exception-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CLISP-exception-2.0.json", - "referenceNumber": "20", - "name": "CLISP exception 2.0", - "seeAlso": [ - "http://sourceforge.net/p/clisp/clisp/ci/default/tree/COPYRIGHT" - ], - "licenseExceptionId": "CLISP-exception-2.0" - }, - { - "reference": "./FLTK-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/FLTK-exception.json", - "referenceNumber": "21", - "name": "FLTK exception", - "seeAlso": [ - "http://www.fltk.org/COPYING.php" - ], - "licenseExceptionId": "FLTK-exception" - }, - { - "reference": "./Bootloader-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Bootloader-exception.json", - "referenceNumber": "22", - "name": "Bootloader Distribution Exception", - "seeAlso": [ - "https://github.com/pyinstaller/pyinstaller/blob/develop/COPYING.txt" - ], - "licenseExceptionId": "Bootloader-exception" - }, - { - "reference": "./Nokia-Qt-exception-1.1.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/Nokia-Qt-exception-1.1.json", - "referenceNumber": "23", - "name": "Nokia Qt LGPL exception 1.1", - "seeAlso": [ - "https://www.keepassx.org/dev/projects/keepassx/repository/revisions/b8dfb9cc4d5133e0f09cd7533d15a4f1c19a40f2/entry/LICENSE.NOKIA-LGPL-EXCEPTION" - ], - "licenseExceptionId": "Nokia-Qt-exception-1.1" - }, - { - "reference": "./LLVM-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LLVM-exception.json", - "referenceNumber": "24", - "name": "LLVM Exception", - "seeAlso": [ - "http://llvm.org/foundation/relicensing/LICENSE.txt" - ], - "licenseExceptionId": "LLVM-exception" - }, - { - "reference": "./WxWindows-exception-3.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/WxWindows-exception-3.1.json", - "referenceNumber": "25", - "name": "WxWindows Library Exception 3.1", - "seeAlso": [ - "http://www.opensource.org/licenses/WXwindows" - ], - "licenseExceptionId": "WxWindows-exception-3.1" - }, - { - "reference": "./DigiRule-FOSS-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/DigiRule-FOSS-exception.json", - "referenceNumber": "26", - "name": "DigiRule FOSS License Exception", - "seeAlso": [ - "http://www.digirulesolutions.com/drupal/foss" - ], - "licenseExceptionId": "DigiRule-FOSS-exception" - }, - { - "reference": "./Swift-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Swift-exception.json", - "referenceNumber": "27", - "name": "Swift Exception", - "seeAlso": [ - "https://swift.org/LICENSE.txt", - "https://github.com/apple/swift-package-manager/blob/7ab2275f447a5eb37497ed63a9340f8a6d1e488b/LICENSE.txt#L205" - ], - "licenseExceptionId": "Swift-exception" - }, - { - "reference": "./GCC-exception-3.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GCC-exception-3.1.json", - "referenceNumber": "28", - "name": "GCC Runtime Library exception 3.1", - "seeAlso": [ - "http://www.gnu.org/licenses/gcc-exception-3.1.html" - ], - "licenseExceptionId": "GCC-exception-3.1" - }, - { - "reference": "./eCos-exception-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/eCos-exception-2.0.json", - "referenceNumber": "29", - "name": "eCos exception 2.0", - "seeAlso": [ - "http://ecos.sourceware.org/license-overview.html" - ], - "licenseExceptionId": "eCos-exception-2.0" - }, - { - "reference": "./Autoconf-exception-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-2.0.json", - "referenceNumber": "30", - "name": "Autoconf exception 2.0", - "seeAlso": [ - "http://ac-archive.sourceforge.net/doc/copyright.html", - "http://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz" - ], - "licenseExceptionId": "Autoconf-exception-2.0" - }, - { - "reference": "./GPL-CC-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GPL-CC-1.0.json", - "referenceNumber": "31", - "name": "GPL Cooperation Commitment 1.0", - "seeAlso": [ - "https://github.com/gplcc/gplcc/blob/master/Project/COMMITMENT", - "https://gplcc.github.io/gplcc/Project/README-PROJECT.html" - ], - "licenseExceptionId": "GPL-CC-1.0" - }, - { - "reference": "./Font-exception-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Font-exception-2.0.json", - "referenceNumber": "32", - "name": "Font exception 2.0", - "seeAlso": [ - "http://www.gnu.org/licenses/gpl-faq.html#FontException" - ], - "licenseExceptionId": "Font-exception-2.0" - }, - { - "reference": "./u-boot-exception-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/u-boot-exception-2.0.json", - "referenceNumber": "33", - "name": "U-Boot exception 2.0", - "seeAlso": [ - "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003dLicenses/Exceptions" - ], - "licenseExceptionId": "u-boot-exception-2.0" - }, - { - "reference": "./GCC-exception-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GCC-exception-2.0.json", - "referenceNumber": "34", - "name": "GCC Runtime Library exception 2.0", - "seeAlso": [ - "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10" - ], - "licenseExceptionId": "GCC-exception-2.0" - }, - { - "reference": "./mif-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/mif-exception.json", - "referenceNumber": "35", - "name": "Macros and Inline Functions Exception", - "seeAlso": [ - "http://www.scs.stanford.edu/histar/src/lib/cppsup/exception", - "http://dev.bertos.org/doxygen/", - "https://www.threadingbuildingblocks.org/licensing" - ], - "licenseExceptionId": "mif-exception" - }, - { - "reference": "./OCaml-LGPL-linking-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OCaml-LGPL-linking-exception.json", - "referenceNumber": "36", - "name": "OCaml LGPL Linking Exception", - "seeAlso": [ - "https://caml.inria.fr/ocaml/license.en.html" - ], - "licenseExceptionId": "OCaml-LGPL-linking-exception" - } - ] -} \ No newline at end of file diff --git a/spdx/file.py b/spdx/file.py deleted file mode 100644 index d0f6dc99b..000000000 --- a/spdx/file.py +++ /dev/null @@ -1,197 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from functools import total_ordering -import hashlib - -import six - -from spdx import checksum -from spdx import document -from spdx import utils - - -class FileType(object): - SOURCE = 1 - BINARY = 2 - ARCHIVE = 3 - OTHER = 4 - -@total_ordering -class File(object): - """ - Represent an SPDX file. - Fields: - - name: File name, str mandatory one. - - spdx_id: Uniquely identify any element in an SPDX document which may be - referenced by other elements. Mandatory, one. Type: str. - - comment: File comment str, Optional zero or one. - - type: one of FileType.SOURCE, FileType.BINARY, FileType.ARCHIVE - and FileType.OTHER, optional zero or one. - - chk_sum: SHA1, Mandatory one. - - conc_lics: Mandatory one. document.License or utils.NoAssert or utils.SPDXNone. - - licenses_in_file: list of licenses found in file, mandatory one or more. - document.License or utils.SPDXNone or utils.NoAssert. - - document.license or utils.NoAssert or utils.SPDXNone. - - license_comment: Optional. - - copyright: Copyright text, Mandatory one. utils.NoAssert or utils.SPDXNone or str. - - notice: optional One, str. - - contributors: List of strings. - - dependencies: list of file locations. - - artifact_of_project_name: list of project names, possibly empty. - - artifact_of_project_home: list of project home page, possibly empty. - - artifact_of_project_uri: list of project uris, possibly empty. - """ - - def __init__(self, name, spdx_id=None, chk_sum=None): - self.name = name - self.spdx_id = spdx_id - self.comment = None - self.type = None - self.chk_sum = chk_sum - self.conc_lics = None - self.licenses_in_file = [] - self.license_comment = None - self.copyright = None - self.notice = None - self.contributors = [] - self.dependencies = [] - self.artifact_of_project_name = [] - self.artifact_of_project_home = [] - self.artifact_of_project_uri = [] - - def __eq__(self, other): - return isinstance(other, File) and self.name == other.name - - def __lt__(self, other): - return self.name < other.name - - def add_lics(self, lics): - self.licenses_in_file.append(lics) - - def add_contrib(self, contrib): - self.contributors.append(contrib) - - def add_depend(self, depend): - self.dependencies.append(depend) - - def add_artifact(self, symbol, value): - """ - Add value as artifact_of_project{symbol}. - """ - symbol = 'artifact_of_project_{}'.format(symbol) - artifact = getattr(self, symbol) - artifact.append(value) - - def validate(self, messages): - """Validates the fields and appends user friendly messages - to messages parameter if there are errors. - """ - messages = self.validate_concluded_license(messages) - messages = self.validate_type(messages) - messages = self.validate_checksum(messages) - messages = self.validate_licenses_in_file(messages) - messages = self.validate_copyright(messages) - messages = self.validate_artifacts(messages) - messages = self.validate_spdx_id(messages) - - return messages - - def validate_spdx_id(self, messages): - if self.spdx_id is None: - messages = messages + ['File has no SPDX Identifier.'] - - return messages - - def validate_copyright(self, messages): - if not isinstance( - self.copyright, - (six.string_types, six.text_type, utils.NoAssert, utils.SPDXNone) - ): - messages = messages + [ - 'File copyright must be str or unicode or ' - 'utils.NoAssert or utils.SPDXNone' - ] - - return messages - - def validate_artifacts(self, messages): - if (len(self.artifact_of_project_home) < - max(len(self.artifact_of_project_uri), - len(self.artifact_of_project_name))): - messages = messages + [ - 'File must have as much artifact of project as uri or homepage'] - - return messages - - def validate_licenses_in_file(self, messages): - # FIXME: what are we testing the length of a list? or? - if len(self.licenses_in_file) == 0: - messages = messages + [ - 'File must have at least one license in file.' - ] - - return messages - - def validate_concluded_license(self, messages): - # FIXME: use isinstance instead?? - if not isinstance(self.conc_lics, (document.License, utils.NoAssert, - utils.SPDXNone)): - messages = messages + [ - 'File concluded license must be one of ' - 'document.License, utils.NoAssert or utils.SPDXNone' - ] - - return messages - - def validate_type(self, messages): - if self.type not in [ - None, FileType.SOURCE, FileType.OTHER, FileType.BINARY, - FileType.ARCHIVE - ]: - messages = messages + [ - 'File type must be one of the constants defined in ' - 'class spdx.file.FileType' - ] - - return messages - - def validate_checksum(self, messages): - if not isinstance(self.chk_sum, checksum.Algorithm): - messages = messages + [ - 'File checksum must be instance of spdx.checksum.Algorithm' - ] - else: - if not self.chk_sum.identifier == 'SHA1': - messages = messages + ['File checksum algorithm must be SHA1'] - - return messages - - def calc_chksum(self): - BUFFER_SIZE = 65536 - - file_sha1 = hashlib.sha1() - with open(self.name, 'rb') as file_handle: - while True: - data = file_handle.read(BUFFER_SIZE) - if not data: - break - file_sha1.update(data) - - return file_sha1.hexdigest() - - def has_optional_field(self, field): - return getattr(self, field, None) is not None diff --git a/spdx/licenses.json b/spdx/licenses.json deleted file mode 100644 index 10550cbd4..000000000 --- a/spdx/licenses.json +++ /dev/null @@ -1,4974 +0,0 @@ -{ - "licenseListVersion": "3.6", - "licenses": [ - { - "reference": "./0BSD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/0BSD.json", - "referenceNumber": "319", - "name": "BSD Zero Clause License", - "licenseId": "0BSD", - "seeAlso": [ - "http://landley.net/toybox/license.html" - ], - "isOsiApproved": true - }, - { - "reference": "./AAL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AAL.json", - "referenceNumber": "21", - "name": "Attribution Assurance License", - "licenseId": "AAL", - "seeAlso": [ - "https://opensource.org/licenses/attribution" - ], - "isOsiApproved": true - }, - { - "reference": "./ADSL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ADSL.json", - "referenceNumber": "19", - "name": "Amazon Digital Services License", - "licenseId": "ADSL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense" - ], - "isOsiApproved": false - }, - { - "reference": "./AFL-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-1.1.json", - "referenceNumber": "118", - "name": "Academic Free License v1.1", - "licenseId": "AFL-1.1", - "seeAlso": [ - "http://opensource.linux-mirror.org/licenses/afl-1.1.txt", - "http://wayback.archive.org/web/20021004124254/http://www.opensource.org/licenses/academic.php" - ], - "isOsiApproved": true - }, - { - "reference": "./AFL-1.2.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-1.2.json", - "referenceNumber": "136", - "name": "Academic Free License v1.2", - "licenseId": "AFL-1.2", - "seeAlso": [ - "http://opensource.linux-mirror.org/licenses/afl-1.2.txt", - "http://wayback.archive.org/web/20021204204652/http://www.opensource.org/licenses/academic.php" - ], - "isOsiApproved": true - }, - { - "reference": "./AFL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-2.0.json", - "referenceNumber": "115", - "name": "Academic Free License v2.0", - "licenseId": "AFL-2.0", - "seeAlso": [ - "http://wayback.archive.org/web/20060924134533/http://www.opensource.org/licenses/afl-2.0.txt" - ], - "isOsiApproved": true - }, - { - "reference": "./AFL-2.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-2.1.json", - "referenceNumber": "251", - "name": "Academic Free License v2.1", - "licenseId": "AFL-2.1", - "seeAlso": [ - "http://opensource.linux-mirror.org/licenses/afl-2.1.txt" - ], - "isOsiApproved": true - }, - { - "reference": "./AFL-3.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-3.0.json", - "referenceNumber": "216", - "name": "Academic Free License v3.0", - "licenseId": "AFL-3.0", - "seeAlso": [ - "http://www.rosenlaw.com/AFL3.0.htm", - "https://opensource.org/licenses/afl-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./AGPL-1.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AGPL-1.0.json", - "referenceNumber": "335", - "name": "Affero General Public License v1.0", - "licenseId": "AGPL-1.0", - "seeAlso": [ - "http://www.affero.org/oagpl.html" - ], - "isOsiApproved": false - }, - { - "reference": "./AGPL-1.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AGPL-1.0-only.json", - "referenceNumber": "384", - "name": "Affero General Public License v1.0 only", - "licenseId": "AGPL-1.0-only", - "seeAlso": [ - "http://www.affero.org/oagpl.html" - ], - "isOsiApproved": false - }, - { - "reference": "./AGPL-1.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AGPL-1.0-or-later.json", - "referenceNumber": "332", - "name": "Affero General Public License v1.0 or later", - "licenseId": "AGPL-1.0-or-later", - "seeAlso": [ - "http://www.affero.org/oagpl.html" - ], - "isOsiApproved": false - }, - { - "reference": "./AGPL-3.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AGPL-3.0.json", - "referenceNumber": "229", - "name": "GNU Affero General Public License v3.0", - "licenseId": "AGPL-3.0", - "seeAlso": [ - "https://www.gnu.org/licenses/agpl.txt", - "https://opensource.org/licenses/AGPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./AGPL-3.0-only.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-only.json", - "referenceNumber": "95", - "name": "GNU Affero General Public License v3.0 only", - "licenseId": "AGPL-3.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/agpl.txt", - "https://opensource.org/licenses/AGPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./AGPL-3.0-or-later.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-or-later.json", - "referenceNumber": "155", - "name": "GNU Affero General Public License v3.0 or later", - "licenseId": "AGPL-3.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/agpl.txt", - "https://opensource.org/licenses/AGPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./AMDPLPA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AMDPLPA.json", - "referenceNumber": "33", - "name": "AMD\u0027s plpa_map.c License", - "licenseId": "AMDPLPA", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AMD_plpa_map_License" - ], - "isOsiApproved": false - }, - { - "reference": "./AML.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AML.json", - "referenceNumber": "148", - "name": "Apple MIT License", - "licenseId": "AML", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Apple_MIT_License" - ], - "isOsiApproved": false - }, - { - "reference": "./AMPAS.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AMPAS.json", - "referenceNumber": "191", - "name": "Academy of Motion Picture Arts and Sciences BSD", - "licenseId": "AMPAS", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/BSD#AMPASBSD" - ], - "isOsiApproved": false - }, - { - "reference": "./ANTLR-PD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ANTLR-PD.json", - "referenceNumber": "395", - "name": "ANTLR Software Rights Notice", - "licenseId": "ANTLR-PD", - "seeAlso": [ - "http://www.antlr2.org/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./APAFML.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APAFML.json", - "referenceNumber": "195", - "name": "Adobe Postscript AFM License", - "licenseId": "APAFML", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AdobePostscriptAFM" - ], - "isOsiApproved": false - }, - { - "reference": "./APL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APL-1.0.json", - "referenceNumber": "252", - "name": "Adaptive Public License 1.0", - "licenseId": "APL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/APL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./APSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APSL-1.0.json", - "referenceNumber": "354", - "name": "Apple Public Source License 1.0", - "licenseId": "APSL-1.0", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Apple_Public_Source_License_1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./APSL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APSL-1.1.json", - "referenceNumber": "324", - "name": "Apple Public Source License 1.1", - "licenseId": "APSL-1.1", - "seeAlso": [ - "http://www.opensource.apple.com/source/IOSerialFamily/IOSerialFamily-7/APPLE_LICENSE" - ], - "isOsiApproved": true - }, - { - "reference": "./APSL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APSL-1.2.json", - "referenceNumber": "34", - "name": "Apple Public Source License 1.2", - "licenseId": "APSL-1.2", - "seeAlso": [ - "http://www.samurajdata.se/opensource/mirror/licenses/apsl.php" - ], - "isOsiApproved": true - }, - { - "reference": "./APSL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/APSL-2.0.json", - "referenceNumber": "109", - "name": "Apple Public Source License 2.0", - "licenseId": "APSL-2.0", - "seeAlso": [ - "http://www.opensource.apple.com/license/apsl/" - ], - "isOsiApproved": true - }, - { - "reference": "./Abstyles.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Abstyles.json", - "referenceNumber": "80", - "name": "Abstyles License", - "licenseId": "Abstyles", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Abstyles" - ], - "isOsiApproved": false - }, - { - "reference": "./Adobe-2006.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Adobe-2006.json", - "referenceNumber": "285", - "name": "Adobe Systems Incorporated Source Code License Agreement", - "licenseId": "Adobe-2006", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AdobeLicense" - ], - "isOsiApproved": false - }, - { - "reference": "./Adobe-Glyph.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Adobe-Glyph.json", - "referenceNumber": "107", - "name": "Adobe Glyph List License", - "licenseId": "Adobe-Glyph", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT#AdobeGlyph" - ], - "isOsiApproved": false - }, - { - "reference": "./Afmparse.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Afmparse.json", - "referenceNumber": "42", - "name": "Afmparse License", - "licenseId": "Afmparse", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Afmparse" - ], - "isOsiApproved": false - }, - { - "reference": "./Aladdin.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Aladdin.json", - "referenceNumber": "258", - "name": "Aladdin Free Public License", - "licenseId": "Aladdin", - "seeAlso": [ - "http://pages.cs.wisc.edu/~ghost/doc/AFPL/6.01/Public.htm" - ], - "isOsiApproved": false - }, - { - "reference": "./Apache-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Apache-1.0.json", - "referenceNumber": "237", - "name": "Apache License 1.0", - "licenseId": "Apache-1.0", - "seeAlso": [ - "http://www.apache.org/licenses/LICENSE-1.0" - ], - "isOsiApproved": false - }, - { - "reference": "./Apache-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Apache-1.1.json", - "referenceNumber": "84", - "name": "Apache License 1.1", - "licenseId": "Apache-1.1", - "seeAlso": [ - "http://apache.org/licenses/LICENSE-1.1", - "https://opensource.org/licenses/Apache-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./Apache-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Apache-2.0.json", - "referenceNumber": "26", - "name": "Apache License 2.0", - "licenseId": "Apache-2.0", - "seeAlso": [ - "http://www.apache.org/licenses/LICENSE-2.0", - "https://opensource.org/licenses/Apache-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./Artistic-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Artistic-1.0.json", - "referenceNumber": "165", - "name": "Artistic License 1.0", - "licenseId": "Artistic-1.0", - "seeAlso": [ - "https://opensource.org/licenses/Artistic-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./Artistic-1.0-Perl.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-Perl.json", - "referenceNumber": "377", - "name": "Artistic License 1.0 (Perl)", - "licenseId": "Artistic-1.0-Perl", - "seeAlso": [ - "http://dev.perl.org/licenses/artistic.html" - ], - "isOsiApproved": true - }, - { - "reference": "./Artistic-1.0-cl8.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-cl8.json", - "referenceNumber": "13", - "name": "Artistic License 1.0 w/clause 8", - "licenseId": "Artistic-1.0-cl8", - "seeAlso": [ - "https://opensource.org/licenses/Artistic-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./Artistic-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Artistic-2.0.json", - "referenceNumber": "189", - "name": "Artistic License 2.0", - "licenseId": "Artistic-2.0", - "seeAlso": [ - "http://www.perlfoundation.org/artistic_license_2_0", - "https://opensource.org/licenses/artistic-license-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./BSD-1-Clause.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-1-Clause.json", - "referenceNumber": "358", - "name": "BSD 1-Clause License", - "licenseId": "BSD-1-Clause", - "seeAlso": [ - "https://svnweb.freebsd.org/base/head/include/ifaddrs.h?revision\u003d326823" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-2-Clause.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause.json", - "referenceNumber": "325", - "name": "BSD 2-Clause \"Simplified\" License", - "licenseId": "BSD-2-Clause", - "seeAlso": [ - "https://opensource.org/licenses/BSD-2-Clause" - ], - "isOsiApproved": true - }, - { - "reference": "./BSD-2-Clause-FreeBSD.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-FreeBSD.json", - "referenceNumber": "121", - "name": "BSD 2-Clause FreeBSD License", - "licenseId": "BSD-2-Clause-FreeBSD", - "seeAlso": [ - "http://www.freebsd.org/copyright/freebsd-license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-2-Clause-NetBSD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-NetBSD.json", - "referenceNumber": "381", - "name": "BSD 2-Clause NetBSD License", - "licenseId": "BSD-2-Clause-NetBSD", - "seeAlso": [ - "http://www.netbsd.org/about/redistribution.html#default" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-2-Clause-Patent.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-Patent.json", - "referenceNumber": "169", - "name": "BSD-2-Clause Plus Patent License", - "licenseId": "BSD-2-Clause-Patent", - "seeAlso": [ - "https://opensource.org/licenses/BSDplusPatent" - ], - "isOsiApproved": true - }, - { - "reference": "./BSD-3-Clause.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause.json", - "referenceNumber": "270", - "name": "BSD 3-Clause \"New\" or \"Revised\" License", - "licenseId": "BSD-3-Clause", - "seeAlso": [ - "https://opensource.org/licenses/BSD-3-Clause" - ], - "isOsiApproved": true - }, - { - "reference": "./BSD-3-Clause-Attribution.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Attribution.json", - "referenceNumber": "39", - "name": "BSD with attribution", - "licenseId": "BSD-3-Clause-Attribution", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/BSD_with_Attribution" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-3-Clause-Clear.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Clear.json", - "referenceNumber": "212", - "name": "BSD 3-Clause Clear License", - "licenseId": "BSD-3-Clause-Clear", - "seeAlso": [ - "http://labs.metacarta.com/license-explanation.html#license" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-3-Clause-LBNL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-LBNL.json", - "referenceNumber": "337", - "name": "Lawrence Berkeley National Labs BSD variant license", - "licenseId": "BSD-3-Clause-LBNL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/LBNLBSD" - ], - "isOsiApproved": true - }, - { - "reference": "./BSD-3-Clause-No-Nuclear-License.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.json", - "referenceNumber": "12", - "name": "BSD 3-Clause No Nuclear License", - "licenseId": "BSD-3-Clause-No-Nuclear-License", - "seeAlso": [ - "http://download.oracle.com/otn-pub/java/licenses/bsd.txt?AuthParam\u003d1467140197_43d516ce1776bd08a58235a7785be1cc" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-3-Clause-No-Nuclear-License-2014.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.json", - "referenceNumber": "137", - "name": "BSD 3-Clause No Nuclear License 2014", - "licenseId": "BSD-3-Clause-No-Nuclear-License-2014", - "seeAlso": [ - "https://java.net/projects/javaeetutorial/pages/BerkeleyLicense" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-3-Clause-No-Nuclear-Warranty.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.json", - "referenceNumber": "44", - "name": "BSD 3-Clause No Nuclear Warranty", - "licenseId": "BSD-3-Clause-No-Nuclear-Warranty", - "seeAlso": [ - "https://jogamp.org/git/?p\u003dgluegen.git;a\u003dblob_plain;f\u003dLICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-3-Clause-Open-MPI.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Open-MPI.json", - "referenceNumber": "349", - "name": "BSD 3-Clause Open MPI variant", - "licenseId": "BSD-3-Clause-Open-MPI", - "seeAlso": [ - "https://www.open-mpi.org/community/license.php", - "http://www.netlib.org/lapack/LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-4-Clause.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause.json", - "referenceNumber": "162", - "name": "BSD 4-Clause \"Original\" or \"Old\" License", - "licenseId": "BSD-4-Clause", - "seeAlso": [ - "http://directory.fsf.org/wiki/License:BSD_4Clause" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-4-Clause-UC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause-UC.json", - "referenceNumber": "203", - "name": "BSD-4-Clause (University of California-Specific)", - "licenseId": "BSD-4-Clause-UC", - "seeAlso": [ - "http://www.freebsd.org/copyright/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-Protection.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-Protection.json", - "referenceNumber": "119", - "name": "BSD Protection License", - "licenseId": "BSD-Protection", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/BSD_Protection_License" - ], - "isOsiApproved": false - }, - { - "reference": "./BSD-Source-Code.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-Source-Code.json", - "referenceNumber": "308", - "name": "BSD Source Code Attribution", - "licenseId": "BSD-Source-Code", - "seeAlso": [ - "https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./BSL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSL-1.0.json", - "referenceNumber": "224", - "name": "Boost Software License 1.0", - "licenseId": "BSL-1.0", - "seeAlso": [ - "http://www.boost.org/LICENSE_1_0.txt", - "https://opensource.org/licenses/BSL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./Bahyph.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Bahyph.json", - "referenceNumber": "366", - "name": "Bahyph License", - "licenseId": "Bahyph", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Bahyph" - ], - "isOsiApproved": false - }, - { - "reference": "./Barr.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Barr.json", - "referenceNumber": "333", - "name": "Barr License", - "licenseId": "Barr", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Barr" - ], - "isOsiApproved": false - }, - { - "reference": "./Beerware.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Beerware.json", - "referenceNumber": "17", - "name": "Beerware License", - "licenseId": "Beerware", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Beerware", - "https://people.freebsd.org/~phk/" - ], - "isOsiApproved": false - }, - { - "reference": "./BitTorrent-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.0.json", - "referenceNumber": "218", - "name": "BitTorrent Open Source License v1.0", - "licenseId": "BitTorrent-1.0", - "seeAlso": [ - "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/BitTorrent?r1\u003d1.1\u0026r2\u003d1.1.1.1\u0026diff_format\u003ds" - ], - "isOsiApproved": false - }, - { - "reference": "./BitTorrent-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.1.json", - "referenceNumber": "179", - "name": "BitTorrent Open Source License v1.1", - "licenseId": "BitTorrent-1.1", - "seeAlso": [ - "http://directory.fsf.org/wiki/License:BitTorrentOSL1.1" - ], - "isOsiApproved": false - }, - { - "reference": "./BlueOak-1.0.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BlueOak-1.0.0.json", - "referenceNumber": "23", - "name": "Blue Oak Model License 1.0.0", - "licenseId": "BlueOak-1.0.0", - "seeAlso": [ - "https://blueoakcouncil.org/license/1.0.0" - ], - "isOsiApproved": false - }, - { - "reference": "./Borceux.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Borceux.json", - "referenceNumber": "311", - "name": "Borceux license", - "licenseId": "Borceux", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Borceux" - ], - "isOsiApproved": false - }, - { - "reference": "./CATOSL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CATOSL-1.1.json", - "referenceNumber": "262", - "name": "Computer Associates Trusted Open Source License 1.1", - "licenseId": "CATOSL-1.1", - "seeAlso": [ - "https://opensource.org/licenses/CATOSL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./CC-BY-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-1.0.json", - "referenceNumber": "128", - "name": "Creative Commons Attribution 1.0 Generic", - "licenseId": "CC-BY-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-2.0.json", - "referenceNumber": "232", - "name": "Creative Commons Attribution 2.0 Generic", - "licenseId": "CC-BY-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-2.5.json", - "referenceNumber": "129", - "name": "Creative Commons Attribution 2.5 Generic", - "licenseId": "CC-BY-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-3.0.json", - "referenceNumber": "256", - "name": "Creative Commons Attribution 3.0 Unported", - "licenseId": "CC-BY-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-4.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CC-BY-4.0.json", - "referenceNumber": "330", - "name": "Creative Commons Attribution 4.0 International", - "licenseId": "CC-BY-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by/4.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-1.0.json", - "referenceNumber": "130", - "name": "Creative Commons Attribution Non Commercial 1.0 Generic", - "licenseId": "CC-BY-NC-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.0.json", - "referenceNumber": "244", - "name": "Creative Commons Attribution Non Commercial 2.0 Generic", - "licenseId": "CC-BY-NC-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.5.json", - "referenceNumber": "1", - "name": "Creative Commons Attribution Non Commercial 2.5 Generic", - "licenseId": "CC-BY-NC-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-3.0.json", - "referenceNumber": "255", - "name": "Creative Commons Attribution Non Commercial 3.0 Unported", - "licenseId": "CC-BY-NC-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-4.0.json", - "referenceNumber": "186", - "name": "Creative Commons Attribution Non Commercial 4.0 International", - "licenseId": "CC-BY-NC-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/4.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-ND-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-1.0.json", - "referenceNumber": "59", - "name": "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic", - "licenseId": "CC-BY-NC-ND-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-ND-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.0.json", - "referenceNumber": "36", - "name": "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic", - "licenseId": "CC-BY-NC-ND-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-ND-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.5.json", - "referenceNumber": "158", - "name": "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic", - "licenseId": "CC-BY-NC-ND-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-ND-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-3.0.json", - "referenceNumber": "48", - "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported", - "licenseId": "CC-BY-NC-ND-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-ND-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-4.0.json", - "referenceNumber": "281", - "name": "Creative Commons Attribution Non Commercial No Derivatives 4.0 International", - "licenseId": "CC-BY-NC-ND-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-SA-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-1.0.json", - "referenceNumber": "178", - "name": "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic", - "licenseId": "CC-BY-NC-SA-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-SA-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.0.json", - "referenceNumber": "81", - "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic", - "licenseId": "CC-BY-NC-SA-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-SA-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.5.json", - "referenceNumber": "62", - "name": "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic", - "licenseId": "CC-BY-NC-SA-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-SA-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-3.0.json", - "referenceNumber": "22", - "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported", - "licenseId": "CC-BY-NC-SA-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-NC-SA-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-4.0.json", - "referenceNumber": "47", - "name": "Creative Commons Attribution Non Commercial Share Alike 4.0 International", - "licenseId": "CC-BY-NC-SA-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-ND-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-1.0.json", - "referenceNumber": "50", - "name": "Creative Commons Attribution No Derivatives 1.0 Generic", - "licenseId": "CC-BY-ND-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-ND-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.0.json", - "referenceNumber": "287", - "name": "Creative Commons Attribution No Derivatives 2.0 Generic", - "licenseId": "CC-BY-ND-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-ND-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.5.json", - "referenceNumber": "68", - "name": "Creative Commons Attribution No Derivatives 2.5 Generic", - "licenseId": "CC-BY-ND-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-ND-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-3.0.json", - "referenceNumber": "393", - "name": "Creative Commons Attribution No Derivatives 3.0 Unported", - "licenseId": "CC-BY-ND-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-ND-4.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-4.0.json", - "referenceNumber": "132", - "name": "Creative Commons Attribution No Derivatives 4.0 International", - "licenseId": "CC-BY-ND-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/4.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-SA-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-1.0.json", - "referenceNumber": "322", - "name": "Creative Commons Attribution Share Alike 1.0 Generic", - "licenseId": "CC-BY-SA-1.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-SA-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.0.json", - "referenceNumber": "142", - "name": "Creative Commons Attribution Share Alike 2.0 Generic", - "licenseId": "CC-BY-SA-2.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/2.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-SA-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.5.json", - "referenceNumber": "306", - "name": "Creative Commons Attribution Share Alike 2.5 Generic", - "licenseId": "CC-BY-SA-2.5", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/2.5/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-SA-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-3.0.json", - "referenceNumber": "394", - "name": "Creative Commons Attribution Share Alike 3.0 Unported", - "licenseId": "CC-BY-SA-3.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/3.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-BY-SA-4.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-4.0.json", - "referenceNumber": "32", - "name": "Creative Commons Attribution Share Alike 4.0 International", - "licenseId": "CC-BY-SA-4.0", - "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/4.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CC-PDDC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-PDDC.json", - "referenceNumber": "371", - "name": "Creative Commons Public Domain Dedication and Certification", - "licenseId": "CC-PDDC", - "seeAlso": [ - "https://creativecommons.org/licenses/publicdomain/" - ], - "isOsiApproved": false - }, - { - "reference": "./CC0-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CC0-1.0.json", - "referenceNumber": "213", - "name": "Creative Commons Zero v1.0 Universal", - "licenseId": "CC0-1.0", - "seeAlso": [ - "https://creativecommons.org/publicdomain/zero/1.0/legalcode" - ], - "isOsiApproved": false - }, - { - "reference": "./CDDL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CDDL-1.0.json", - "referenceNumber": "138", - "name": "Common Development and Distribution License 1.0", - "licenseId": "CDDL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/cddl1" - ], - "isOsiApproved": true - }, - { - "reference": "./CDDL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CDDL-1.1.json", - "referenceNumber": "376", - "name": "Common Development and Distribution License 1.1", - "licenseId": "CDDL-1.1", - "seeAlso": [ - "http://glassfish.java.net/public/CDDL+GPL_1_1.html", - "https://javaee.github.io/glassfish/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "./CDLA-Permissive-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CDLA-Permissive-1.0.json", - "referenceNumber": "250", - "name": "Community Data License Agreement Permissive 1.0", - "licenseId": "CDLA-Permissive-1.0", - "seeAlso": [ - "https://cdla.io/permissive-1-0" - ], - "isOsiApproved": false - }, - { - "reference": "./CDLA-Sharing-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CDLA-Sharing-1.0.json", - "referenceNumber": "310", - "name": "Community Data License Agreement Sharing 1.0", - "licenseId": "CDLA-Sharing-1.0", - "seeAlso": [ - "https://cdla.io/sharing-1-0" - ], - "isOsiApproved": false - }, - { - "reference": "./CECILL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CECILL-1.0.json", - "referenceNumber": "223", - "name": "CeCILL Free Software License Agreement v1.0", - "licenseId": "CECILL-1.0", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V1-fr.html" - ], - "isOsiApproved": false - }, - { - "reference": "./CECILL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CECILL-1.1.json", - "referenceNumber": "300", - "name": "CeCILL Free Software License Agreement v1.1", - "licenseId": "CECILL-1.1", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.html" - ], - "isOsiApproved": false - }, - { - "reference": "./CECILL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CECILL-2.0.json", - "referenceNumber": "352", - "name": "CeCILL Free Software License Agreement v2.0", - "licenseId": "CECILL-2.0", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html" - ], - "isOsiApproved": false - }, - { - "reference": "./CECILL-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CECILL-2.1.json", - "referenceNumber": "120", - "name": "CeCILL Free Software License Agreement v2.1", - "licenseId": "CECILL-2.1", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html" - ], - "isOsiApproved": true - }, - { - "reference": "./CECILL-B.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CECILL-B.json", - "referenceNumber": "340", - "name": "CeCILL-B Free Software License Agreement", - "licenseId": "CECILL-B", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html" - ], - "isOsiApproved": false - }, - { - "reference": "./CECILL-C.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CECILL-C.json", - "referenceNumber": "77", - "name": "CeCILL-C Free Software License Agreement", - "licenseId": "CECILL-C", - "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html" - ], - "isOsiApproved": false - }, - { - "reference": "./CERN-OHL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CERN-OHL-1.1.json", - "referenceNumber": "341", - "name": "CERN Open Hardware License v1.1", - "licenseId": "CERN-OHL-1.1", - "seeAlso": [ - "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.1" - ], - "isOsiApproved": false - }, - { - "reference": "./CERN-OHL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CERN-OHL-1.2.json", - "referenceNumber": "3", - "name": "CERN Open Hardware Licence v1.2", - "licenseId": "CERN-OHL-1.2", - "seeAlso": [ - "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.2" - ], - "isOsiApproved": false - }, - { - "reference": "./CNRI-Jython.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CNRI-Jython.json", - "referenceNumber": "94", - "name": "CNRI Jython License", - "licenseId": "CNRI-Jython", - "seeAlso": [ - "http://www.jython.org/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./CNRI-Python.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CNRI-Python.json", - "referenceNumber": "45", - "name": "CNRI Python License", - "licenseId": "CNRI-Python", - "seeAlso": [ - "https://opensource.org/licenses/CNRI-Python" - ], - "isOsiApproved": true - }, - { - "reference": "./CNRI-Python-GPL-Compatible.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CNRI-Python-GPL-Compatible.json", - "referenceNumber": "202", - "name": "CNRI Python Open Source GPL Compatible License Agreement", - "licenseId": "CNRI-Python-GPL-Compatible", - "seeAlso": [ - "http://www.python.org/download/releases/1.6.1/download_win/" - ], - "isOsiApproved": false - }, - { - "reference": "./CPAL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CPAL-1.0.json", - "referenceNumber": "170", - "name": "Common Public Attribution License 1.0", - "licenseId": "CPAL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/CPAL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./CPL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CPL-1.0.json", - "referenceNumber": "172", - "name": "Common Public License 1.0", - "licenseId": "CPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/CPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./CPOL-1.02.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CPOL-1.02.json", - "referenceNumber": "28", - "name": "Code Project Open License 1.02", - "licenseId": "CPOL-1.02", - "seeAlso": [ - "http://www.codeproject.com/info/cpol10.aspx" - ], - "isOsiApproved": false - }, - { - "reference": "./CUA-OPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CUA-OPL-1.0.json", - "referenceNumber": "365", - "name": "CUA Office Public License v1.0", - "licenseId": "CUA-OPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/CUA-OPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./Caldera.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Caldera.json", - "referenceNumber": "108", - "name": "Caldera License", - "licenseId": "Caldera", - "seeAlso": [ - "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf" - ], - "isOsiApproved": false - }, - { - "reference": "./ClArtistic.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ClArtistic.json", - "referenceNumber": "271", - "name": "Clarified Artistic License", - "licenseId": "ClArtistic", - "seeAlso": [ - "http://gianluca.dellavedova.org/2011/01/03/clarified-artistic-license/", - "http://www.ncftp.com/ncftp/doc/LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./Condor-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Condor-1.1.json", - "referenceNumber": "307", - "name": "Condor Public License v1.1", - "licenseId": "Condor-1.1", - "seeAlso": [ - "http://research.cs.wisc.edu/condor/license.html#condor", - "http://web.archive.org/web/20111123062036/http://research.cs.wisc.edu/condor/license.html#condor" - ], - "isOsiApproved": false - }, - { - "reference": "./Crossword.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Crossword.json", - "referenceNumber": "363", - "name": "Crossword License", - "licenseId": "Crossword", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Crossword" - ], - "isOsiApproved": false - }, - { - "reference": "./CrystalStacker.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CrystalStacker.json", - "referenceNumber": "168", - "name": "CrystalStacker License", - "licenseId": "CrystalStacker", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:CrystalStacker?rd\u003dLicensing/CrystalStacker" - ], - "isOsiApproved": false - }, - { - "reference": "./Cube.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Cube.json", - "referenceNumber": "370", - "name": "Cube License", - "licenseId": "Cube", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Cube" - ], - "isOsiApproved": false - }, - { - "reference": "./D-FSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/D-FSL-1.0.json", - "referenceNumber": "182", - "name": "Deutsche Freie Software Lizenz", - "licenseId": "D-FSL-1.0", - "seeAlso": [ - "http://www.dipp.nrw.de/d-fsl/lizenzen/", - "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/de/D-FSL-1_0_de.txt", - "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/en/D-FSL-1_0_en.txt", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/deutsche-freie-software-lizenz", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/german-free-software-license", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_de.txt/at_download/file", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_en.txt/at_download/file" - ], - "isOsiApproved": false - }, - { - "reference": "./DOC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/DOC.json", - "referenceNumber": "160", - "name": "DOC License", - "licenseId": "DOC", - "seeAlso": [ - "http://www.cs.wustl.edu/~schmidt/ACE-copying.html" - ], - "isOsiApproved": false - }, - { - "reference": "./DSDP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/DSDP.json", - "referenceNumber": "141", - "name": "DSDP License", - "licenseId": "DSDP", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/DSDP" - ], - "isOsiApproved": false - }, - { - "reference": "./Dotseqn.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Dotseqn.json", - "referenceNumber": "390", - "name": "Dotseqn License", - "licenseId": "Dotseqn", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Dotseqn" - ], - "isOsiApproved": false - }, - { - "reference": "./ECL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ECL-1.0.json", - "referenceNumber": "396", - "name": "Educational Community License v1.0", - "licenseId": "ECL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/ECL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./ECL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ECL-2.0.json", - "referenceNumber": "298", - "name": "Educational Community License v2.0", - "licenseId": "ECL-2.0", - "seeAlso": [ - "https://opensource.org/licenses/ECL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./EFL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/EFL-1.0.json", - "referenceNumber": "150", - "name": "Eiffel Forum License v1.0", - "licenseId": "EFL-1.0", - "seeAlso": [ - "http://www.eiffel-nice.org/license/forum.txt", - "https://opensource.org/licenses/EFL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./EFL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EFL-2.0.json", - "referenceNumber": "161", - "name": "Eiffel Forum License v2.0", - "licenseId": "EFL-2.0", - "seeAlso": [ - "http://www.eiffel-nice.org/license/eiffel-forum-license-2.html", - "https://opensource.org/licenses/EFL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./EPL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EPL-1.0.json", - "referenceNumber": "214", - "name": "Eclipse Public License 1.0", - "licenseId": "EPL-1.0", - "seeAlso": [ - "http://www.eclipse.org/legal/epl-v10.html", - "https://opensource.org/licenses/EPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./EPL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EPL-2.0.json", - "referenceNumber": "134", - "name": "Eclipse Public License 2.0", - "licenseId": "EPL-2.0", - "seeAlso": [ - "https://www.eclipse.org/legal/epl-2.0", - "https://www.opensource.org/licenses/EPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./EUDatagrid.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EUDatagrid.json", - "referenceNumber": "192", - "name": "EU DataGrid Software License", - "licenseId": "EUDatagrid", - "seeAlso": [ - "http://eu-datagrid.web.cern.ch/eu-datagrid/license.html", - "https://opensource.org/licenses/EUDatagrid" - ], - "isOsiApproved": true - }, - { - "reference": "./EUPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/EUPL-1.0.json", - "referenceNumber": "173", - "name": "European Union Public License 1.0", - "licenseId": "EUPL-1.0", - "seeAlso": [ - "http://ec.europa.eu/idabc/en/document/7330.html", - "http://ec.europa.eu/idabc/servlets/Doc027f.pdf?id\u003d31096" - ], - "isOsiApproved": false - }, - { - "reference": "./EUPL-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EUPL-1.1.json", - "referenceNumber": "92", - "name": "European Union Public License 1.1", - "licenseId": "EUPL-1.1", - "seeAlso": [ - "https://joinup.ec.europa.eu/software/page/eupl/licence-eupl", - "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf", - "https://opensource.org/licenses/EUPL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./EUPL-1.2.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EUPL-1.2.json", - "referenceNumber": "387", - "name": "European Union Public License 1.2", - "licenseId": "EUPL-1.2", - "seeAlso": [ - "https://joinup.ec.europa.eu/page/eupl-text-11-12", - "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf", - "https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt", - "http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri\u003dCELEX:32017D0863", - "https://opensource.org/licenses/EUPL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./Entessa.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Entessa.json", - "referenceNumber": "99", - "name": "Entessa Public License v1.0", - "licenseId": "Entessa", - "seeAlso": [ - "https://opensource.org/licenses/Entessa" - ], - "isOsiApproved": true - }, - { - "reference": "./ErlPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ErlPL-1.1.json", - "referenceNumber": "157", - "name": "Erlang Public License v1.1", - "licenseId": "ErlPL-1.1", - "seeAlso": [ - "http://www.erlang.org/EPLICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "./Eurosym.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Eurosym.json", - "referenceNumber": "113", - "name": "Eurosym License", - "licenseId": "Eurosym", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Eurosym" - ], - "isOsiApproved": false - }, - { - "reference": "./FSFAP.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/FSFAP.json", - "referenceNumber": "114", - "name": "FSF All Permissive License", - "licenseId": "FSFAP", - "seeAlso": [ - "https://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html" - ], - "isOsiApproved": false - }, - { - "reference": "./FSFUL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/FSFUL.json", - "referenceNumber": "193", - "name": "FSF Unlimited License", - "licenseId": "FSFUL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License" - ], - "isOsiApproved": false - }, - { - "reference": "./FSFULLR.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/FSFULLR.json", - "referenceNumber": "43", - "name": "FSF Unlimited License (with License Retention)", - "licenseId": "FSFULLR", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License#License_Retention_Variant" - ], - "isOsiApproved": false - }, - { - "reference": "./FTL.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/FTL.json", - "referenceNumber": "240", - "name": "Freetype Project License", - "licenseId": "FTL", - "seeAlso": [ - "http://freetype.fis.uniroma2.it/FTL.TXT", - "http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT" - ], - "isOsiApproved": false - }, - { - "reference": "./Fair.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Fair.json", - "referenceNumber": "297", - "name": "Fair License", - "licenseId": "Fair", - "seeAlso": [ - "http://fairlicense.org/", - "https://opensource.org/licenses/Fair" - ], - "isOsiApproved": true - }, - { - "reference": "./Frameworx-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Frameworx-1.0.json", - "referenceNumber": "389", - "name": "Frameworx Open License 1.0", - "licenseId": "Frameworx-1.0", - "seeAlso": [ - "https://opensource.org/licenses/Frameworx-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./FreeImage.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/FreeImage.json", - "referenceNumber": "277", - "name": "FreeImage Public License v1.0", - "licenseId": "FreeImage", - "seeAlso": [ - "http://freeimage.sourceforge.net/freeimage-license.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GFDL-1.1.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.1.json", - "referenceNumber": "98", - "name": "GNU Free Documentation License v1.1", - "licenseId": "GFDL-1.1", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GFDL-1.1-only.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-only.json", - "referenceNumber": "102", - "name": "GNU Free Documentation License v1.1 only", - "licenseId": "GFDL-1.1-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GFDL-1.1-or-later.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-or-later.json", - "referenceNumber": "348", - "name": "GNU Free Documentation License v1.1 or later", - "licenseId": "GFDL-1.1-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GFDL-1.2.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.2.json", - "referenceNumber": "197", - "name": "GNU Free Documentation License v1.2", - "licenseId": "GFDL-1.2", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GFDL-1.2-only.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-only.json", - "referenceNumber": "236", - "name": "GNU Free Documentation License v1.2 only", - "licenseId": "GFDL-1.2-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GFDL-1.2-or-later.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-or-later.json", - "referenceNumber": "215", - "name": "GNU Free Documentation License v1.2 or later", - "licenseId": "GFDL-1.2-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GFDL-1.3.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.3.json", - "referenceNumber": "112", - "name": "GNU Free Documentation License v1.3", - "licenseId": "GFDL-1.3", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GFDL-1.3-only.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-only.json", - "referenceNumber": "69", - "name": "GNU Free Documentation License v1.3 only", - "licenseId": "GFDL-1.3-only", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GFDL-1.3-or-later.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-or-later.json", - "referenceNumber": "4", - "name": "GNU Free Documentation License v1.3 or later", - "licenseId": "GFDL-1.3-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./GL2PS.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GL2PS.json", - "referenceNumber": "124", - "name": "GL2PS License", - "licenseId": "GL2PS", - "seeAlso": [ - "http://www.geuz.org/gl2ps/COPYING.GL2PS" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-1.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-1.0.json", - "referenceNumber": "79", - "name": "GNU General Public License v1.0 only", - "licenseId": "GPL-1.0", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-1.0+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-1.0+.json", - "referenceNumber": "175", - "name": "GNU General Public License v1.0 or later", - "licenseId": "GPL-1.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-1.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GPL-1.0-only.json", - "referenceNumber": "15", - "name": "GNU General Public License v1.0 only", - "licenseId": "GPL-1.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-1.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GPL-1.0-or-later.json", - "referenceNumber": "357", - "name": "GNU General Public License v1.0 or later", - "licenseId": "GPL-1.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-2.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0.json", - "referenceNumber": "147", - "name": "GNU General Public License v2.0 only", - "licenseId": "GPL-2.0", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://opensource.org/licenses/GPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./GPL-2.0+.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0+.json", - "referenceNumber": "75", - "name": "GNU General Public License v2.0 or later", - "licenseId": "GPL-2.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://opensource.org/licenses/GPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./GPL-2.0-only.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-only.json", - "referenceNumber": "233", - "name": "GNU General Public License v2.0 only", - "licenseId": "GPL-2.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://opensource.org/licenses/GPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./GPL-2.0-or-later.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-or-later.json", - "referenceNumber": "56", - "name": "GNU General Public License v2.0 or later", - "licenseId": "GPL-2.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://opensource.org/licenses/GPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./GPL-2.0-with-GCC-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-GCC-exception.json", - "referenceNumber": "117", - "name": "GNU General Public License v2.0 w/GCC Runtime Library exception", - "licenseId": "GPL-2.0-with-GCC-exception", - "seeAlso": [ - "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-2.0-with-autoconf-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-autoconf-exception.json", - "referenceNumber": "355", - "name": "GNU General Public License v2.0 w/Autoconf exception", - "licenseId": "GPL-2.0-with-autoconf-exception", - "seeAlso": [ - "http://ac-archive.sourceforge.net/doc/copyright.html" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-2.0-with-bison-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-bison-exception.json", - "referenceNumber": "378", - "name": "GNU General Public License v2.0 w/Bison exception", - "licenseId": "GPL-2.0-with-bison-exception", - "seeAlso": [ - "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-2.0-with-classpath-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-classpath-exception.json", - "referenceNumber": "60", - "name": "GNU General Public License v2.0 w/Classpath exception", - "licenseId": "GPL-2.0-with-classpath-exception", - "seeAlso": [ - "https://www.gnu.org/software/classpath/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-2.0-with-font-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-font-exception.json", - "referenceNumber": "375", - "name": "GNU General Public License v2.0 w/Font exception", - "licenseId": "GPL-2.0-with-font-exception", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-faq.html#FontException" - ], - "isOsiApproved": false - }, - { - "reference": "./GPL-3.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0.json", - "referenceNumber": "242", - "name": "GNU General Public License v3.0 only", - "licenseId": "GPL-3.0", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./GPL-3.0+.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0+.json", - "referenceNumber": "73", - "name": "GNU General Public License v3.0 or later", - "licenseId": "GPL-3.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./GPL-3.0-only.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0-only.json", - "referenceNumber": "206", - "name": "GNU General Public License v3.0 only", - "licenseId": "GPL-3.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./GPL-3.0-or-later.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0-or-later.json", - "referenceNumber": "196", - "name": "GNU General Public License v3.0 or later", - "licenseId": "GPL-3.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./GPL-3.0-with-GCC-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-GCC-exception.json", - "referenceNumber": "221", - "name": "GNU General Public License v3.0 w/GCC Runtime Library exception", - "licenseId": "GPL-3.0-with-GCC-exception", - "seeAlso": [ - "https://www.gnu.org/licenses/gcc-exception-3.1.html" - ], - "isOsiApproved": true - }, - { - "reference": "./GPL-3.0-with-autoconf-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-autoconf-exception.json", - "referenceNumber": "235", - "name": "GNU General Public License v3.0 w/Autoconf exception", - "licenseId": "GPL-3.0-with-autoconf-exception", - "seeAlso": [ - "https://www.gnu.org/licenses/autoconf-exception-3.0.html" - ], - "isOsiApproved": false - }, - { - "reference": "./Giftware.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Giftware.json", - "referenceNumber": "369", - "name": "Giftware License", - "licenseId": "Giftware", - "seeAlso": [ - "http://liballeg.org/license.html#allegro-4-the-giftware-license" - ], - "isOsiApproved": false - }, - { - "reference": "./Glide.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Glide.json", - "referenceNumber": "374", - "name": "3dfx Glide License", - "licenseId": "Glide", - "seeAlso": [ - "http://www.users.on.net/~triforce/glidexp/COPYING.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./Glulxe.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Glulxe.json", - "referenceNumber": "93", - "name": "Glulxe License", - "licenseId": "Glulxe", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Glulxe" - ], - "isOsiApproved": false - }, - { - "reference": "./HPND.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/HPND.json", - "referenceNumber": "264", - "name": "Historical Permission Notice and Disclaimer", - "licenseId": "HPND", - "seeAlso": [ - "https://opensource.org/licenses/HPND" - ], - "isOsiApproved": true - }, - { - "reference": "./HPND-sell-variant.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/HPND-sell-variant.json", - "referenceNumber": "145", - "name": "Historical Permission Notice and Disclaimer - sell variant", - "licenseId": "HPND-sell-variant", - "seeAlso": [ - "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/sunrpc/auth_gss/gss_generic_token.c?h\u003dv4.19" - ], - "isOsiApproved": false - }, - { - "reference": "./HaskellReport.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/HaskellReport.json", - "referenceNumber": "122", - "name": "Haskell Language Report License", - "licenseId": "HaskellReport", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Haskell_Language_Report_License" - ], - "isOsiApproved": false - }, - { - "reference": "./IBM-pibs.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/IBM-pibs.json", - "referenceNumber": "207", - "name": "IBM PowerPC Initialization and Boot Software", - "licenseId": "IBM-pibs", - "seeAlso": [ - "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003darch/powerpc/cpu/ppc4xx/miiphy.c;h\u003d297155fdafa064b955e53e9832de93bfb0cfb85b;hb\u003d9fab4bf4cc077c21e43941866f3f2c196f28670d" - ], - "isOsiApproved": false - }, - { - "reference": "./ICU.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ICU.json", - "referenceNumber": "194", - "name": "ICU License", - "licenseId": "ICU", - "seeAlso": [ - "http://source.icu-project.org/repos/icu/icu/trunk/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./IJG.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/IJG.json", - "referenceNumber": "55", - "name": "Independent JPEG Group License", - "licenseId": "IJG", - "seeAlso": [ - "http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev\u003d1.2" - ], - "isOsiApproved": false - }, - { - "reference": "./IPA.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/IPA.json", - "referenceNumber": "312", - "name": "IPA Font License", - "licenseId": "IPA", - "seeAlso": [ - "https://opensource.org/licenses/IPA" - ], - "isOsiApproved": true - }, - { - "reference": "./IPL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/IPL-1.0.json", - "referenceNumber": "31", - "name": "IBM Public License v1.0", - "licenseId": "IPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/IPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./ISC.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ISC.json", - "referenceNumber": "110", - "name": "ISC License", - "licenseId": "ISC", - "seeAlso": [ - "https://www.isc.org/downloads/software-support-policy/isc-license/", - "https://opensource.org/licenses/ISC" - ], - "isOsiApproved": true - }, - { - "reference": "./ImageMagick.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ImageMagick.json", - "referenceNumber": "231", - "name": "ImageMagick License", - "licenseId": "ImageMagick", - "seeAlso": [ - "http://www.imagemagick.org/script/license.php" - ], - "isOsiApproved": false - }, - { - "reference": "./Imlib2.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Imlib2.json", - "referenceNumber": "257", - "name": "Imlib2 License", - "licenseId": "Imlib2", - "seeAlso": [ - "http://trac.enlightenment.org/e/browser/trunk/imlib2/COPYING", - "https://git.enlightenment.org/legacy/imlib2.git/tree/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "./Info-ZIP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Info-ZIP.json", - "referenceNumber": "104", - "name": "Info-ZIP License", - "licenseId": "Info-ZIP", - "seeAlso": [ - "http://www.info-zip.org/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./Intel.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Intel.json", - "referenceNumber": "167", - "name": "Intel Open Source License", - "licenseId": "Intel", - "seeAlso": [ - "https://opensource.org/licenses/Intel" - ], - "isOsiApproved": true - }, - { - "reference": "./Intel-ACPI.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Intel-ACPI.json", - "referenceNumber": "88", - "name": "Intel ACPI Software License Agreement", - "licenseId": "Intel-ACPI", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Intel_ACPI_Software_License_Agreement" - ], - "isOsiApproved": false - }, - { - "reference": "./Interbase-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Interbase-1.0.json", - "referenceNumber": "83", - "name": "Interbase Public License v1.0", - "licenseId": "Interbase-1.0", - "seeAlso": [ - "https://web.archive.org/web/20060319014854/http://info.borland.com/devsupport/interbase/opensource/IPL.html" - ], - "isOsiApproved": false - }, - { - "reference": "./JPNIC.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/JPNIC.json", - "referenceNumber": "105", - "name": "Japan Network Information Center License", - "licenseId": "JPNIC", - "seeAlso": [ - "https://gitlab.isc.org/isc-projects/bind9/blob/master/COPYRIGHT#L366" - ], - "isOsiApproved": false - }, - { - "reference": "./JSON.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/JSON.json", - "referenceNumber": "372", - "name": "JSON License", - "licenseId": "JSON", - "seeAlso": [ - "http://www.json.org/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./JasPer-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/JasPer-2.0.json", - "referenceNumber": "239", - "name": "JasPer License", - "licenseId": "JasPer-2.0", - "seeAlso": [ - "http://www.ece.uvic.ca/~mdadams/jasper/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "./LAL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LAL-1.2.json", - "referenceNumber": "380", - "name": "Licence Art Libre 1.2", - "licenseId": "LAL-1.2", - "seeAlso": [ - "http://artlibre.org/licence/lal/licence-art-libre-12/" - ], - "isOsiApproved": false - }, - { - "reference": "./LAL-1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LAL-1.3.json", - "referenceNumber": "156", - "name": "Licence Art Libre 1.3", - "licenseId": "LAL-1.3", - "seeAlso": [ - "http://artlibre.org/" - ], - "isOsiApproved": false - }, - { - "reference": "./LGPL-2.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.0.json", - "referenceNumber": "268", - "name": "GNU Library General Public License v2 only", - "licenseId": "LGPL-2.0", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-2.0+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.0+.json", - "referenceNumber": "52", - "name": "GNU Library General Public License v2 or later", - "licenseId": "LGPL-2.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-2.0-only.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-only.json", - "referenceNumber": "276", - "name": "GNU Library General Public License v2 only", - "licenseId": "LGPL-2.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-2.0-or-later.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-or-later.json", - "referenceNumber": "217", - "name": "GNU Library General Public License v2 or later", - "licenseId": "LGPL-2.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-2.1.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.1.json", - "referenceNumber": "166", - "name": "GNU Lesser General Public License v2.1 only", - "licenseId": "LGPL-2.1", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-2.1+.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.1+.json", - "referenceNumber": "64", - "name": "GNU Library General Public License v2.1 or later", - "licenseId": "LGPL-2.1+", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-2.1-only.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-only.json", - "referenceNumber": "2", - "name": "GNU Lesser General Public License v2.1 only", - "licenseId": "LGPL-2.1-only", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-2.1-or-later.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-or-later.json", - "referenceNumber": "338", - "name": "GNU Lesser General Public License v2.1 or later", - "licenseId": "LGPL-2.1-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-3.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-3.0.json", - "referenceNumber": "210", - "name": "GNU Lesser General Public License v3.0 only", - "licenseId": "LGPL-3.0", - "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://opensource.org/licenses/LGPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-3.0+.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-3.0+.json", - "referenceNumber": "152", - "name": "GNU Lesser General Public License v3.0 or later", - "licenseId": "LGPL-3.0+", - "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://opensource.org/licenses/LGPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-3.0-only.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-only.json", - "referenceNumber": "254", - "name": "GNU Lesser General Public License v3.0 only", - "licenseId": "LGPL-3.0-only", - "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://opensource.org/licenses/LGPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPL-3.0-or-later.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-or-later.json", - "referenceNumber": "301", - "name": "GNU Lesser General Public License v3.0 or later", - "licenseId": "LGPL-3.0-or-later", - "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://opensource.org/licenses/LGPL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./LGPLLR.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LGPLLR.json", - "referenceNumber": "103", - "name": "Lesser General Public License For Linguistic Resources", - "licenseId": "LGPLLR", - "seeAlso": [ - "http://www-igm.univ-mlv.fr/~unitex/lgpllr.html" - ], - "isOsiApproved": false - }, - { - "reference": "./LPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LPL-1.0.json", - "referenceNumber": "89", - "name": "Lucent Public License Version 1.0", - "licenseId": "LPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/LPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./LPL-1.02.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LPL-1.02.json", - "referenceNumber": "131", - "name": "Lucent Public License v1.02", - "licenseId": "LPL-1.02", - "seeAlso": [ - "http://plan9.bell-labs.com/plan9/license.html", - "https://opensource.org/licenses/LPL-1.02" - ], - "isOsiApproved": true - }, - { - "reference": "./LPPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.0.json", - "referenceNumber": "259", - "name": "LaTeX Project Public License v1.0", - "licenseId": "LPPL-1.0", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-0.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./LPPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.1.json", - "referenceNumber": "309", - "name": "LaTeX Project Public License v1.1", - "licenseId": "LPPL-1.1", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-1.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./LPPL-1.2.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.2.json", - "referenceNumber": "392", - "name": "LaTeX Project Public License v1.2", - "licenseId": "LPPL-1.2", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-2.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./LPPL-1.3a.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.3a.json", - "referenceNumber": "305", - "name": "LaTeX Project Public License v1.3a", - "licenseId": "LPPL-1.3a", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-3a.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./LPPL-1.3c.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.3c.json", - "referenceNumber": "326", - "name": "LaTeX Project Public License v1.3c", - "licenseId": "LPPL-1.3c", - "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-3c.txt", - "https://opensource.org/licenses/LPPL-1.3c" - ], - "isOsiApproved": true - }, - { - "reference": "./Latex2e.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Latex2e.json", - "referenceNumber": "283", - "name": "Latex2e License", - "licenseId": "Latex2e", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Latex2e" - ], - "isOsiApproved": false - }, - { - "reference": "./Leptonica.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Leptonica.json", - "referenceNumber": "159", - "name": "Leptonica License", - "licenseId": "Leptonica", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Leptonica" - ], - "isOsiApproved": false - }, - { - "reference": "./LiLiQ-P-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LiLiQ-P-1.1.json", - "referenceNumber": "379", - "name": "Licence Libre du Québec – Permissive version 1.1", - "licenseId": "LiLiQ-P-1.1", - "seeAlso": [ - "https://forge.gouv.qc.ca/licence/fr/liliq-v1-1/", - "http://opensource.org/licenses/LiLiQ-P-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./LiLiQ-R-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LiLiQ-R-1.1.json", - "referenceNumber": "286", - "name": "Licence Libre du Québec – Réciprocité version 1.1", - "licenseId": "LiLiQ-R-1.1", - "seeAlso": [ - "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-liliq-r-v1-1/", - "http://opensource.org/licenses/LiLiQ-R-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./LiLiQ-Rplus-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LiLiQ-Rplus-1.1.json", - "referenceNumber": "139", - "name": "Licence Libre du Québec – Réciprocité forte version 1.1", - "licenseId": "LiLiQ-Rplus-1.1", - "seeAlso": [ - "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-forte-liliq-r-v1-1/", - "http://opensource.org/licenses/LiLiQ-Rplus-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./Libpng.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Libpng.json", - "referenceNumber": "101", - "name": "libpng License", - "licenseId": "Libpng", - "seeAlso": [ - "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./Linux-OpenIB.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Linux-OpenIB.json", - "referenceNumber": "5", - "name": "Linux Kernel Variant of OpenIB.org license", - "licenseId": "Linux-OpenIB", - "seeAlso": [ - "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/infiniband/core/sa.h" - ], - "isOsiApproved": false - }, - { - "reference": "./MIT.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MIT.json", - "referenceNumber": "201", - "name": "MIT License", - "licenseId": "MIT", - "seeAlso": [ - "https://opensource.org/licenses/MIT" - ], - "isOsiApproved": true - }, - { - "reference": "./MIT-0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-0.json", - "referenceNumber": "6", - "name": "MIT No Attribution", - "licenseId": "MIT-0", - "seeAlso": [ - "https://github.com/aws/mit-0", - "https://romanrm.net/mit-zero", - "https://github.com/awsdocs/aws-cloud9-user-guide/blob/master/LICENSE-SAMPLECODE" - ], - "isOsiApproved": true - }, - { - "reference": "./MIT-CMU.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-CMU.json", - "referenceNumber": "9", - "name": "CMU License", - "licenseId": "MIT-CMU", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:MIT?rd\u003dLicensing/MIT#CMU_Style", - "https://github.com/python-pillow/Pillow/blob/fffb426092c8db24a5f4b6df243a8a3c01fb63cd/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "./MIT-advertising.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-advertising.json", - "referenceNumber": "8", - "name": "Enlightenment License (e16)", - "licenseId": "MIT-advertising", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT_With_Advertising" - ], - "isOsiApproved": false - }, - { - "reference": "./MIT-enna.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-enna.json", - "referenceNumber": "25", - "name": "enna License", - "licenseId": "MIT-enna", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT#enna" - ], - "isOsiApproved": false - }, - { - "reference": "./MIT-feh.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-feh.json", - "referenceNumber": "38", - "name": "feh License", - "licenseId": "MIT-feh", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT#feh" - ], - "isOsiApproved": false - }, - { - "reference": "./MITNFA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MITNFA.json", - "referenceNumber": "294", - "name": "MIT +no-false-attribs license", - "licenseId": "MITNFA", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MITNFA" - ], - "isOsiApproved": false - }, - { - "reference": "./MPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MPL-1.0.json", - "referenceNumber": "49", - "name": "Mozilla Public License 1.0", - "licenseId": "MPL-1.0", - "seeAlso": [ - "http://www.mozilla.org/MPL/MPL-1.0.html", - "https://opensource.org/licenses/MPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./MPL-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MPL-1.1.json", - "referenceNumber": "304", - "name": "Mozilla Public License 1.1", - "licenseId": "MPL-1.1", - "seeAlso": [ - "http://www.mozilla.org/MPL/MPL-1.1.html", - "https://opensource.org/licenses/MPL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./MPL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MPL-2.0.json", - "referenceNumber": "234", - "name": "Mozilla Public License 2.0", - "licenseId": "MPL-2.0", - "seeAlso": [ - "http://www.mozilla.org/MPL/2.0/", - "https://opensource.org/licenses/MPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./MPL-2.0-no-copyleft-exception.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MPL-2.0-no-copyleft-exception.json", - "referenceNumber": "303", - "name": "Mozilla Public License 2.0 (no copyleft exception)", - "licenseId": "MPL-2.0-no-copyleft-exception", - "seeAlso": [ - "http://www.mozilla.org/MPL/2.0/", - "https://opensource.org/licenses/MPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./MS-PL.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MS-PL.json", - "referenceNumber": "336", - "name": "Microsoft Public License", - "licenseId": "MS-PL", - "seeAlso": [ - "http://www.microsoft.com/opensource/licenses.mspx", - "https://opensource.org/licenses/MS-PL" - ], - "isOsiApproved": true - }, - { - "reference": "./MS-RL.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MS-RL.json", - "referenceNumber": "280", - "name": "Microsoft Reciprocal License", - "licenseId": "MS-RL", - "seeAlso": [ - "http://www.microsoft.com/opensource/licenses.mspx", - "https://opensource.org/licenses/MS-RL" - ], - "isOsiApproved": true - }, - { - "reference": "./MTLL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MTLL.json", - "referenceNumber": "181", - "name": "Matrix Template Library License", - "licenseId": "MTLL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Matrix_Template_Library_License" - ], - "isOsiApproved": false - }, - { - "reference": "./MakeIndex.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MakeIndex.json", - "referenceNumber": "187", - "name": "MakeIndex License", - "licenseId": "MakeIndex", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MakeIndex" - ], - "isOsiApproved": false - }, - { - "reference": "./MirOS.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MirOS.json", - "referenceNumber": "299", - "name": "MirOS License", - "licenseId": "MirOS", - "seeAlso": [ - "https://opensource.org/licenses/MirOS" - ], - "isOsiApproved": true - }, - { - "reference": "./Motosoto.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Motosoto.json", - "referenceNumber": "317", - "name": "Motosoto License", - "licenseId": "Motosoto", - "seeAlso": [ - "https://opensource.org/licenses/Motosoto" - ], - "isOsiApproved": true - }, - { - "reference": "./Multics.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Multics.json", - "referenceNumber": "63", - "name": "Multics License", - "licenseId": "Multics", - "seeAlso": [ - "https://opensource.org/licenses/Multics" - ], - "isOsiApproved": true - }, - { - "reference": "./Mup.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Mup.json", - "referenceNumber": "353", - "name": "Mup License", - "licenseId": "Mup", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Mup" - ], - "isOsiApproved": false - }, - { - "reference": "./NASA-1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NASA-1.3.json", - "referenceNumber": "87", - "name": "NASA Open Source Agreement 1.3", - "licenseId": "NASA-1.3", - "seeAlso": [ - "http://ti.arc.nasa.gov/opensource/nosa/", - "https://opensource.org/licenses/NASA-1.3" - ], - "isOsiApproved": true - }, - { - "reference": "./NBPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NBPL-1.0.json", - "referenceNumber": "361", - "name": "Net Boolean Public License v1", - "licenseId": "NBPL-1.0", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d37b4b3f6cc4bf34e1d3dec61e69914b9819d8894" - ], - "isOsiApproved": false - }, - { - "reference": "./NCSA.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/NCSA.json", - "referenceNumber": "58", - "name": "University of Illinois/NCSA Open Source License", - "licenseId": "NCSA", - "seeAlso": [ - "http://otm.illinois.edu/uiuc_openSource", - "https://opensource.org/licenses/NCSA" - ], - "isOsiApproved": true - }, - { - "reference": "./NGPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NGPL.json", - "referenceNumber": "71", - "name": "Nethack General Public License", - "licenseId": "NGPL", - "seeAlso": [ - "https://opensource.org/licenses/NGPL" - ], - "isOsiApproved": true - }, - { - "reference": "./NLOD-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NLOD-1.0.json", - "referenceNumber": "209", - "name": "Norwegian Licence for Open Government Data", - "licenseId": "NLOD-1.0", - "seeAlso": [ - "http://data.norge.no/nlod/en/1.0" - ], - "isOsiApproved": false - }, - { - "reference": "./NLPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NLPL.json", - "referenceNumber": "344", - "name": "No Limit Public License", - "licenseId": "NLPL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/NLPL" - ], - "isOsiApproved": false - }, - { - "reference": "./NOSL.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/NOSL.json", - "referenceNumber": "383", - "name": "Netizen Open Source License", - "licenseId": "NOSL", - "seeAlso": [ - "http://bits.netizen.com.au/licenses/NOSL/nosl.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./NPL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/NPL-1.0.json", - "referenceNumber": "328", - "name": "Netscape Public License v1.0", - "licenseId": "NPL-1.0", - "seeAlso": [ - "http://www.mozilla.org/MPL/NPL/1.0/" - ], - "isOsiApproved": false - }, - { - "reference": "./NPL-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/NPL-1.1.json", - "referenceNumber": "185", - "name": "Netscape Public License v1.1", - "licenseId": "NPL-1.1", - "seeAlso": [ - "http://www.mozilla.org/MPL/NPL/1.1/" - ], - "isOsiApproved": false - }, - { - "reference": "./NPOSL-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NPOSL-3.0.json", - "referenceNumber": "222", - "name": "Non-Profit Open Software License 3.0", - "licenseId": "NPOSL-3.0", - "seeAlso": [ - "https://opensource.org/licenses/NOSL3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./NRL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NRL.json", - "referenceNumber": "53", - "name": "NRL License", - "licenseId": "NRL", - "seeAlso": [ - "http://web.mit.edu/network/isakmp/nrllicense.html" - ], - "isOsiApproved": false - }, - { - "reference": "./NTP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NTP.json", - "referenceNumber": "261", - "name": "NTP License", - "licenseId": "NTP", - "seeAlso": [ - "https://opensource.org/licenses/NTP" - ], - "isOsiApproved": true - }, - { - "reference": "./Naumen.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Naumen.json", - "referenceNumber": "278", - "name": "Naumen Public License", - "licenseId": "Naumen", - "seeAlso": [ - "https://opensource.org/licenses/Naumen" - ], - "isOsiApproved": true - }, - { - "reference": "./Net-SNMP.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Net-SNMP.json", - "referenceNumber": "284", - "name": "Net-SNMP License", - "licenseId": "Net-SNMP", - "seeAlso": [ - "http://net-snmp.sourceforge.net/about/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./NetCDF.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NetCDF.json", - "referenceNumber": "46", - "name": "NetCDF license", - "licenseId": "NetCDF", - "seeAlso": [ - "http://www.unidata.ucar.edu/software/netcdf/copyright.html" - ], - "isOsiApproved": false - }, - { - "reference": "./Newsletr.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Newsletr.json", - "referenceNumber": "279", - "name": "Newsletr License", - "licenseId": "Newsletr", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Newsletr" - ], - "isOsiApproved": false - }, - { - "reference": "./Nokia.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Nokia.json", - "referenceNumber": "327", - "name": "Nokia Open Source License", - "licenseId": "Nokia", - "seeAlso": [ - "https://opensource.org/licenses/nokia" - ], - "isOsiApproved": true - }, - { - "reference": "./Noweb.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Noweb.json", - "referenceNumber": "364", - "name": "Noweb License", - "licenseId": "Noweb", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Noweb" - ], - "isOsiApproved": false - }, - { - "reference": "./Nunit.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Nunit.json", - "referenceNumber": "288", - "name": "Nunit License", - "licenseId": "Nunit", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Nunit" - ], - "isOsiApproved": false - }, - { - "reference": "./OCCT-PL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OCCT-PL.json", - "referenceNumber": "282", - "name": "Open CASCADE Technology Public License", - "licenseId": "OCCT-PL", - "seeAlso": [ - "http://www.opencascade.com/content/occt-public-license" - ], - "isOsiApproved": false - }, - { - "reference": "./OCLC-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OCLC-2.0.json", - "referenceNumber": "111", - "name": "OCLC Research Public License 2.0", - "licenseId": "OCLC-2.0", - "seeAlso": [ - "http://www.oclc.org/research/activities/software/license/v2final.htm", - "https://opensource.org/licenses/OCLC-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./ODC-By-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ODC-By-1.0.json", - "referenceNumber": "144", - "name": "Open Data Commons Attribution License v1.0", - "licenseId": "ODC-By-1.0", - "seeAlso": [ - "https://opendatacommons.org/licenses/by/1.0/" - ], - "isOsiApproved": false - }, - { - "reference": "./ODbL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ODbL-1.0.json", - "referenceNumber": "246", - "name": "ODC Open Database License v1.0", - "licenseId": "ODbL-1.0", - "seeAlso": [ - "http://www.opendatacommons.org/licenses/odbl/1.0/" - ], - "isOsiApproved": false - }, - { - "reference": "./OFL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OFL-1.0.json", - "referenceNumber": "153", - "name": "SIL Open Font License 1.0", - "licenseId": "OFL-1.0", - "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" - ], - "isOsiApproved": false - }, - { - "reference": "./OFL-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OFL-1.1.json", - "referenceNumber": "315", - "name": "SIL Open Font License 1.1", - "licenseId": "OFL-1.1", - "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", - "https://opensource.org/licenses/OFL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./OGL-UK-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OGL-UK-1.0.json", - "referenceNumber": "116", - "name": "Open Government Licence v1.0", - "licenseId": "OGL-UK-1.0", - "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/1/" - ], - "isOsiApproved": false - }, - { - "reference": "./OGL-UK-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OGL-UK-2.0.json", - "referenceNumber": "289", - "name": "Open Government Licence v2.0", - "licenseId": "OGL-UK-2.0", - "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/2/" - ], - "isOsiApproved": false - }, - { - "reference": "./OGL-UK-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OGL-UK-3.0.json", - "referenceNumber": "226", - "name": "Open Government Licence v3.0", - "licenseId": "OGL-UK-3.0", - "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" - ], - "isOsiApproved": false - }, - { - "reference": "./OGTSL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OGTSL.json", - "referenceNumber": "125", - "name": "Open Group Test Suite License", - "licenseId": "OGTSL", - "seeAlso": [ - "http://www.opengroup.org/testing/downloads/The_Open_Group_TSL.txt", - "https://opensource.org/licenses/OGTSL" - ], - "isOsiApproved": true - }, - { - "reference": "./OLDAP-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-1.1.json", - "referenceNumber": "97", - "name": "Open LDAP Public License v1.1", - "licenseId": "OLDAP-1.1", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d806557a5ad59804ef3a44d5abfbe91d706b0791f" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-1.2.json", - "referenceNumber": "190", - "name": "Open LDAP Public License v1.2", - "licenseId": "OLDAP-1.2", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d42b0383c50c299977b5893ee695cf4e486fb0dc7" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-1.3.json", - "referenceNumber": "106", - "name": "Open LDAP Public License v1.3", - "licenseId": "OLDAP-1.3", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003de5f8117f0ce088d0bd7a8e18ddf37eaa40eb09b1" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-1.4.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-1.4.json", - "referenceNumber": "30", - "name": "Open LDAP Public License v1.4", - "licenseId": "OLDAP-1.4", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dc9f95c2f3f2ffb5e0ae55fe7388af75547660941" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.json", - "referenceNumber": "266", - "name": "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", - "licenseId": "OLDAP-2.0", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcbf50f4e1185a21abd4c0a54d3f4341fe28f36ea" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.0.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.1.json", - "referenceNumber": "350", - "name": "Open LDAP Public License v2.0.1", - "licenseId": "OLDAP-2.0.1", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db6d68acd14e51ca3aab4428bf26522aa74873f0e" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.1.json", - "referenceNumber": "154", - "name": "Open LDAP Public License v2.1", - "licenseId": "OLDAP-2.1", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db0d176738e96a0d3b9f85cb51e140a86f21be715" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.json", - "referenceNumber": "362", - "name": "Open LDAP Public License v2.2", - "licenseId": "OLDAP-2.2", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d470b0c18ec67621c85881b2733057fecf4a1acc3" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.1.json", - "referenceNumber": "339", - "name": "Open LDAP Public License v2.2.1", - "licenseId": "OLDAP-2.2.1", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d4bc786f34b50aa301be6f5600f58a980070f481e" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.2.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.2.json", - "referenceNumber": "199", - "name": "Open LDAP Public License 2.2.2", - "licenseId": "OLDAP-2.2.2", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003ddf2cc1e21eb7c160695f5b7cffd6296c151ba188" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.3.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.3.json", - "referenceNumber": "164", - "name": "Open LDAP Public License v2.3", - "licenseId": "OLDAP-2.3", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dd32cf54a32d581ab475d23c810b0a7fbaf8d63c3" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.4.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.4.json", - "referenceNumber": "66", - "name": "Open LDAP Public License v2.4", - "licenseId": "OLDAP-2.4", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcd1284c4a91a8a380d904eee68d1583f989ed386" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.5.json", - "referenceNumber": "183", - "name": "Open LDAP Public License v2.5", - "licenseId": "OLDAP-2.5", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d6852b9d90022e8593c98205413380536b1b5a7cf" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.6.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.6.json", - "referenceNumber": "61", - "name": "Open LDAP Public License v2.6", - "licenseId": "OLDAP-2.6", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d1cae062821881f41b73012ba816434897abf4205" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.7.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.7.json", - "referenceNumber": "123", - "name": "Open LDAP Public License v2.7", - "licenseId": "OLDAP-2.7", - "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d47c2415c1df81556eeb39be6cad458ef87c534a2" - ], - "isOsiApproved": false - }, - { - "reference": "./OLDAP-2.8.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.8.json", - "referenceNumber": "37", - "name": "Open LDAP Public License v2.8", - "licenseId": "OLDAP-2.8", - "seeAlso": [ - "http://www.openldap.org/software/release/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./OML.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OML.json", - "referenceNumber": "65", - "name": "Open Market License", - "licenseId": "OML", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Open_Market_License" - ], - "isOsiApproved": false - }, - { - "reference": "./OPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OPL-1.0.json", - "referenceNumber": "343", - "name": "Open Public License v1.0", - "licenseId": "OPL-1.0", - "seeAlso": [ - "http://old.koalateam.com/jackaroo/OPL_1_0.TXT", - "https://fedoraproject.org/wiki/Licensing/Open_Public_License" - ], - "isOsiApproved": false - }, - { - "reference": "./OSET-PL-2.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OSET-PL-2.1.json", - "referenceNumber": "291", - "name": "OSET Public License version 2.1", - "licenseId": "OSET-PL-2.1", - "seeAlso": [ - "http://www.osetfoundation.org/public-license", - "https://opensource.org/licenses/OPL-2.1" - ], - "isOsiApproved": true - }, - { - "reference": "./OSL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-1.0.json", - "referenceNumber": "85", - "name": "Open Software License 1.0", - "licenseId": "OSL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/OSL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./OSL-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-1.1.json", - "referenceNumber": "334", - "name": "Open Software License 1.1", - "licenseId": "OSL-1.1", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/OSL1.1" - ], - "isOsiApproved": false - }, - { - "reference": "./OSL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-2.0.json", - "referenceNumber": "20", - "name": "Open Software License 2.0", - "licenseId": "OSL-2.0", - "seeAlso": [ - "http://web.archive.org/web/20041020171434/http://www.rosenlaw.com/osl2.0.html" - ], - "isOsiApproved": true - }, - { - "reference": "./OSL-2.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-2.1.json", - "referenceNumber": "24", - "name": "Open Software License 2.1", - "licenseId": "OSL-2.1", - "seeAlso": [ - "http://web.archive.org/web/20050212003940/http://www.rosenlaw.com/osl21.htm", - "https://opensource.org/licenses/OSL-2.1" - ], - "isOsiApproved": true - }, - { - "reference": "./OSL-3.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-3.0.json", - "referenceNumber": "100", - "name": "Open Software License 3.0", - "licenseId": "OSL-3.0", - "seeAlso": [ - "https://web.archive.org/web/20120101081418/http://rosenlaw.com:80/OSL3.0.htm", - "https://opensource.org/licenses/OSL-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./OpenSSL.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OpenSSL.json", - "referenceNumber": "249", - "name": "OpenSSL License", - "licenseId": "OpenSSL", - "seeAlso": [ - "http://www.openssl.org/source/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./PDDL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/PDDL-1.0.json", - "referenceNumber": "14", - "name": "ODC Public Domain Dedication \u0026 License 1.0", - "licenseId": "PDDL-1.0", - "seeAlso": [ - "http://opendatacommons.org/licenses/pddl/1.0/" - ], - "isOsiApproved": false - }, - { - "reference": "./PHP-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/PHP-3.0.json", - "referenceNumber": "385", - "name": "PHP License v3.0", - "licenseId": "PHP-3.0", - "seeAlso": [ - "http://www.php.net/license/3_0.txt", - "https://opensource.org/licenses/PHP-3.0" - ], - "isOsiApproved": true - }, - { - "reference": "./PHP-3.01.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/PHP-3.01.json", - "referenceNumber": "316", - "name": "PHP License v3.01", - "licenseId": "PHP-3.01", - "seeAlso": [ - "http://www.php.net/license/3_01.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./Parity-6.0.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Parity-6.0.0.json", - "referenceNumber": "91", - "name": "The Parity Public License 6.0.0", - "licenseId": "Parity-6.0.0", - "seeAlso": [ - "https://paritylicense.com/versions/6.0.0.html" - ], - "isOsiApproved": false - }, - { - "reference": "./Plexus.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Plexus.json", - "referenceNumber": "225", - "name": "Plexus Classworlds License", - "licenseId": "Plexus", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Plexus_Classworlds_License" - ], - "isOsiApproved": false - }, - { - "reference": "./PostgreSQL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/PostgreSQL.json", - "referenceNumber": "247", - "name": "PostgreSQL License", - "licenseId": "PostgreSQL", - "seeAlso": [ - "http://www.postgresql.org/about/licence", - "https://opensource.org/licenses/PostgreSQL" - ], - "isOsiApproved": true - }, - { - "reference": "./Python-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Python-2.0.json", - "referenceNumber": "35", - "name": "Python License 2.0", - "licenseId": "Python-2.0", - "seeAlso": [ - "https://opensource.org/licenses/Python-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./QPL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/QPL-1.0.json", - "referenceNumber": "27", - "name": "Q Public License 1.0", - "licenseId": "QPL-1.0", - "seeAlso": [ - "http://doc.qt.nokia.com/3.3/license.html", - "https://opensource.org/licenses/QPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./Qhull.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Qhull.json", - "referenceNumber": "67", - "name": "Qhull License", - "licenseId": "Qhull", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Qhull" - ], - "isOsiApproved": false - }, - { - "reference": "./RHeCos-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RHeCos-1.1.json", - "referenceNumber": "149", - "name": "Red Hat eCos Public License v1.1", - "licenseId": "RHeCos-1.1", - "seeAlso": [ - "http://ecos.sourceware.org/old-license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./RPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RPL-1.1.json", - "referenceNumber": "269", - "name": "Reciprocal Public License 1.1", - "licenseId": "RPL-1.1", - "seeAlso": [ - "https://opensource.org/licenses/RPL-1.1" - ], - "isOsiApproved": true - }, - { - "reference": "./RPL-1.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RPL-1.5.json", - "referenceNumber": "227", - "name": "Reciprocal Public License 1.5", - "licenseId": "RPL-1.5", - "seeAlso": [ - "https://opensource.org/licenses/RPL-1.5" - ], - "isOsiApproved": true - }, - { - "reference": "./RPSL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/RPSL-1.0.json", - "referenceNumber": "273", - "name": "RealNetworks Public Source License v1.0", - "licenseId": "RPSL-1.0", - "seeAlso": [ - "https://helixcommunity.org/content/rpsl", - "https://opensource.org/licenses/RPSL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./RSA-MD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RSA-MD.json", - "referenceNumber": "82", - "name": "RSA Message-Digest License ", - "licenseId": "RSA-MD", - "seeAlso": [ - "http://www.faqs.org/rfcs/rfc1321.html" - ], - "isOsiApproved": false - }, - { - "reference": "./RSCPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RSCPL.json", - "referenceNumber": "211", - "name": "Ricoh Source Code Public License", - "licenseId": "RSCPL", - "seeAlso": [ - "http://wayback.archive.org/web/20060715140826/http://www.risource.org/RPL/RPL-1.0A.shtml", - "https://opensource.org/licenses/RSCPL" - ], - "isOsiApproved": true - }, - { - "reference": "./Rdisc.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Rdisc.json", - "referenceNumber": "295", - "name": "Rdisc License", - "licenseId": "Rdisc", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Rdisc_License" - ], - "isOsiApproved": false - }, - { - "reference": "./Ruby.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Ruby.json", - "referenceNumber": "263", - "name": "Ruby License", - "licenseId": "Ruby", - "seeAlso": [ - "http://www.ruby-lang.org/en/LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./SAX-PD.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SAX-PD.json", - "referenceNumber": "140", - "name": "Sax Public Domain Notice", - "licenseId": "SAX-PD", - "seeAlso": [ - "http://www.saxproject.org/copying.html" - ], - "isOsiApproved": false - }, - { - "reference": "./SCEA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SCEA.json", - "referenceNumber": "16", - "name": "SCEA Shared Source License", - "licenseId": "SCEA", - "seeAlso": [ - "http://research.scea.com/scea_shared_source_license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./SGI-B-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SGI-B-1.0.json", - "referenceNumber": "90", - "name": "SGI Free Software License B v1.0", - "licenseId": "SGI-B-1.0", - "seeAlso": [ - "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.1.0.html" - ], - "isOsiApproved": false - }, - { - "reference": "./SGI-B-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SGI-B-1.1.json", - "referenceNumber": "241", - "name": "SGI Free Software License B v1.1", - "licenseId": "SGI-B-1.1", - "seeAlso": [ - "http://oss.sgi.com/projects/FreeB/" - ], - "isOsiApproved": false - }, - { - "reference": "./SGI-B-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/SGI-B-2.0.json", - "referenceNumber": "272", - "name": "SGI Free Software License B v2.0", - "licenseId": "SGI-B-2.0", - "seeAlso": [ - "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf" - ], - "isOsiApproved": false - }, - { - "reference": "./SHL-0.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SHL-0.5.json", - "referenceNumber": "72", - "name": "Solderpad Hardware License v0.5", - "licenseId": "SHL-0.5", - "seeAlso": [ - "https://solderpad.org/licenses/SHL-0.5/" - ], - "isOsiApproved": false - }, - { - "reference": "./SHL-0.51.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SHL-0.51.json", - "referenceNumber": "314", - "name": "Solderpad Hardware License, Version 0.51", - "licenseId": "SHL-0.51", - "seeAlso": [ - "https://solderpad.org/licenses/SHL-0.51/" - ], - "isOsiApproved": false - }, - { - "reference": "./SISSL.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/SISSL.json", - "referenceNumber": "74", - "name": "Sun Industry Standards Source License v1.1", - "licenseId": "SISSL", - "seeAlso": [ - "http://www.openoffice.org/licenses/sissl_license.html", - "https://opensource.org/licenses/SISSL" - ], - "isOsiApproved": true - }, - { - "reference": "./SISSL-1.2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SISSL-1.2.json", - "referenceNumber": "7", - "name": "Sun Industry Standards Source License v1.2", - "licenseId": "SISSL-1.2", - "seeAlso": [ - "http://gridscheduler.sourceforge.net/Gridengine_SISSL_license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./SMLNJ.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/SMLNJ.json", - "referenceNumber": "296", - "name": "Standard ML of New Jersey License", - "licenseId": "SMLNJ", - "seeAlso": [ - "https://www.smlnj.org/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./SMPPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SMPPL.json", - "referenceNumber": "127", - "name": "Secure Messaging Protocol Public License", - "licenseId": "SMPPL", - "seeAlso": [ - "https://github.com/dcblake/SMP/blob/master/Documentation/License.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./SNIA.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SNIA.json", - "referenceNumber": "230", - "name": "SNIA Public License 1.1", - "licenseId": "SNIA", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/SNIA_Public_License" - ], - "isOsiApproved": false - }, - { - "reference": "./SPL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/SPL-1.0.json", - "referenceNumber": "54", - "name": "Sun Public License v1.0", - "licenseId": "SPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/SPL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./SSPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SSPL-1.0.json", - "referenceNumber": "356", - "name": "Server Side Public License, v 1", - "licenseId": "SSPL-1.0", - "seeAlso": [ - "https://www.mongodb.com/licensing/server-side-public-license" - ], - "isOsiApproved": false - }, - { - "reference": "./SWL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SWL.json", - "referenceNumber": "208", - "name": "Scheme Widget Library (SWL) Software License Agreement", - "licenseId": "SWL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/SWL" - ], - "isOsiApproved": false - }, - { - "reference": "./Saxpath.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Saxpath.json", - "referenceNumber": "18", - "name": "Saxpath License", - "licenseId": "Saxpath", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Saxpath_License" - ], - "isOsiApproved": false - }, - { - "reference": "./Sendmail.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Sendmail.json", - "referenceNumber": "151", - "name": "Sendmail License", - "licenseId": "Sendmail", - "seeAlso": [ - "http://www.sendmail.com/pdfs/open_source/sendmail_license.pdf", - "https://web.archive.org/web/20160322142305/https://www.sendmail.com/pdfs/open_source/sendmail_license.pdf" - ], - "isOsiApproved": false - }, - { - "reference": "./Sendmail-8.23.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Sendmail-8.23.json", - "referenceNumber": "41", - "name": "Sendmail License 8.23", - "licenseId": "Sendmail-8.23", - "seeAlso": [ - "https://www.proofpoint.com/sites/default/files/sendmail-license.pdf", - "https://web.archive.org/web/20181003101040/https://www.proofpoint.com/sites/default/files/sendmail-license.pdf" - ], - "isOsiApproved": false - }, - { - "reference": "./SimPL-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SimPL-2.0.json", - "referenceNumber": "184", - "name": "Simple Public License 2.0", - "licenseId": "SimPL-2.0", - "seeAlso": [ - "https://opensource.org/licenses/SimPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./Sleepycat.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Sleepycat.json", - "referenceNumber": "290", - "name": "Sleepycat License", - "licenseId": "Sleepycat", - "seeAlso": [ - "https://opensource.org/licenses/Sleepycat" - ], - "isOsiApproved": true - }, - { - "reference": "./Spencer-86.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Spencer-86.json", - "referenceNumber": "313", - "name": "Spencer License 86", - "licenseId": "Spencer-86", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License" - ], - "isOsiApproved": false - }, - { - "reference": "./Spencer-94.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Spencer-94.json", - "referenceNumber": "29", - "name": "Spencer License 94", - "licenseId": "Spencer-94", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License" - ], - "isOsiApproved": false - }, - { - "reference": "./Spencer-99.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Spencer-99.json", - "referenceNumber": "386", - "name": "Spencer License 99", - "licenseId": "Spencer-99", - "seeAlso": [ - "http://www.opensource.apple.com/source/tcl/tcl-5/tcl/generic/regfronts.c" - ], - "isOsiApproved": false - }, - { - "reference": "./StandardML-NJ.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/StandardML-NJ.json", - "referenceNumber": "219", - "name": "Standard ML of New Jersey License", - "licenseId": "StandardML-NJ", - "seeAlso": [ - "http://www.smlnj.org//license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./SugarCRM-1.1.3.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SugarCRM-1.1.3.json", - "referenceNumber": "292", - "name": "SugarCRM Public License v1.1.3", - "licenseId": "SugarCRM-1.1.3", - "seeAlso": [ - "http://www.sugarcrm.com/crm/SPL" - ], - "isOsiApproved": false - }, - { - "reference": "./TAPR-OHL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TAPR-OHL-1.0.json", - "referenceNumber": "267", - "name": "TAPR Open Hardware License v1.0", - "licenseId": "TAPR-OHL-1.0", - "seeAlso": [ - "https://www.tapr.org/OHL" - ], - "isOsiApproved": false - }, - { - "reference": "./TCL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TCL.json", - "referenceNumber": "265", - "name": "TCL/TK License", - "licenseId": "TCL", - "seeAlso": [ - "http://www.tcl.tk/software/tcltk/license.html", - "https://fedoraproject.org/wiki/Licensing/TCL" - ], - "isOsiApproved": false - }, - { - "reference": "./TCP-wrappers.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TCP-wrappers.json", - "referenceNumber": "274", - "name": "TCP Wrappers License", - "licenseId": "TCP-wrappers", - "seeAlso": [ - "http://rc.quest.com/topics/openssh/license.php#tcpwrappers" - ], - "isOsiApproved": false - }, - { - "reference": "./TMate.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TMate.json", - "referenceNumber": "253", - "name": "TMate Open Source License", - "licenseId": "TMate", - "seeAlso": [ - "http://svnkit.com/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./TORQUE-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TORQUE-1.1.json", - "referenceNumber": "171", - "name": "TORQUE v2.5+ Software License v1.1", - "licenseId": "TORQUE-1.1", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/TORQUEv1.1" - ], - "isOsiApproved": false - }, - { - "reference": "./TOSL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TOSL.json", - "referenceNumber": "360", - "name": "Trusster Open Source License", - "licenseId": "TOSL", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/TOSL" - ], - "isOsiApproved": false - }, - { - "reference": "./TU-Berlin-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TU-Berlin-1.0.json", - "referenceNumber": "373", - "name": "Technische Universitaet Berlin License 1.0", - "licenseId": "TU-Berlin-1.0", - "seeAlso": [ - "https://github.com/swh/ladspa/blob/7bf6f3799fdba70fda297c2d8fd9f526803d9680/gsm/COPYRIGHT" - ], - "isOsiApproved": false - }, - { - "reference": "./TU-Berlin-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TU-Berlin-2.0.json", - "referenceNumber": "391", - "name": "Technische Universitaet Berlin License 2.0", - "licenseId": "TU-Berlin-2.0", - "seeAlso": [ - "https://github.com/CorsixTH/deps/blob/fd339a9f526d1d9c9f01ccf39e438a015da50035/licences/libgsm.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./UPL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/UPL-1.0.json", - "referenceNumber": "205", - "name": "Universal Permissive License v1.0", - "licenseId": "UPL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/UPL" - ], - "isOsiApproved": true - }, - { - "reference": "./Unicode-DFS-2015.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2015.json", - "referenceNumber": "11", - "name": "Unicode License Agreement - Data Files and Software (2015)", - "licenseId": "Unicode-DFS-2015", - "seeAlso": [ - "https://web.archive.org/web/20151224134844/http://unicode.org/copyright.html" - ], - "isOsiApproved": false - }, - { - "reference": "./Unicode-DFS-2016.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2016.json", - "referenceNumber": "382", - "name": "Unicode License Agreement - Data Files and Software (2016)", - "licenseId": "Unicode-DFS-2016", - "seeAlso": [ - "http://www.unicode.org/copyright.html" - ], - "isOsiApproved": false - }, - { - "reference": "./Unicode-TOU.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Unicode-TOU.json", - "referenceNumber": "70", - "name": "Unicode Terms of Use", - "licenseId": "Unicode-TOU", - "seeAlso": [ - "http://www.unicode.org/copyright.html" - ], - "isOsiApproved": false - }, - { - "reference": "./Unlicense.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Unlicense.json", - "referenceNumber": "293", - "name": "The Unlicense", - "licenseId": "Unlicense", - "seeAlso": [ - "http://unlicense.org/" - ], - "isOsiApproved": false - }, - { - "reference": "./VOSTROM.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/VOSTROM.json", - "referenceNumber": "228", - "name": "VOSTROM Public License for Open Source", - "licenseId": "VOSTROM", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/VOSTROM" - ], - "isOsiApproved": false - }, - { - "reference": "./VSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/VSL-1.0.json", - "referenceNumber": "180", - "name": "Vovida Software License v1.0", - "licenseId": "VSL-1.0", - "seeAlso": [ - "https://opensource.org/licenses/VSL-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./Vim.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Vim.json", - "referenceNumber": "133", - "name": "Vim License", - "licenseId": "Vim", - "seeAlso": [ - "http://vimdoc.sourceforge.net/htmldoc/uganda.html" - ], - "isOsiApproved": false - }, - { - "reference": "./W3C.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/W3C.json", - "referenceNumber": "351", - "name": "W3C Software Notice and License (2002-12-31)", - "licenseId": "W3C", - "seeAlso": [ - "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html", - "https://opensource.org/licenses/W3C" - ], - "isOsiApproved": true - }, - { - "reference": "./W3C-19980720.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/W3C-19980720.json", - "referenceNumber": "323", - "name": "W3C Software Notice and License (1998-07-20)", - "licenseId": "W3C-19980720", - "seeAlso": [ - "http://www.w3.org/Consortium/Legal/copyright-software-19980720.html" - ], - "isOsiApproved": false - }, - { - "reference": "./W3C-20150513.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/W3C-20150513.json", - "referenceNumber": "51", - "name": "W3C Software Notice and Document License (2015-05-13)", - "licenseId": "W3C-20150513", - "seeAlso": [ - "https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document" - ], - "isOsiApproved": false - }, - { - "reference": "./WTFPL.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/WTFPL.json", - "referenceNumber": "368", - "name": "Do What The F*ck You Want To Public License", - "licenseId": "WTFPL", - "seeAlso": [ - "http://sam.zoy.org/wtfpl/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "./Watcom-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Watcom-1.0.json", - "referenceNumber": "177", - "name": "Sybase Open Watcom Public License 1.0", - "licenseId": "Watcom-1.0", - "seeAlso": [ - "https://opensource.org/licenses/Watcom-1.0" - ], - "isOsiApproved": true - }, - { - "reference": "./Wsuipa.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Wsuipa.json", - "referenceNumber": "135", - "name": "Wsuipa License", - "licenseId": "Wsuipa", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Wsuipa" - ], - "isOsiApproved": false - }, - { - "reference": "./X11.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/X11.json", - "referenceNumber": "188", - "name": "X11 License", - "licenseId": "X11", - "seeAlso": [ - "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3" - ], - "isOsiApproved": false - }, - { - "reference": "./XFree86-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/XFree86-1.1.json", - "referenceNumber": "243", - "name": "XFree86 License 1.1", - "licenseId": "XFree86-1.1", - "seeAlso": [ - "http://www.xfree86.org/current/LICENSE4.html" - ], - "isOsiApproved": false - }, - { - "reference": "./XSkat.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/XSkat.json", - "referenceNumber": "96", - "name": "XSkat License", - "licenseId": "XSkat", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/XSkat_License" - ], - "isOsiApproved": false - }, - { - "reference": "./Xerox.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Xerox.json", - "referenceNumber": "163", - "name": "Xerox License", - "licenseId": "Xerox", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Xerox" - ], - "isOsiApproved": false - }, - { - "reference": "./Xnet.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Xnet.json", - "referenceNumber": "388", - "name": "X.Net License", - "licenseId": "Xnet", - "seeAlso": [ - "https://opensource.org/licenses/Xnet" - ], - "isOsiApproved": true - }, - { - "reference": "./YPL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/YPL-1.0.json", - "referenceNumber": "174", - "name": "Yahoo! Public License v1.0", - "licenseId": "YPL-1.0", - "seeAlso": [ - "http://www.zimbra.com/license/yahoo_public_license_1.0.html" - ], - "isOsiApproved": false - }, - { - "reference": "./YPL-1.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/YPL-1.1.json", - "referenceNumber": "57", - "name": "Yahoo! Public License v1.1", - "licenseId": "YPL-1.1", - "seeAlso": [ - "http://www.zimbra.com/license/yahoo_public_license_1.1.html" - ], - "isOsiApproved": false - }, - { - "reference": "./ZPL-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ZPL-1.1.json", - "referenceNumber": "359", - "name": "Zope Public License 1.1", - "licenseId": "ZPL-1.1", - "seeAlso": [ - "http://old.zope.org/Resources/License/ZPL-1.1" - ], - "isOsiApproved": false - }, - { - "reference": "./ZPL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ZPL-2.0.json", - "referenceNumber": "78", - "name": "Zope Public License 2.0", - "licenseId": "ZPL-2.0", - "seeAlso": [ - "http://old.zope.org/Resources/License/ZPL-2.0", - "https://opensource.org/licenses/ZPL-2.0" - ], - "isOsiApproved": true - }, - { - "reference": "./ZPL-2.1.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ZPL-2.1.json", - "referenceNumber": "345", - "name": "Zope Public License 2.1", - "licenseId": "ZPL-2.1", - "seeAlso": [ - "http://old.zope.org/Resources/ZPL/" - ], - "isOsiApproved": false - }, - { - "reference": "./Zed.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Zed.json", - "referenceNumber": "248", - "name": "Zed License", - "licenseId": "Zed", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Zed" - ], - "isOsiApproved": false - }, - { - "reference": "./Zend-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Zend-2.0.json", - "referenceNumber": "198", - "name": "Zend License v2.0", - "licenseId": "Zend-2.0", - "seeAlso": [ - "https://web.archive.org/web/20130517195954/http://www.zend.com/license/2_00.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./Zimbra-1.3.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Zimbra-1.3.json", - "referenceNumber": "40", - "name": "Zimbra Public License v1.3", - "licenseId": "Zimbra-1.3", - "seeAlso": [ - "http://web.archive.org/web/20100302225219/http://www.zimbra.com/license/zimbra-public-license-1-3.html" - ], - "isOsiApproved": false - }, - { - "reference": "./Zimbra-1.4.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Zimbra-1.4.json", - "referenceNumber": "238", - "name": "Zimbra Public License v1.4", - "licenseId": "Zimbra-1.4", - "seeAlso": [ - "http://www.zimbra.com/legal/zimbra-public-license-1-4" - ], - "isOsiApproved": false - }, - { - "reference": "./Zlib.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Zlib.json", - "referenceNumber": "320", - "name": "zlib License", - "licenseId": "Zlib", - "seeAlso": [ - "http://www.zlib.net/zlib_license.html", - "https://opensource.org/licenses/Zlib" - ], - "isOsiApproved": true - }, - { - "reference": "./blessing.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/blessing.json", - "referenceNumber": "331", - "name": "SQLite Blessing", - "licenseId": "blessing", - "seeAlso": [ - "https://www.sqlite.org/src/artifact/e33a4df7e32d742a?ln\u003d4-9", - "https://sqlite.org/src/artifact/df5091916dbb40e6" - ], - "isOsiApproved": false - }, - { - "reference": "./bzip2-1.0.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.5.json", - "referenceNumber": "200", - "name": "bzip2 and libbzip2 License v1.0.5", - "licenseId": "bzip2-1.0.5", - "seeAlso": [ - "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html" - ], - "isOsiApproved": false - }, - { - "reference": "./bzip2-1.0.6.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.6.json", - "referenceNumber": "302", - "name": "bzip2 and libbzip2 License v1.0.6", - "licenseId": "bzip2-1.0.6", - "seeAlso": [ - "https://github.com/asimonov-im/bzip2/blob/master/LICENSE" - ], - "isOsiApproved": false - }, - { - "reference": "./copyleft-next-0.3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/copyleft-next-0.3.0.json", - "referenceNumber": "176", - "name": "copyleft-next 0.3.0", - "licenseId": "copyleft-next-0.3.0", - "seeAlso": [ - "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.0" - ], - "isOsiApproved": false - }, - { - "reference": "./copyleft-next-0.3.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/copyleft-next-0.3.1.json", - "referenceNumber": "347", - "name": "copyleft-next 0.3.1", - "licenseId": "copyleft-next-0.3.1", - "seeAlso": [ - "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.1" - ], - "isOsiApproved": false - }, - { - "reference": "./curl.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/curl.json", - "referenceNumber": "260", - "name": "curl License", - "licenseId": "curl", - "seeAlso": [ - "https://github.com/bagder/curl/blob/master/COPYING" - ], - "isOsiApproved": false - }, - { - "reference": "./diffmark.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/diffmark.json", - "referenceNumber": "367", - "name": "diffmark license", - "licenseId": "diffmark", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/diffmark" - ], - "isOsiApproved": false - }, - { - "reference": "./dvipdfm.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/dvipdfm.json", - "referenceNumber": "143", - "name": "dvipdfm License", - "licenseId": "dvipdfm", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/dvipdfm" - ], - "isOsiApproved": false - }, - { - "reference": "./eCos-2.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/eCos-2.0.json", - "referenceNumber": "329", - "name": "eCos license version 2.0", - "licenseId": "eCos-2.0", - "seeAlso": [ - "https://www.gnu.org/licenses/ecos-license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./eGenix.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/eGenix.json", - "referenceNumber": "204", - "name": "eGenix.com Public License 1.1.0", - "licenseId": "eGenix", - "seeAlso": [ - "http://www.egenix.com/products/eGenix.com-Public-License-1.1.0.pdf", - "https://fedoraproject.org/wiki/Licensing/eGenix.com_Public_License_1.1.0" - ], - "isOsiApproved": false - }, - { - "reference": "./gSOAP-1.3b.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/gSOAP-1.3b.json", - "referenceNumber": "346", - "name": "gSOAP Public License v1.3b", - "licenseId": "gSOAP-1.3b", - "seeAlso": [ - "http://www.cs.fsu.edu/~engelen/license.html" - ], - "isOsiApproved": false - }, - { - "reference": "./gnuplot.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/gnuplot.json", - "referenceNumber": "10", - "name": "gnuplot License", - "licenseId": "gnuplot", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Gnuplot" - ], - "isOsiApproved": false - }, - { - "reference": "./iMatix.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/iMatix.json", - "referenceNumber": "342", - "name": "iMatix Standard Function Library Agreement", - "licenseId": "iMatix", - "seeAlso": [ - "http://legacy.imatix.com/html/sfl/sfl4.htm#license" - ], - "isOsiApproved": false - }, - { - "reference": "./libpng-2.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/libpng-2.0.json", - "referenceNumber": "76", - "name": "PNG Reference Library version 2", - "licenseId": "libpng-2.0", - "seeAlso": [ - "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" - ], - "isOsiApproved": false - }, - { - "reference": "./libtiff.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/libtiff.json", - "referenceNumber": "220", - "name": "libtiff License", - "licenseId": "libtiff", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/libtiff" - ], - "isOsiApproved": false - }, - { - "reference": "./mpich2.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/mpich2.json", - "referenceNumber": "318", - "name": "mpich2 License", - "licenseId": "mpich2", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT" - ], - "isOsiApproved": false - }, - { - "reference": "./psfrag.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/psfrag.json", - "referenceNumber": "245", - "name": "psfrag License", - "licenseId": "psfrag", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/psfrag" - ], - "isOsiApproved": false - }, - { - "reference": "./psutils.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/psutils.json", - "referenceNumber": "126", - "name": "psutils License", - "licenseId": "psutils", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/psutils" - ], - "isOsiApproved": false - }, - { - "reference": "./wxWindows.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/wxWindows.json", - "referenceNumber": "86", - "name": "wxWindows Library License", - "licenseId": "wxWindows", - "seeAlso": [ - "https://opensource.org/licenses/WXwindows" - ], - "isOsiApproved": false - }, - { - "reference": "./xinetd.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/xinetd.json", - "referenceNumber": "146", - "name": "xinetd License", - "licenseId": "xinetd", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Xinetd_License" - ], - "isOsiApproved": false - }, - { - "reference": "./xpp.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/xpp.json", - "referenceNumber": "275", - "name": "XPP License", - "licenseId": "xpp", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/xpp" - ], - "isOsiApproved": false - }, - { - "reference": "./zlib-acknowledgement.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/zlib-acknowledgement.json", - "referenceNumber": "321", - "name": "zlib/libpng License with Acknowledgement", - "licenseId": "zlib-acknowledgement", - "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/ZlibWithAcknowledgement" - ], - "isOsiApproved": false - } - ], - "releaseDate": "2019-07-10" -} \ No newline at end of file diff --git a/spdx/package.py b/spdx/package.py deleted file mode 100644 index 2e48ae845..000000000 --- a/spdx/package.py +++ /dev/null @@ -1,316 +0,0 @@ -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import hashlib - -from six.moves import reduce - -from spdx import checksum -from spdx import creationinfo -from spdx import document -from spdx import utils - - -class Package(object): - - """ - Represent an analyzed Package. - Fields: - - name : Mandatory, string. - - spdx_id: Uniquely identify any element in an SPDX document which may be - referenced by other elements. Mandatory, one. Type: str. - - version: Optional, string. - - file_name: Optional, string. - - supplier: Optional, Organization or Person or NO_ASSERTION. - - originator: Optional, Organization or Person. - - download_location: Mandatory, URL as string. - - files_analyzed: Indicates whether the file content of this package has - been available for or subjected to analysis when creating the SPDX - document. If "false" indicates packages that represent metadata or URI - references to a project, product, artifact, distribution or a component. - If set to "false", the package must not contain any files. - Optional, boolean. - - homepage: Optional, URL as string or NONE or NO_ASSERTION. - - verif_code: Mandatory string. - - check_sum: Optional , spdx.checksum.Algorithm. - - source_info: Optional string. - - conc_lics: Mandatory spdx.document.License or spdx.utils.SPDXNone or - - spdx.utils.NoAssert. - - license_declared : Mandatory spdx.document.License or spdx.utils.SPDXNone or - - spdx.utils.NoAssert. - - license_comment : optional string. - - licenses_from_files: list of spdx.document.License or spdx.utils.SPDXNone or - - spdx.utils.NoAssert. - - cr_text: Copyright text, string , utils.NoAssert or utils.SPDXNone. Mandatory. - - summary: Optional str. - - description: Optional str. - - comment: Comments about the package being described, optional one. - Type: str - - files: List of files in package, atleast one. - - verif_exc_files : list of file names excluded from verification code or None. - - ext_pkg_refs : External references referenced within the given package. - Optional, one or many. Type: ExternalPackageRef - """ - - def __init__(self, name=None, spdx_id=None, download_location=None, - version=None, file_name=None, supplier=None, originator=None): - self.name = name - self.spdx_id = spdx_id - self.version = version - self.file_name = file_name - self.supplier = supplier - self.originator = originator - self.download_location = download_location - self.files_analyzed = None - self.homepage = None - self.verif_code = None - self.check_sum = None - self.source_info = None - self.conc_lics = None - self.license_declared = None - self.license_comment = None - self.licenses_from_files = [] - self.cr_text = None - self.summary = None - self.description = None - self.comment = None - self.files = [] - self.verif_exc_files = [] - self.pkg_ext_refs = [] - - def add_file(self, fil): - self.files.append(fil) - - def add_lics_from_file(self, lics): - self.licenses_from_files.append(lics) - - def add_exc_file(self, filename): - self.verif_exc_files.append(filename) - - def add_pkg_ext_refs(self, pkg_ext_ref): - self.pkg_ext_refs.append(pkg_ext_ref) - - def validate(self, messages=None): - """ - Validate the package fields. - Append user friendly error messages to the `messages` list. - """ - messages = self.validate_checksum(messages) - messages = self.validate_optional_str_fields(messages) - messages = self.validate_mandatory_str_fields(messages) - messages = self.validate_files(messages) - messages = self.validate_pkg_ext_refs(messages) - messages = self.validate_mandatory_fields(messages) - messages = self.validate_optional_fields(messages) - - return messages - - def validate_optional_fields(self, messages): - if self.originator and not isinstance(self.originator, (utils.NoAssert, creationinfo.Creator)): - messages = messages + [ - 'Package originator must be instance of ' - 'spdx.utils.NoAssert or spdx.creationinfo.Creator' - ] - - if self.supplier and not isinstance(self.supplier, (utils.NoAssert, creationinfo.Creator)): - messages = messages + [ - 'Package supplier must be instance of ' - 'spdx.utils.NoAssert or spdx.creationinfo.Creator' - ] - - return messages - - def validate_pkg_ext_refs(self, messages=None): - for ref in self.pkg_ext_refs: - if isinstance(ref, ExternalPackageRef): - messages = ref.validate(messages) - else: - messages = messages + [ - 'External package references must be of the type ' - 'spdx.package.ExternalPackageRef and not ' + str(type(ref)) - ] - - return messages - - def validate_mandatory_fields(self, messages): - if not isinstance(self.conc_lics, (utils.SPDXNone, utils.NoAssert, document.License)): - messages = messages + [ - 'Package concluded license must be instance of ' - 'spdx.utils.SPDXNone or spdx.utils.NoAssert or ' - 'spdx.document.License' - ] - - if not isinstance(self.license_declared, (utils.SPDXNone, utils.NoAssert, document.License)): - messages = messages + [ - 'Package declared license must be instance of ' - 'spdx.utils.SPDXNone or spdx.utils.NoAssert or ' - 'spdx.document.License' - ] - - # FIXME: this is obscure and unreadable - license_from_file_check = lambda prev, el: prev and isinstance(el, (document.License, utils.SPDXNone, utils.NoAssert)) - if not reduce(license_from_file_check, self.licenses_from_files, True): - messages = messages + [ - 'Each element in licenses_from_files must be instance of ' - 'spdx.utils.SPDXNone or spdx.utils.NoAssert or ' - 'spdx.document.License' - ] - - if not self.licenses_from_files: - messages = messages + [ - 'Package licenses_from_files can not be empty' - ] - - return messages - - def validate_files(self, messages): - if not self.files: - messages = messages + [ - 'Package must have at least one file.' - ] - else: - for f in self.files: - messages = f.validate(messages) - - return messages - - def validate_optional_str_fields(self, messages): - """Fields marked as optional and of type string in class - docstring must be of a type that provides __str__ method. - """ - FIELDS = [ - 'file_name', - 'version', - 'homepage', - 'source_info', - 'summary', - 'description', - 'comment' - ] - messages = self.validate_str_fields(FIELDS, True, messages) - - return messages - - def validate_mandatory_str_fields(self, messages): - """Fields marked as Mandatory and of type string in class - docstring must be of a type that provides __str__ method. - """ - FIELDS = ['name', 'spdx_id', 'download_location', 'verif_code', 'cr_text'] - messages = self.validate_str_fields(FIELDS, False, messages) - - return messages - - def validate_str_fields(self, fields, optional, messages): - """Helper for validate_mandatory_str_field and - validate_optional_str_fields""" - for field_str in fields: - field = getattr(self, field_str) - if field is not None: - # FIXME: this does not make sense??? - attr = getattr(field, '__str__', None) - if not callable(attr): - messages = messages + [ - '{0} must provide __str__ method.'.format(field) - ] - # Continue checking. - elif not optional: - messages = messages + [ - 'Package {0} can not be None.'.format(field_str) - ] - - return messages - - def validate_checksum(self, messages): - if not isinstance(self.check_sum, checksum.Algorithm): - messages = messages + [ - 'Package checksum must be instance of spdx.checksum.Algorithm' - ] - else: - if self.check_sum.identifier != 'SHA1': - messages = messages + ['File checksum algorithm must be SHA1'] - - return messages - - def calc_verif_code(self): - hashes = [] - - for file_entry in self.files: - if (isinstance(file_entry.chk_sum, checksum.Algorithm) and - file_entry.chk_sum.identifier == 'SHA1'): - sha1 = file_entry.chk_sum.value - else: - sha1 = file_entry.calc_chksum() - hashes.append(sha1) - - hashes.sort() - - sha1 = hashlib.sha1() - sha1.update(''.join(hashes).encode('utf-8')) - return sha1.hexdigest() - - def has_optional_field(self, field): - return getattr(self, field, None) is not None - - -class ExternalPackageRef(object): - """ - An External Reference allows a Package to reference an external source of - additional information, metadata, enumerations, asset identifiers, or - downloadable content believed to be relevant to the Package. - Fields: - - category: "SECURITY" or "PACKAGE-MANAGER" or "OTHER". - - pkg_ext_ref_type: A unique string containing letters, numbers, ".","-". - - locator: A unique string with no spaces necessary to access the - package-specific information, metadata, or content within the target - location. - - comment: To provide information about the purpose and target of the - reference. - """ - - def __init__(self, category=None, pkg_ext_ref_type=None, locator=None, - comment=None): - self.category = category - self.pkg_ext_ref_type = pkg_ext_ref_type - self.locator = locator - self.comment = comment - - def validate(self, messages=None): - """ - Validate all fields of the ExternalPackageRef class and update the - messages list with user friendly error messages for display. - """ - messages = self.validate_category(messages) - messages = self.validate_pkg_ext_ref_type(messages) - messages = self.validate_locator(messages) - - return messages - - def validate_category(self, messages=None): - if self.category is None: - messages = messages + ['ExternalPackageRef has no category.'] - - return messages - - def validate_pkg_ext_ref_type(self, messages=None): - if self.pkg_ext_ref_type is None: - messages = messages + ['ExternalPackageRef has no type.'] - - return messages - - def validate_locator(self, messages=None): - if self.locator is None: - messages = messages + ['ExternalPackageRef has no locator.'] - - return messages diff --git a/spdx/parsers/__init__.py b/spdx/parsers/__init__.py deleted file mode 100644 index ba32848f0..000000000 --- a/spdx/parsers/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. diff --git a/spdx/parsers/builderexceptions.py b/spdx/parsers/builderexceptions.py deleted file mode 100644 index 489fb162a..000000000 --- a/spdx/parsers/builderexceptions.py +++ /dev/null @@ -1,35 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - - -class BuilderException(Exception): - """Builder exception base class.""" - pass - - -class CardinalityError(BuilderException): - def __init__(self, msg): - self.msg = msg - - -class SPDXValueError(BuilderException): - def __init__(self, msg): - self.msg = msg - - -class OrderError(BuilderException): - def __init__(self, msg): - self.msg = msg diff --git a/spdx/parsers/jsonparser.py b/spdx/parsers/jsonparser.py deleted file mode 100644 index 26b159c64..000000000 --- a/spdx/parsers/jsonparser.py +++ /dev/null @@ -1,33 +0,0 @@ - -# Copyright (c) Xavier Figueroa -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import json - -from spdx.parsers import jsonyamlxml - - -class Parser(jsonyamlxml.Parser): - """ - Wrapper class for jsonyamlxml.Parser to provide an interface similar to - RDF and TV Parser classes (i.e., spdx.parsers..Parser) for JSON parser. - It also avoids to repeat jsonyamlxml.Parser.parse code for JSON, YAML and XML parsers - """ - def __init__(self, builder, logger): - super(Parser, self).__init__(builder, logger) - - def parse(self, file): - self.document_object = json.load(file).get('Document') - return super(Parser, self).parse() diff --git a/spdx/parsers/jsonyamlxml.py b/spdx/parsers/jsonyamlxml.py deleted file mode 100644 index 601b3c842..000000000 --- a/spdx/parsers/jsonyamlxml.py +++ /dev/null @@ -1,1399 +0,0 @@ - -# Copyright (c) Xavier Figueroa -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import six - -from spdx import document -from spdx.document import LicenseConjunction -from spdx.document import LicenseDisjunction -from spdx.parsers.builderexceptions import SPDXValueError, CardinalityError, OrderError -from spdx.parsers import rdf -from spdx import utils -from spdx.utils import UnKnown - - -ERROR_MESSAGES = rdf.ERROR_MESSAGES - - -class BaseParser(object): - def __init__(self, builder, logger): - self.builder = builder - self.logger = logger - - def order_error(self, first_tag, second_tag): - """ - Helper method for logging an OrderError raised. - - first_tag: field to be added - - second_tag: required field - """ - self.error = True - msg = '{0} Can not appear before {1}'.format(first_tag, second_tag) - self.logger.log(msg) - - def more_than_one_error(self, field): - """ - Helper method for logging an CardinalityError raised. - - field: field/property that has been already defined. - """ - msg = 'More than one {0} defined.'.format(field) - self.logger.log(msg) - self.error = True - - def value_error(self, key, bad_value): - """ - Helper method for logging an SPDXValueError raised. - It reports a value error using ERROR_MESSAGES dict. - - key: key to use for ERROR_MESSAGES. If not present, a default message is logged - - bad_value: malformed value - """ - msg = ERROR_MESSAGES.get(key) - if msg: - self.logger.log(msg.format(bad_value)) - else: - msg = "'{0}' is not a valid value for {1}".format(bad_value, key) - self.logger.log(msg) - self.error = True - -class CreationInfoParser(BaseParser): - def __init__(self, builder, logger): - super(CreationInfoParser, self).__init__(builder, logger) - - def parse_creation_info(self, creation_info): - """ - Parse Creation Information fields - - creation_info: Python dict with Creation Information fields in it - """ - if isinstance(creation_info, dict): - self.parse_creation_info_comment(creation_info.get('comment')) - self.parse_creation_info_lic_list_version(creation_info.get('licenseListVersion')) - self.parse_creation_info_created(creation_info.get('created')) - self.parse_creation_info_creators(creation_info.get('creators')) - else: - self.value_error('CREATION_INFO_SECTION', creation_info) - - def parse_creation_info_comment(self, comment): - """ - Parse CreationInfo comment - - comment: Python str/unicode - """ - if isinstance(comment, six.string_types): - try: - return self.builder.set_creation_comment(self.document, comment) - except CardinalityError: - self.more_than_one_error('CreationInfo comment') - elif comment is not None: - self.value_error('CREATION_COMMENT', comment) - - def parse_creation_info_lic_list_version(self, license_list_version): - """ - Parse CreationInfo license list version - - license_list_version: Python str/unicode - """ - if isinstance(license_list_version, six.string_types): - try: - return self.builder.set_lics_list_ver(self.document, license_list_version) - except SPDXValueError: - raise - self.value_error('LL_VALUE', license_list_version) - except CardinalityError: - self.more_than_one_error('CreationInfo licenseListVersion') - elif license_list_version is not None: - self.value_error('LL_VALUE', license_list_version) - - def parse_creation_info_created(self, created): - """ - Parse CreationInfo creation date - - created: Python str/unicode (ISO-8601 representation of datetime) - """ - if isinstance(created, six.string_types): - try: - return self.builder.set_created_date(self.document, created) - except SPDXValueError: - self.value_error('CREATED_VALUE', created) - except CardinalityError: - self.more_than_one_error('CreationInfo created') - else: - self.value_error('CREATED_VALUE', created) - - def parse_creation_info_creators(self, creators): - """ - Parse CreationInfo creators - - creators: Python list of creators (str/unicode) - """ - if isinstance(creators, list): - for creator in creators: - if isinstance(creator, six.string_types): - entity = self.builder.create_entity(self.document, creator) - try: - self.builder.add_creator(self.document, entity) - except SPDXValueError: - self.value_error('CREATOR_VALUE', creator) - else: - self.value_error('CREATOR_VALUE', creator) - else: - self.value_error('CREATORS_SECTION', creators) - -class ExternalDocumentRefsParser(BaseParser): - def __init__(self, builder, logger): - super(ExternalDocumentRefsParser, self).__init__(builder, logger) - - def parse_external_document_refs(self, external_document_refs): - """ - Parse External Document References fields - - external_document_refs: Python list with External Document References dicts in it - """ - if isinstance(external_document_refs, list): - for external_document_ref in external_document_refs: - if isinstance(external_document_ref, dict): - self.parse_ext_doc_ref_id(external_document_ref.get('externalDocumentId')) - self.parse_ext_doc_ref_namespace(external_document_ref.get('spdxDocumentNamespace')) - self.parse_ext_doc_ref_chksum(external_document_ref.get('checksum')) - else: - self.value_error('EXT_DOC_REF', external_document_ref) - elif external_document_refs is not None: - self.value_error('EXT_DOC_REFS_SECTION', external_document_refs) - - def parse_ext_doc_ref_id(self, ext_doc_ref_id): - """ - Parse ExternalDocumentReference id - ext_doc_ref_id: Python str/unicode - """ - if isinstance(ext_doc_ref_id, six.string_types): - return self.builder.set_ext_doc_id(self.document, ext_doc_ref_id) - self.value_error('EXT_DOC_REF_ID', ext_doc_ref_id) - return self.builder.set_ext_doc_id(self.document, 'dummy_ext_doc_ref') - # ext_doc_ref_id is set even if it is None or not string. If weren't, the other attributes - # would be added to the ex_doc_ref previously added. - # Another approach is to skip the whole ex_doc_ref itself - - def parse_ext_doc_ref_namespace(self, namespace): - """ - Parse ExternalDocumentReference namespace - namespace: Python str/unicode - """ - if isinstance(namespace, six.string_types): - try: - return self.builder.set_spdx_doc_uri(self.document, namespace) - except SPDXValueError: - self.value_error('EXT_DOC_REF_VALUE', namespace) - else: - self.value_error('EXT_DOC_REF_VALUE', namespace) - - def parse_ext_doc_ref_chksum(self, chksum): - """ - Parse ExternalDocumentReference checksum - chksum: Python dict('algorithm':str/unicode, 'value':str/unicode) - """ - if isinstance(chksum, dict): - value = chksum.get('value') - if isinstance(value, six.string_types): - try: - return self.builder.set_chksum(self.document, value) - except SPDXValueError: - self.value_error('CHECKSUM_VALUE', value) - else: - self.value_error('CHECKSUM_VALUE', value) - else: - self.value_error('CHECKSUM_FIELD', chksum) - -class LicenseParser(BaseParser): - - def __init__(self, builder, logger): - super(LicenseParser, self).__init__(builder, logger) - - def parse_extracted_license_info(self, extracted_license_info): - """ - Parse Extracted Lisence Information fields - - extracted_license_info: Python list with Extracted Lisence Information dicts in it - """ - if isinstance(extracted_license_info, list): - for extracted_license in extracted_license_info: - if isinstance(extracted_license, dict): - if self.parse_ext_lic_id(extracted_license.get('licenseId')): - self.parse_ext_lic_name(extracted_license.get('name')) - self.parse_ext_lic_comment(extracted_license.get('comment')) - self.parse_ext_lic_text(extracted_license.get('extractedText')) - self.parse_ext_lic_cross_refs(extracted_license.get('seeAlso')) - else: - self.value_error('EXTR_LIC', extracted_license) - - def parse_ext_lic_id(self, ext_lic_id): - """ - Parse ExtractedLicenseInformation id - ext_lic_id: Python str/unicode - """ - if isinstance(ext_lic_id, six.string_types): - try: - return self.builder.set_lic_id(self.document, ext_lic_id) - except SPDXValueError: - self.value_error('EXTR_LIC_ID', ext_lic_id) - else: - self.value_error('EXTR_LIC_ID', ext_lic_id) - - def parse_ext_lic_name(self, ext_lic_name): - """ - Parse ExtractedLicenseInformation name - ext_lic_name: Python str/unicode - """ - try: - return self.builder.set_lic_name(self.document, ext_lic_name) - except SPDXValueError: - self.value_error('EXTR_LIC_NAME', ext_lic_name) - except CardinalityError: - self.more_than_one_error('ExtractedLicense name') - except OrderError: - self.order_error('ExtractedLicense name', 'ExtractedLicense id') - - def parse_ext_lic_comment(self, ext_lic_comment): - """ - Parse ExtractedLicenseInformation comment - ext_lic_comment: Python str/unicode - """ - if isinstance(ext_lic_comment, six.string_types): - try: - return self.builder.set_lic_comment(self.document, ext_lic_comment) - except CardinalityError: - self.more_than_one_error('ExtractedLicense comment') - except OrderError: - self.order_error('ExtractedLicense comment', 'ExtractedLicense id') - elif ext_lic_comment is not None: - self.value_error('EXTR_LIC_COMMENT', ext_lic_comment) - - def parse_ext_lic_text(self, ext_lic_text): - """ - Parse ExtractedLicenseInformation text - ext_lic_text: Python str/unicode - """ - if isinstance(ext_lic_text, six.string_types): - try: - return self.builder.set_lic_text(self.document, ext_lic_text) - except CardinalityError: - self.more_than_one_error('ExtractedLicense text') - except OrderError: - self.order_error('ExtractedLicense text', 'ExtractedLicense id') - else: - self.value_error('EXTR_LIC_TXT', ext_lic_text) - - def parse_ext_lic_cross_refs(self, cross_refs): - """ - Parse ExtractedLicenseInformation cross references - cross_refs: Python list of cross references (str/unicode) - """ - if isinstance(cross_refs, list): - for cross_ref in cross_refs: - if isinstance(cross_ref, six.string_types): - try: - self.builder.add_lic_xref(self.document, cross_ref) - except OrderError: - self.order_error('ExtractedLicense cross references', 'ExtractedLicense id') - else: - self.value_error('CROSS_REF', cross_ref) - - def replace_license(self, license_object): - if isinstance(license_object, LicenseConjunction): - return LicenseConjunction(self.replace_license(license_object.license_1), self.replace_license(license_object.license_2)) - elif isinstance(license_object, LicenseDisjunction): - return LicenseDisjunction(self.replace_license(license_object.license_1), self.replace_license(license_object.license_2)) - else: - license_objects = list(filter(lambda lic: lic.identifier == license_object.identifier, self.document.extracted_licenses)) - return license_objects[-1] if license_objects else license_object - -class AnnotationParser(BaseParser): - def __init__(self, builder, logger): - super(AnnotationParser, self).__init__(builder, logger) - - def parse_annotations(self, annotations): - """ - Parse Annotation Information fields - - annotations: Python list with Annotation Information dicts in it - """ - if isinstance(annotations, list): - for annotation in annotations: - if isinstance(annotation, dict): - if self.parse_annotation_annotator(annotation.get('annotator')): - self.parse_annotation_date(annotation.get('annotationDate')) - self.parse_annotation_comment(annotation.get('comment')) - self.parse_annotation_type(annotation.get('annotationType')) - self.parse_annotation_id(annotation.get('id')) - else: - self.value_error('ANNOTATION', annotation) - - def parse_annotation_annotator(self, annotator): - """ - Parse Annotation annotator - - annotator: Python str/unicode - """ - if isinstance(annotator, six.string_types): - entity = self.builder.create_entity(self.document, annotator) - try: - return self.builder.add_annotator(self.document, entity) - except SPDXValueError: - self.value_error('ANNOTATOR_VALUE', annotator) - else: - self.value_error('ANNOTATOR_VALUE', annotator) - - - def parse_annotation_date(self, date): - """ - Parse Annotation date - - date: Python str/unicode (ISO-8601 representation of datetime) - """ - if isinstance(date, six.string_types): - try: - return self.builder.add_annotation_date(self.document, date) - except SPDXValueError: - self.value_error('ANNOTATION_DATE', date) - except CardinalityError: - self.more_than_one_error('Annotation date') - except OrderError: - self.order_error('ANNOTATION_DATE', 'ANNOTATOR_VALUE') - else: - self.value_error('ANNOTATION_DATE', date) - - def parse_annotation_comment(self, comment): - """ - Parse Annotation comment - - comment: Python str/unicode - """ - if isinstance(comment, six.string_types): - try: - return self.builder.add_annotation_comment(self.document, comment) - except CardinalityError: - self.more_than_one_error('Annotation comment') - except OrderError: - self.order_error('ANNOTATION_COMMENT', 'ANNOTATOR_VALUE') - else: - self.value_error('ANNOTATION_COMMENT', comment) - - def parse_annotation_type(self, annotation_type): - """ - Parse Annotation type - - annotation_type: Python str/unicode (REVIEW or OTHER) - """ - if isinstance(annotation_type, six.string_types): - try: - return self.builder.add_annotation_type(self.document, annotation_type) - except SPDXValueError: - self.value_error('ANNOTATION_TYPE', annotation_type) - except CardinalityError: - self.more_than_one_error('ANNOTATION_TYPE') - except OrderError: - self.order_error('ANNOTATION_TYPE', 'ANNOTATOR_VALUE') - else: - self.value_error('ANNOTATION_TYPE', annotation_type) - - def parse_annotation_id(self, annotation_id): - """ - Parse Annotation id - - annotation_id: Python str/unicode - """ - if isinstance(annotation_id, six.string_types): - try: - return self.builder.set_annotation_spdx_id(self.document, annotation_id) - except CardinalityError: - self.more_than_one_error('ANNOTATION_ID') - except OrderError: - self.order_error('ANNOTATION_ID', 'ANNOTATOR_VALUE') - else: - self.value_error('ANNOTATION_ID', annotation_id) - -class SnippetParser(BaseParser): - def __init__(self, builder, logger): - super(SnippetParser, self).__init__(builder, logger) - - def parse_snippets(self, snippets): - """ - Parse Snippet Information fields - - snippets: Python list with Snippet Information dicts in it - """ - if isinstance(snippets, list): - for snippet in snippets: - if isinstance(snippet, dict): - if self.parse_snippet_id(snippet.get('id')): - self.parse_snippet_name(snippet.get('name')) - self.parse_snippet_comment(snippet.get('comment')) - self.parse_snippet_copyright(snippet.get('copyrightText')) - self.parse_snippet_license_comment(snippet.get('licenseComments')) - self.parse_snippet_file_spdxid(snippet.get('fileId')) - self.parse_snippet_concluded_license(snippet.get('licenseConcluded')) - self.parse_snippet_license_info_from_snippet(snippet.get('licenseInfoFromSnippet')) - else: - self.value_error('SNIPPET', snippet) - - def parse_snippet_id(self, snippet_id): - """ - Parse Snippet id - - snippet_id: Python str/unicode - """ - if isinstance(snippet_id, six.string_types): - try: - return self.builder.create_snippet(self.document, snippet_id) - except SPDXValueError: - self.value_error('SNIPPET_SPDX_ID_VALUE', snippet_id) - else: - self.value_error('SNIPPET_SPDX_ID_VALUE', snippet_id) - - def parse_snippet_name(self, snippet_name): - """ - Parse Snippet name - - snippet_name: Python str/unicode - """ - if isinstance(snippet_name, six.string_types): - try: - return self.builder.set_snippet_name(self.document, snippet_name) - except CardinalityError: - self.more_than_one_error('SNIPPET_NAME') - elif snippet_name is not None: - self.value_error('SNIPPET_NAME', snippet_name) - - def parse_snippet_comment(self, snippet_comment): - """ - Parse Snippet comment - - snippet_comment: Python str/unicode - """ - if isinstance(snippet_comment, six.string_types): - try: - return self.builder.set_snippet_comment(self.document, snippet_comment) - except CardinalityError: - self.more_than_one_error('SNIPPET_COMMENT') - elif snippet_comment is not None: - self.value_error('SNIPPET_COMMENT', snippet_comment) - - def parse_snippet_copyright(self, copyright_text): - """ - Parse Snippet copyright text - - copyright_text: Python str/unicode - """ - if isinstance(copyright_text, six.string_types): - try: - return self.builder.set_snippet_copyright(self.document, copyright_text) - except CardinalityError: - self.more_than_one_error('SNIPPET_COPYRIGHT') - else: - self.value_error('SNIPPET_COPYRIGHT', copyright_text) - - def parse_snippet_license_comment(self, license_comment): - """ - Parse Snippet license comment - - license_comment: Python str/unicode - """ - if isinstance(license_comment, six.string_types): - try: - return self.builder.set_snippet_lic_comment(self.document, license_comment) - except CardinalityError: - self.more_than_one_error('SNIPPET_LIC_COMMENTS') - elif license_comment is not None: - self.value_error('SNIPPET_LIC_COMMENTS', license_comment) - - def parse_snippet_file_spdxid(self, file_spdxid): - """ - Parse Snippet file id - - file_spdxid: Python str/unicode - """ - if isinstance(file_spdxid, six.string_types): - try: - return self.builder.set_snip_from_file_spdxid(self.document, file_spdxid) - except SPDXValueError: - self.value_error('SNIPPET_FILE_ID', file_spdxid) - except CardinalityError: - self.more_than_one_error('SNIPPET_FILE_ID') - else: - self.value_error('SNIPPET_FILE_ID', file_spdxid) - - def parse_snippet_concluded_license(self, concluded_license): - """ - Parse Snippet concluded license - - concluded_license: Python str/unicode - """ - if isinstance(concluded_license, six.string_types): - lic_parser = utils.LicenseListParser() - lic_parser.build(write_tables=0, debug=0) - license_object = self.replace_license(lic_parser.parse(concluded_license)) - try: - return self.builder.set_snip_concluded_license(self.document, license_object) - except SPDXValueError: - self.value_error('SNIPPET_SINGLE_LICS', concluded_license) - except CardinalityError: - self.more_than_one_error('SNIPPET_SINGLE_LICS') - else: - self.value_error('SNIPPET_SINGLE_LICS', concluded_license) - - def parse_snippet_license_info_from_snippet(self, license_info_from_snippet): - """ - Parse Snippet license information from snippet - - license_info_from_snippet: Python list of licenses information from snippet (str/unicode) - """ - if isinstance(license_info_from_snippet, list): - for lic_in_snippet in license_info_from_snippet: - if isinstance(lic_in_snippet, six.string_types): - lic_parser = utils.LicenseListParser() - lic_parser.build(write_tables=0, debug=0) - license_object = self.replace_license(lic_parser.parse(lic_in_snippet)) - try: - return self.builder.set_snippet_lics_info(self.document, license_object) - except SPDXValueError: - self.value_error('SNIPPET_LIC_INFO', lic_in_snippet) - else: - self.value_error('SNIPPET_LIC_INFO', lic_in_snippet) - else: - self.value_error('SNIPPET_LIC_INFO_FIELD', license_info_from_snippet) - -class ReviewParser(BaseParser): - def __init__(self, builder, logger): - super(ReviewParser, self).__init__(builder, logger) - - def parse_reviews(self, reviews): - """ - Parse Review Information fields - - reviews: Python list with Review Information dicts in it - """ - if isinstance(reviews, list): - for review in reviews: - if isinstance(review, dict): - if self.parse_review_reviewer(review.get('reviewer')): - self.parse_review_date(review.get('reviewDate')) - self.parse_review_comment(review.get('comment')) - else: - self.value_error('REVIEW', review) - - def parse_review_reviewer(self, reviewer): - """ - Parse Review reviewer - - reviewer: Python str/unicode - """ - if isinstance(reviewer, six.string_types): - entity = self.builder.create_entity(self.document, reviewer) - try: - return self.builder.add_reviewer(self.document, entity) - except SPDXValueError: - self.value_error('REVIEWER_VALUE', reviewer) - else: - self.value_error('REVIEWER_VALUE', reviewer) - - def parse_review_date(self, review_date): - """ - Parse Review date - - review_date: Python str/unicode (ISO-8601 representation of datetime) - """ - if isinstance(review_date, six.string_types): - try: - return self.builder.add_review_date(self.document, review_date) - except SPDXValueError: - self.value_error('REVIEW_DATE', review_date) - except CardinalityError: - self.more_than_one_error('REVIEW_DATE') - except OrderError: - self.order_error('REVIEW_DATE', 'REVIEWER_VALUE') - else: - self.value_error('REVIEW_DATE', review_date) - - def parse_review_comment(self, review_comment): - """ - Parse Review comment - - review_comment: Python str/unicode - """ - if isinstance(review_comment, six.string_types): - try: - return self.builder.add_review_comment(self.document, review_comment) - except CardinalityError: - self.more_than_one_error('REVIEW_COMMENT') - except OrderError: - self.order_error('REVIEW_COMMENT', 'REVIEWER_VALUE') - elif review_comment is not None: - self.value_error('REVIEW_COMMENT', review_comment) - -class FileParser(BaseParser): - def __init__(self, builder, logger): - super(FileParser, self).__init__(builder, logger) - - def parse_file(self, file): - """ - Parse File Information fields - - file: Python dict with File Information fields in it - """ - if isinstance(file, dict): - self.parse_file_name(file.get('name')) - self.parse_file_id(file.get('id')) - self.parse_file_types(file.get('fileTypes')) - self.parse_file_concluded_license(file.get('licenseConcluded')) - self.parse_file_license_info_from_files(file.get('licenseInfoFromFiles')) - self.parse_file_license_comments(file.get('licenseComments')) - self.parse_file_copyright_text(file.get('copyrightText')) - self.parse_file_artifacts(file.get('artifactOf')) - self.parse_file_comment(file.get('comment')) - self.parse_file_notice_text(file.get('noticeText')) - self.parse_file_contributors(file.get('fileContributors')) - self.parse_file_dependencies(file.get('fileDependencies')) - self.parse_annotations(file.get('annotations')) - self.parse_file_chksum(file.get('sha1')) - else: - self.value_error('FILE', file) - - def parse_file_name(self, file_name): - """ - Parse File name - - file_name: Python str/unicode - """ - if isinstance(file_name, six.string_types): - return self.builder.set_file_name(self.document, file_name) - self.value_error('FILE_NAME', file_name) - return self.builder.set_file_name(self.document, 'dummy_file') - # file_name is set even if it is None or not string. If weren't, the other attributes - # would be added to the file previously added. - # Another approach is to skip the whole file itself - - def parse_file_id(self, file_id): - """ - Parse File id - - file_id: Python str/unicode - """ - if isinstance(file_id, six.string_types): - try: - return self.builder.set_file_spdx_id(self.document, file_id) - except SPDXValueError: - self.value_error('FILE_ID', file_id) - except CardinalityError: - self.more_than_one_error('FILE_ID') - except OrderError: - self.order_error('FILE_ID', 'FILE_NAME') - else: - self.value_error('FILE_ID', file_id) - - def parse_file_types(self, file_types): - """ - Parse File types - - file_types: Python list of file types (str/unicode: fileType_archive, fileType_binary, fileType_source or fileType_other) - """ - if isinstance(file_types, list): # file_types is an array in JSON examples... - for file_type in file_types: - self.parse_file_type(file_type) - # ...but file.File allows only one type at the moment. - elif isinstance(file_types, six.string_types): - return self.parse_file_type(file_types) - elif file_types is not None: - self.value_error('FILE_TYPES', file_types) - - def parse_file_type(self, file_type): - """ - Parse File type - - file_type: Python str/unicode (fileType_archive, fileType_binary, fileType_source or fileType_other) - """ - if isinstance(file_type, six.string_types): - try: - return self.builder.set_file_type(self.document, file_type) - except SPDXValueError: - self.value_error('FILE_TYPE', file_type) - except CardinalityError: - self.more_than_one_error('FILE_TYPE') - except OrderError: - self.order_error('FILE_TYPE', 'FILE_NAME') - else: - self.value_error('FILE_TYPE', file_type) - - def parse_file_concluded_license(self, concluded_license): - """ - Parse File concluded license - - concluded_license: Python str/unicode - """ - if isinstance(concluded_license, six.string_types): - lic_parser = utils.LicenseListParser() - lic_parser.build(write_tables=0, debug=0) - license_object = self.replace_license(lic_parser.parse(concluded_license)) - try: - return self.builder.set_concluded_license(self.document, license_object) - except SPDXValueError: - self.value_error('FILE_SINGLE_LICS', concluded_license) - except CardinalityError: - self.more_than_one_error('FILE_SINGLE_LICS') - except OrderError: - self.order_error('FILE_SINGLE_LICS', 'FILE_NAME') - else: - self.value_error('FILE_SINGLE_LICS', concluded_license) - - def parse_file_license_info_from_files(self, license_info_from_files): - """ - Parse File license information from files - - license_info_from_files: Python list of licenses information from files (str/unicode) - """ - if isinstance(license_info_from_files, list): - for license_info_from_file in license_info_from_files: - if isinstance(license_info_from_file, six.string_types): - lic_parser = utils.LicenseListParser() - lic_parser.build(write_tables=0, debug=0) - license_object = self.replace_license(lic_parser.parse(license_info_from_file)) - try: - self.builder.set_file_license_in_file(self.document, license_object) - except SPDXValueError: - self.value_error('FILE_LIC_FRM_FILES', license_info_from_file) - except OrderError: - self.order_error('FILE_LIC_FRM_FILES', 'FILE_NAME') - else: - self.value_error('FILE_LIC_FRM_FILES', license_info_from_file) - else: - self.value_error('FILE_LIC_FRM_FILES_FIELD', license_info_from_files) - - def parse_file_license_comments(self, license_comments): - """ - Parse File license comments - - license_comments: Python str/unicode - """ - if isinstance(license_comments, six.string_types): - try: - return self.builder.set_file_license_comment(self.document, license_comments) - except CardinalityError: - self.more_than_one_error('FILE_LIC_COMMENTS') - except OrderError: - self.order_error('FILE_LIC_COMMENTS', 'FILE_NAME') - elif license_comments is not None: - self.value_error('FILE_LIC_COMMENTS', license_comments) - - def parse_file_copyright_text(self, copyright_text): - """ - Parse File copyright text - - copyright_text: Python str/unicode - """ - if isinstance(copyright_text, six.string_types): - try: - return self.builder.set_file_copyright(self.document, copyright_text) - except CardinalityError: - self.more_than_one_error('FILE_COPYRIGHT_TEXT') - except OrderError: - self.order_error('FILE_COPYRIGHT_TEXT', 'FILE_NAME') - else: - self.value_error('FILE_COPYRIGHT_TEXT', copyright_text) - - def parse_file_artifacts(self, file_artifacts): - """ - Parse File artifacts - - file_artifacts: Python list of dict('name':str/unicode, 'homePage':str/unicode, 'projectUri':str/unicode) - """ - if isinstance(file_artifacts, list): - for artifact in file_artifacts: - if isinstance(artifact, dict): - self.builder.set_file_atrificat_of_project(self.document, 'name', artifact.get('name', UnKnown())) - self.builder.set_file_atrificat_of_project(self.document, 'home', artifact.get('homePage', UnKnown())) - self.builder.set_file_atrificat_of_project(self.document, 'uri', artifact.get('projectUri', UnKnown())) - return True - else: - self.value_error('ARTIFACT_OF_VALUE', artifact) - elif file_artifacts is not None: - self.value_error('ARTIFACT_OF_FIELD', file_artifacts) - - def parse_file_comment(self, file_comment): - """ - Parse File comment - - file_comment: Python str/unicode - """ - if isinstance(file_comment, six.string_types): - try: - return self.builder.set_file_comment(self.document, file_comment) - except CardinalityError: - self.more_than_one_error('FILE_COMMENT') - except OrderError: - self.order_error('FILE_COMMENT', 'FILE_NAME') - elif file_comment is not None: - self.value_error('FILE_COMMENT', file_comment) - - def parse_file_notice_text(self, notice_text): - """ - Parse File notice text - - notice_text: Python str/unicode - """ - if isinstance(notice_text, six.string_types): - try: - return self.builder.set_file_notice(self.document, notice_text) - except CardinalityError: - self.more_than_one_error('FILE_NOTICE_TEXT') - except OrderError: - self.order_error('FILE_NOTICE_TEXT', 'FILE_NAME') - elif notice_text is not None: - self.value_error('FILE_NOTICE_TEXT', notice_text) - - def parse_file_contributors(self, file_contributors): - """ - Parse File contributors - - file_contributors: Python list of contributors (str/unicode) - """ - if isinstance(file_contributors, list): - for contributor in file_contributors: - if isinstance(contributor, six.string_types): - try: - self.builder.add_file_contribution(self.document, contributor) - except OrderError: - self.order_error('FILE_CONTRIBUTOR', 'FILE_NAME') - else: - self.value_error('FILE_CONTRIBUTOR', contributor) - elif file_contributors is not None: - self.value_error('FILE_CONTRIBUTORS', file_contributors) - - def parse_file_dependencies(self, file_dependencies): - """ - Parse File dependencies - - file_dependencies: Python list of dependencies (str/unicode or file dict as in FileParser.parse_file) - """ - if isinstance(file_dependencies, list): - for dependency in file_dependencies: - dependency = self._handle_file_dependency(dependency) - if isinstance(dependency, six.string_types): - try: - self.builder.add_file_dep(self.document, dependency) - except OrderError: - self.order_error('FILE_DEPENDENCY', 'FILE_NAME') - else: - self.value_error('FILE_DEPENDENCY', dependency) - elif file_dependencies is not None: - self.value_error('FILE_DEPENDENCIES', file_dependencies) - - def _handle_file_dependency(self, file_dependency): - """ - Helper method that handles file-like dependency - - file_dependency: Python dict as in FileParser.parse_file - return: file name (str/unicode) or None - """ - if isinstance(file_dependency, dict): - filelike_dependency = file_dependency.get('File') - if isinstance(filelike_dependency, dict): - return filelike_dependency.get('name') - return None - return None - - def parse_file_chksum(self, file_chksum): - """ - Parse File checksum - - file_chksum: Python str/unicode - """ - if isinstance(file_chksum, six.string_types): - try: - return self.builder.set_file_chksum(self.document, file_chksum) - except CardinalityError: - self.more_than_one_error('FILE_CHECKSUM') - except OrderError: - self.order_error('FILE_CHECKSUM', 'FILE_NAME') - else: - self.value_error('FILE_CHECKSUM', file_chksum) - -class PackageParser(BaseParser): - def __init__(self, builder, logger): - super(PackageParser, self).__init__(builder, logger) - - def parse_package(self, package): - """ - Parse Package Information fields - - package: Python dict with Package Information fields in it - """ - if isinstance(package, dict): - self.parse_pkg_name(package.get('name')) - self.parse_pkg_id(package.get('id')) - self.parse_pkg_version(package.get('versionInfo')) - self.parse_pkg_file_name(package.get('packageFileName')) - self.parse_pkg_supplier(package.get('supplier')) - self.parse_pkg_originator(package.get('originator')) - self.parse_pkg_down_location(package.get('downloadLocation')) - self.parse_pkg_verif_code_field(package.get('packageVerificationCode')) - self.parse_pkg_homepage(package.get('homepage')) - self.parse_pkg_source_info(package.get('sourceInfo')) - self.parse_pkg_concluded_license(package.get('licenseConcluded')) - self.parse_pkg_license_info_from_files(package.get('licenseInfoFromFiles')) - self.parse_pkg_declared_license(package.get('licenseDeclared')) - self.parse_pkg_license_comment(package.get('licenseComments')) - self.parse_pkg_copyright_text(package.get('copyrightText')) - self.parse_pkg_summary(package.get('summary')) - self.parse_pkg_description(package.get('description')) - self.parse_annotations(package.get('annotations')) - self.parse_pkg_files(package.get('files')) - self.parse_pkg_chksum(package.get('sha1')) - else: - self.value_error('PACKAGE', package) - - def parse_pkg_name(self, pkg_name): - """ - Parse Package name - - pkg_name: Python str/unicode - """ - if isinstance(pkg_name, six.string_types): - return self.builder.create_package(self.document, pkg_name) - self.value_error('PKG_NAME', pkg_name) - return self.builder.create_package(self.document, 'dummy_package') - # pkg_name is set even if it is None or not string. If weren't, the other attributes - # would be added to the package previously added. - # Another approach is to skip the whole package itself - - def parse_pkg_id(self, pkg_id): - """ - Parse Package id - - pkg_id: Python str/unicode - """ - if isinstance(pkg_id, six.string_types): - try: - return self.builder.set_pkg_spdx_id(self.document, pkg_id) - except SPDXValueError: - self.value_error('PKG_ID', pkg_id) - except CardinalityError: - self.more_than_one_error('PKG_ID') - else: - self.value_error('PKG_ID', pkg_id) - - def parse_pkg_version(self, pkg_version): - """ - Parse Package version - - pkg_name: Python str/unicode - """ - if isinstance(pkg_version, six.string_types): - try: - return self.builder.set_pkg_vers(self.document, pkg_version) - except CardinalityError: - self.more_than_one_error('PKG_VERSION') - except OrderError: - self.order_error('PKG_VERSION', 'PKG_NAME') - elif pkg_version is not None: - self.value_error('PKG_VERSION', pkg_version) - - def parse_pkg_file_name(self, pkg_file_name): - """ - Parse Package file name - - pkg_file_name: Python str/unicode - """ - if isinstance(pkg_file_name, six.string_types): - try: - return self.builder.set_pkg_file_name(self.document, pkg_file_name) - except CardinalityError: - self.more_than_one_error('PKG_FILE_NAME') - except OrderError: - self.order_error('PKG_FILE_NAME', 'PKG_NAME') - elif pkg_file_name is not None: - self.value_error('PKG_FILE_NAME', pkg_file_name) - - def parse_pkg_supplier(self, pkg_supplier): - """ - Parse Package supplier - - pkg_supplier: Python str/unicode - """ - if isinstance(pkg_supplier, six.string_types): - entity = self.builder.create_entity(self.document, pkg_supplier) - try: - return self.builder.set_pkg_supplier(self.document, entity) - except SPDXValueError: - self.value_error('PKG_SUPPL_VALUE', pkg_supplier) - except CardinalityError: - self.more_than_one_error('PKG_SUPPL_VALUE') - except OrderError: - self.order_error('PKG_SUPPL_VALUE', 'PKG_NAME') - elif pkg_supplier is not None: - self.value_error('PKG_SUPPL_VALUE', pkg_supplier) - - def parse_pkg_originator(self, pkg_originator): - """ - Parse Package originator - - pkg_originator: Python str/unicode - """ - if isinstance(pkg_originator, six.string_types): - entity = self.builder.create_entity(self.document, pkg_originator) - try: - return self.builder.set_pkg_originator(self.document, entity) - except SPDXValueError: - self.value_error('PKG_ORIGINATOR_VALUE', pkg_originator) - except CardinalityError: - self.more_than_one_error('PKG_ORIGINATOR_VALUE') - except OrderError: - self.order_error('PKG_ORIGINATOR_VALUE', 'PKG_NAME') - elif pkg_originator is not None: - self.value_error('PKG_ORIGINATOR_VALUE', pkg_originator) - - def parse_pkg_down_location(self, pkg_down_location): - """ - Parse Package download location - - pkg_down_location: Python str/unicode - """ - if isinstance(pkg_down_location, six.string_types): - try: - return self.builder.set_pkg_down_location(self.document, pkg_down_location) - except CardinalityError: - self.more_than_one_error('PKG_DOWN_LOC') - except OrderError: - self.order_error('PKG_DOWN_LOC', 'PKG_NAME') - else: - self.value_error('PKG_DOWN_LOC', pkg_down_location) - - def parse_pkg_verif_code_field(self, pkg_verif_code_field): - """ - Parse Package verification code dict - - pkg_verif_code_field: Python dict('value':str/unicode, 'excludedFilesNames':list) - """ - if isinstance(pkg_verif_code_field, dict): - self.parse_pkg_verif_exc_files(pkg_verif_code_field.get('excludedFilesNames')) - return self.parse_pkg_verif_code(pkg_verif_code_field.get('value')) - else: - self.value_error('PKG_VERIF_CODE_FIELD', pkg_verif_code_field) - - def parse_pkg_verif_code(self, pkg_verif_code): - """ - Parse Package verification code value - - pkg_verif_code: Python str/unicode - """ - if isinstance(pkg_verif_code, six.string_types): - try: - return self.builder.set_pkg_verif_code(self.document, pkg_verif_code) - except CardinalityError: - self.more_than_one_error('PKG_VERIF_CODE') - except OrderError: - self.order_error('PKG_VERIF_CODE', 'PKG_NAME') - else: - self.value_error('PKG_VERIF_CODE', pkg_verif_code) - - def parse_pkg_verif_exc_files(self, pkg_verif_exc_files): - """ - Parse Package files excluded from verification code - - pkg_verif_exc_files: Python list of files excluded (str/unicode) - """ - if isinstance(pkg_verif_exc_files, list): - for pkg_verif_exc_file in pkg_verif_exc_files: - if isinstance(pkg_verif_exc_file, six.string_types): - try: - self.builder.set_pkg_excl_file(self.document, pkg_verif_exc_file) - except OrderError: - self.order_error('PKG_VERIF_EXC_FILE', 'PKG_NAME') - else: - self.value_error('PKG_VERIF_EXC_FILE', pkg_verif_exc_file) - elif pkg_verif_exc_files is not None: - self.value_error('PKG_VERIF_EXC_FILE_FIELD', pkg_verif_exc_files) - - def parse_pkg_homepage(self, pkg_homepage): - """ - Parse Package homepage - - pkg_homepage: Python str/unicode - """ - if isinstance(pkg_homepage, six.string_types): - try: - return self.builder.set_pkg_home(self.document, pkg_homepage) - except SPDXValueError: - self.value_error('PKG_HOMEPAGE', pkg_homepage) - except CardinalityError: - self.more_than_one_error('PKG_HOMEPAGE') - except OrderError: - self.order_error('PKG_HOMEPAGE', 'PKG_NAME') - elif pkg_homepage is not None: - self.value_error('PKG_HOMEPAGE', pkg_homepage) - - def parse_pkg_source_info(self, pkg_source_info): - """ - Parse Package source information - - pkg_source_info: Python str/unicode - """ - if isinstance(pkg_source_info, six.string_types): - try: - return self.builder.set_pkg_source_info(self.document, pkg_source_info) - except CardinalityError: - self.more_than_one_error('PKG_SRC_INFO') - except OrderError: - self.order_error('PKG_SRC_INFO', 'PKG_NAME') - elif pkg_source_info is not None: - self.value_error('PKG_SRC_INFO', pkg_source_info) - - def parse_pkg_concluded_license(self, pkg_concluded_license): - """ - Parse Package concluded license - - pkg_concluded_license: Python str/unicode - """ - if isinstance(pkg_concluded_license, six.string_types): - lic_parser = utils.LicenseListParser() - lic_parser.build(write_tables=0, debug=0) - license_object = self.replace_license(lic_parser.parse(pkg_concluded_license)) - try: - return self.builder.set_pkg_licenses_concluded(self.document, license_object) - except SPDXValueError: - self.value_error('PKG_SINGLE_LICS', pkg_concluded_license) - except CardinalityError: - self.more_than_one_error('PKG_SINGLE_LICS') - except OrderError: - self.order_error('PKG_SINGLE_LICS', 'PKG_NAME') - else: - self.value_error('PKG_SINGLE_LICS', pkg_concluded_license) - - def parse_pkg_license_info_from_files(self, license_info_from_files): - """ - Parse Package license information from files - - license_info_from_files: Python list of licenses information from files (str/unicode) - """ - if isinstance(license_info_from_files, list): - for license_info_from_file in license_info_from_files: - if isinstance(license_info_from_file, six.string_types): - lic_parser = utils.LicenseListParser() - lic_parser.build(write_tables=0, debug=0) - license_object = self.replace_license(lic_parser.parse(license_info_from_file)) - try: - self.builder.set_pkg_license_from_file(self.document, license_object) - except SPDXValueError: - self.value_error('PKG_LIC_FRM_FILES', license_info_from_file) - except OrderError: - self.order_error('PKG_LIC_FRM_FILES', 'PKG_NAME') - else: - self.value_error('PKG_LIC_FRM_FILES', license_info_from_file) - else: - self.value_error('PKG_LIC_FRM_FILES_FIELD', license_info_from_files) - - def parse_pkg_declared_license(self, pkg_declared_license): - """ - Parse Package license declared - - pkg_declared_license: Python str/unicode - """ - if isinstance(pkg_declared_license, six.string_types): - lic_parser = utils.LicenseListParser() - lic_parser.build(write_tables=0, debug=0) - license_object = self.replace_license(lic_parser.parse(pkg_declared_license)) - try: - return self.builder.set_pkg_license_declared(self.document, license_object) - except SPDXValueError: - self.value_error('PKG_DECL_LIC', pkg_declared_license) - except CardinalityError: - self.more_than_one_error('PKG_DECL_LIC') - except OrderError: - self.order_error('PKG_DECL_LIC', 'PKG_NAME') - else: - self.value_error('PKG_DECL_LIC', pkg_declared_license) - - def parse_pkg_license_comment(self, pkg_license_comment): - """ - Parse Package license comment - - pkg_license_comment: Python str/unicode - """ - if isinstance(pkg_license_comment, six.string_types): - try: - return self.builder.set_pkg_license_comment(self.document, pkg_license_comment) - except CardinalityError: - self.more_than_one_error('PKG_LIC_COMMENT') - except OrderError: - self.order_error('PKG_LIC_COMMENT', 'PKG_NAME') - elif pkg_license_comment is not None: - self.value_error('PKG_LIC_COMMENT', pkg_license_comment) - - def parse_pkg_copyright_text(self, pkg_copyright_text): - """ - Parse Package copyright text - - pkg_copyright_text: Python str/unicode - """ - if isinstance(pkg_copyright_text, six.string_types): - try: - return self.builder.set_pkg_cr_text(self.document, pkg_copyright_text) - except CardinalityError: - self.more_than_one_error('PKG_COPYRIGHT_TEXT') - except OrderError: - self.order_error('PKG_COPYRIGHT_TEXT', 'PKG_NAME') - else: - self.value_error('PKG_COPYRIGHT_TEXT', pkg_copyright_text) - - def parse_pkg_summary(self, pkg_summary): - """ - Parse Package summary - - pkg_summary: Python str/unicode - """ - if isinstance(pkg_summary, six.string_types): - try: - return self.builder.set_pkg_summary(self.document, pkg_summary) - except CardinalityError: - self.more_than_one_error('PKG_SUMMARY') - except OrderError: - self.order_error('PKG_SUMMARY', 'PKG_NAME') - elif pkg_summary is not None: - self.value_error('PKG_SUMMARY', pkg_summary) - - def parse_pkg_description(self, pkg_description): - """ - Parse Package description - - pkg_description: Python str/unicode - """ - if isinstance(pkg_description, six.string_types): - try: - return self.builder.set_pkg_desc(self.document, pkg_description) - except CardinalityError: - self.more_than_one_error('PKG_DESCRIPTION') - except OrderError: - self.order_error('PKG_DESCRIPTION', 'PKG_NAME') - elif pkg_description is not None: - self.value_error('PKG_DESCRIPTION', pkg_description) - - def parse_pkg_files(self, pkg_files): - """ - Parse Package files - - pkg_files: Python list of dicts as in FileParser.parse_file - """ - if isinstance(pkg_files, list): - for pkg_file in pkg_files: - if isinstance(pkg_file, dict): - self.parse_file(pkg_file.get('File')) - else: - self.value_error('PKG_FILE', pkg_file) - else: - self.value_error('PKG_FILES', pkg_files) - - def parse_pkg_chksum(self, pkg_chksum): - """ - Parse Package checksum - - pkg_chksum: Python str/unicode - """ - if isinstance(pkg_chksum, six.string_types): - try: - return self.builder.set_pkg_chk_sum(self.document, pkg_chksum) - except CardinalityError: - self.more_than_one_error('PKG_CHECKSUM') - except OrderError: - self.order_error('PKG_CHECKSUM', 'PKG_NAME') - elif pkg_chksum is not None: - self.value_error('PKG_CHECKSUM', pkg_chksum) - - -class Parser(CreationInfoParser, ExternalDocumentRefsParser, LicenseParser, - AnnotationParser, SnippetParser, ReviewParser, FileParser, PackageParser): - - def __init__(self, builder, logger): - super(Parser, self).__init__(builder, logger) - - def parse(self): - """ - Parse Document Information fields - """ - self.error = False - self.document = document.Document() - if not isinstance(self.document_object, dict): - self.logger.log('Empty or not valid SPDX Document') - self.error = True - return self.document, self.error - - self.parse_doc_version(self.document_object.get('specVersion')) - self.parse_doc_data_license(self.document_object.get('dataLicense')) - self.parse_doc_id(self.document_object.get('id')) - self.parse_doc_name(self.document_object.get('name')) - self.parse_doc_namespace(self.document_object.get('namespace')) - self.parse_doc_comment(self.document_object.get('comment')) - self.parse_creation_info(self.document_object.get('creationInfo')) - self.parse_external_document_refs(self.document_object.get('externalDocumentRefs')) - self.parse_extracted_license_info(self.document_object.get('extractedLicenseInfos')) - self.parse_annotations(self.document_object.get('annotations')) - self.parse_reviews(self.document_object.get('reviewers')) - self.parse_snippets(self.document_object.get('snippets')) - - self.parse_doc_described_objects(self.document_object.get('documentDescribes')) - - validation_messages = [] - # Report extra errors if self.error is False otherwise there will be - # redundent messages - validation_messages = self.document.validate(validation_messages) - if not self.error: - if validation_messages: - for msg in validation_messages: - self.logger.log(msg) - self.error = True - - return self.document, self.error - - def parse_doc_version(self, doc_version): - """ - Parse Document version - - doc_version: Python str/unicode - """ - if isinstance(doc_version, six.string_types): - try: - return self.builder.set_doc_version(self.document, doc_version) - except SPDXValueError: - self.value_error('DOC_VERS_VALUE', doc_version) - except CardinalityError: - self.more_than_one_error('DOC_VERS_VALUE') - else: - self.value_error('DOC_VERS_VALUE', doc_version) - - def parse_doc_data_license(self, doc_data_license): - """ - Parse Document data license - - doc_data_license: Python str/unicode - """ - try: - return self.builder.set_doc_data_lics(self.document, doc_data_license) - except SPDXValueError: - self.value_error('DOC_D_LICS', doc_data_license) - except CardinalityError: - self.more_than_one_error('DOC_D_LICS') - - def parse_doc_id(self, doc_id): - """ - Parse Document SPDX id - - doc_id: Python str/unicode - """ - if isinstance(doc_id, six.string_types): - try: - return self.builder.set_doc_spdx_id(self.document, doc_id) - except SPDXValueError: - self.value_error('DOC_SPDX_ID_VALUE', doc_id) - except CardinalityError: - self.more_than_one_error('DOC_SPDX_ID_VALUE') - else: - self.value_error('DOC_SPDX_ID_VALUE', doc_id) - - def parse_doc_name(self, doc_name): - """ - Parse Document name - - doc_name: Python str/unicode - """ - if isinstance(doc_name, six.string_types): - try: - return self.builder.set_doc_name(self.document, doc_name) - except CardinalityError: - self.more_than_one_error('DOC_NAME_VALUE') - else: - self.value_error('DOC_NAME_VALUE', doc_name) - - def parse_doc_namespace(self, doc_namespace): - """ - Parse Document namespace - - doc_namespace: Python str/unicode - """ - if isinstance(doc_namespace, six.string_types): - try: - return self.builder.set_doc_namespace(self.document, doc_namespace) - except SPDXValueError: - self.value_error('DOC_NAMESPACE_VALUE', doc_namespace) - except CardinalityError: - self.more_than_one_error('DOC_NAMESPACE_VALUE') - else: - self.value_error('DOC_NAMESPACE_VALUE', doc_namespace) - - def parse_doc_comment(self, doc_comment): - """ - Parse Document comment - - doc_comment: Python str/unicode - """ - if isinstance(doc_comment, six.string_types): - try: - return self.builder.set_doc_comment(self.document, doc_comment) - except CardinalityError: - self.more_than_one_error('DOC_COMMENT_VALUE') - elif doc_comment is not None: - self.value_error('DOC_COMMENT_VALUE', doc_comment) - - def parse_doc_described_objects(self, doc_described_objects): - """ - Parse Document documentDescribes (Files and Packages dicts) - - doc_described_objects: Python list of dicts as in FileParser.parse_file or PackageParser.parse_package - """ - if isinstance(doc_described_objects, list): - packages = filter(lambda described: isinstance(described, dict) and described.get('Package') is not None, doc_described_objects) - files = filter(lambda described: isinstance(described, dict) and described.get('File') is not None, doc_described_objects) - # At the moment, only single-package documents are supported, so just the last package will be stored. - for package in packages: - self.parse_package(package.get('Package')) - for file in files: - self.parse_file(file.get('File')) - return True - else: - self.value_error('DOC_DESCRIBES', doc_described_objects) diff --git a/spdx/parsers/jsonyamlxmlbuilders.py b/spdx/parsers/jsonyamlxmlbuilders.py deleted file mode 100644 index a56c1415b..000000000 --- a/spdx/parsers/jsonyamlxmlbuilders.py +++ /dev/null @@ -1,224 +0,0 @@ - -# Copyright (c) Xavier Figueroa -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from spdx.parsers import rdfbuilders -from spdx.parsers import tagvaluebuilders -from spdx.parsers import validations -from spdx.parsers.builderexceptions import SPDXValueError -from spdx.parsers.builderexceptions import CardinalityError -from spdx.parsers.builderexceptions import OrderError - - -class CreationInfoBuilder(rdfbuilders.CreationInfoBuilder): - def __init__(self): - super(CreationInfoBuilder, self).__init__() - - -class ExternalDocumentRefsBuilder(rdfbuilders.ExternalDocumentRefBuilder): - def __init__(self): - super(ExternalDocumentRefsBuilder, self).__init__() - - -class EntityBuilder(rdfbuilders.EntityBuilder): - def __init__(self): - super(EntityBuilder, self).__init__() - - -class SnippetBuilder(rdfbuilders.SnippetBuilder): - def __init__(self): - super(SnippetBuilder, self).__init__() - - -class ReviewBuilder(rdfbuilders.ReviewBuilder): - def __init__(self): - super(ReviewBuilder, self).__init__() - - -class PackageBuilder(rdfbuilders.PackageBuilder): - def __init__(self): - super(PackageBuilder, self).__init__() - - -class DocBuilder(tagvaluebuilders.DocBuilder): - def __init__(self): - super(DocBuilder, self).__init__() - - def set_doc_spdx_id(self, doc, doc_spdx_id_line): - """ - Set the document SPDX Identifier. - Raise SPDXValueError if malformed value, CardinalityError - if already defined. - """ - if not self.doc_spdx_id_set: - if doc_spdx_id_line == 'SPDXRef-DOCUMENT' or validations.validate_doc_spdx_id(doc_spdx_id_line): - doc.spdx_id = doc_spdx_id_line - self.doc_spdx_id_set = True - return True - else: - raise SPDXValueError('Document::SPDXID') - else: - raise CardinalityError('Document::SPDXID') - - def set_doc_comment(self, doc, comment): - """ - Set document comment. - Raise CardinalityError if comment already set. - """ - if not self.doc_comment_set: - self.doc_comment_set = True - doc.comment = comment - else: - raise CardinalityError('Document::Comment') - - -class LicenseBuilder(tagvaluebuilders.LicenseBuilder): - def __init__(self): - super(LicenseBuilder, self).__init__() - - def set_lic_name(self, doc, name): - """ - Set license name. - Raise SPDXValueError if name is not str or utils.NoAssert - Raise CardinalityError if it is already set - Raise OrderError if no license id defined. - """ - if self.has_extr_lic(doc): - if not self.extr_lic_name_set: - self.extr_lic_name_set = True - if validations.validate_extr_lic_name(name, True): - self.extr_lic(doc).full_name = name - return True - else: - raise SPDXValueError('ExtractedLicense::Name') - else: - raise CardinalityError('ExtractedLicense::Name') - else: - raise OrderError('ExtractedLicense::Name') - - def set_lic_text(self, doc, text): - """ - Set license name. - Raise CardinalityError if it is already set. - Raise OrderError if no license id defined. - """ - if self.has_extr_lic(doc): - if not self.extr_text_set: - self.extr_text_set = True - self.extr_lic(doc).text = text - return True - else: - raise CardinalityError('ExtractedLicense::text') - else: - raise OrderError('ExtractedLicense::text') - - def set_lic_comment(self, doc, comment): - """ - Set license comment. - Raise CardinalityError if it is already set. - Raise OrderError if no license ID defined. - """ - if self.has_extr_lic(doc): - if not self.extr_lic_comment_set: - self.extr_lic_comment_set = True - self.extr_lic(doc).comment = comment - return True - else: - raise CardinalityError('ExtractedLicense::comment') - else: - raise OrderError('ExtractedLicense::comment') - -class FileBuilder(rdfbuilders.FileBuilder): - def __init__(self): - super(FileBuilder, self).__init__() - - def set_file_notice(self, doc, text): - """ - Set file notice - Raise OrderError if no package or file defined. - Raise CardinalityError if more than one. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_notice_set: - self.file_notice_set = True - self.file(doc).notice = text - return True - else: - raise CardinalityError('File::Notice') - else: - raise OrderError('File::Notice') - - def set_file_type(self, doc, type_value): - """ - Wrap rdfbuilders.FileBuilder.set_file_type to match the different - fileType representations. - """ - - type_dict = { - 'fileType_source': 'SOURCE', - 'fileType_binary': 'BINARY', - 'fileType_archive': 'ARCHIVE', - 'fileType_other': 'OTHER' - } - - return super(FileBuilder, self).set_file_type(doc, type_dict.get(type_value)) - - -class AnnotationBuilder(tagvaluebuilders.AnnotationBuilder): - def __init__(self): - super(AnnotationBuilder, self).__init__() - - def add_annotation_comment(self, doc, comment): - """ - Set the annotation comment. - Raise CardinalityError if already set. - Raise OrderError if no annotator defined before. - """ - if len(doc.annotations) != 0: - if not self.annotation_comment_set: - self.annotation_comment_set = True - doc.annotations[-1].comment = comment - return True - else: - raise CardinalityError('AnnotationComment') - else: - raise OrderError('AnnotationComment') - - -class Builder(DocBuilder, CreationInfoBuilder, ExternalDocumentRefsBuilder, EntityBuilder, - SnippetBuilder, ReviewBuilder, LicenseBuilder, FileBuilder, PackageBuilder, - AnnotationBuilder): - """ - SPDX document builder. - """ - - def __init__(self): - super(Builder, self).__init__() - # FIXME: this state does not make sense - self.reset() - - def reset(self): - """ - Reset builder's state for building new documents. - Must be called between usage with different documents. - """ - # FIXME: this state does not make sense - self.reset_creation_info() - self.reset_document() - self.reset_package() - self.reset_file_stat() - self.reset_reviews() - self.reset_annotations() - self.reset_extr_lics() diff --git a/spdx/parsers/lexers/tagvalue.py b/spdx/parsers/lexers/tagvalue.py deleted file mode 100644 index 5a0e7480a..000000000 --- a/spdx/parsers/lexers/tagvalue.py +++ /dev/null @@ -1,213 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function - -from ply import lex - - -class Lexer(object): - reserved = { - # Top level fields - 'SPDXVersion': 'DOC_VERSION', - 'DataLicense': 'DOC_LICENSE', - 'DocumentName': 'DOC_NAME', - 'SPDXID': 'SPDX_ID', - 'DocumentComment': 'DOC_COMMENT', - 'DocumentNamespace': 'DOC_NAMESPACE', - 'ExternalDocumentRef': 'EXT_DOC_REF', - # Creation info - 'Creator': 'CREATOR', - 'Created': 'CREATED', - 'CreatorComment': 'CREATOR_COMMENT', - 'LicenseListVersion': 'LIC_LIST_VER', - # Review info - 'Reviewer': 'REVIEWER', - 'ReviewDate': 'REVIEW_DATE', - 'ReviewComment': 'REVIEW_COMMENT', - # Annotation info - 'Annotator': 'ANNOTATOR', - 'AnnotationDate': 'ANNOTATION_DATE', - 'AnnotationComment': 'ANNOTATION_COMMENT', - 'AnnotationType': 'ANNOTATION_TYPE', - 'SPDXREF': 'ANNOTATION_SPDX_ID', - # Package Fields - 'PackageName': 'PKG_NAME', - 'PackageVersion': 'PKG_VERSION', - 'PackageDownloadLocation': 'PKG_DOWN', - 'FilesAnalyzed': 'PKG_FILES_ANALYZED', - 'PackageSummary': 'PKG_SUM', - 'PackageSourceInfo': 'PKG_SRC_INFO', - 'PackageFileName': 'PKG_FILE_NAME', - 'PackageSupplier': 'PKG_SUPPL', - 'PackageOriginator': 'PKG_ORIG', - 'PackageChecksum': 'PKG_CHKSUM', - 'PackageVerificationCode': 'PKG_VERF_CODE', - 'PackageDescription': 'PKG_DESC', - 'PackageComment': 'PKG_COMMENT', - 'PackageLicenseDeclared': 'PKG_LICS_DECL', - 'PackageLicenseConcluded': 'PKG_LICS_CONC', - 'PackageLicenseInfoFromFiles': 'PKG_LICS_FFILE', - 'PackageLicenseComments': 'PKG_LICS_COMMENT', - 'PackageCopyrightText': 'PKG_CPY_TEXT', - 'PackageHomePage': 'PKG_HOME', - 'ExternalRef': 'PKG_EXT_REF', - 'ExternalRefComment': 'PKG_EXT_REF_COMMENT', - # Files - 'FileName': 'FILE_NAME', - 'FileType': 'FILE_TYPE', - 'FileChecksum': 'FILE_CHKSUM', - 'LicenseConcluded': 'FILE_LICS_CONC', - 'LicenseInfoInFile': 'FILE_LICS_INFO', - 'FileCopyrightText': 'FILE_CR_TEXT', - 'LicenseComments': 'FILE_LICS_COMMENT', - 'FileComment': 'FILE_COMMENT', - 'FileNotice': 'FILE_NOTICE', - 'FileContributor': 'FILE_CONTRIB', - 'FileDependency': 'FILE_DEP', - 'ArtifactOfProjectName': 'ART_PRJ_NAME', - 'ArtifactOfProjectHomePage': 'ART_PRJ_HOME', - 'ArtifactOfProjectURI': 'ART_PRJ_URI', - # License - 'LicenseID': 'LICS_ID', - 'ExtractedText': 'LICS_TEXT', - 'LicenseName': 'LICS_NAME', - 'LicenseCrossReference': 'LICS_CRS_REF', - 'LicenseComment': 'LICS_COMMENT', - # Snippet - 'SnippetSPDXID': 'SNIPPET_SPDX_ID', - 'SnippetName': 'SNIPPET_NAME', - 'SnippetComment': 'SNIPPET_COMMENT', - 'SnippetCopyrightText': 'SNIPPET_CR_TEXT', - 'SnippetLicenseComments': 'SNIPPET_LICS_COMMENT', - 'SnippetFromFileSPDXID': 'SNIPPET_FILE_SPDXID', - 'SnippetLicenseConcluded': 'SNIPPET_LICS_CONC', - 'LicenseInfoInSnippet': 'SNIPPET_LICS_INFO', - # Common - 'NOASSERTION': 'NO_ASSERT', - 'UNKNOWN': 'UN_KNOWN', - 'NONE': 'NONE', - 'SOURCE': 'SOURCE', - 'BINARY': 'BINARY', - 'ARCHIVE': 'ARCHIVE', - 'OTHER': 'OTHER' - } - states = (('text', 'exclusive'),) - - tokens = ['TEXT', 'TOOL_VALUE', 'UNKNOWN_TAG', - 'ORG_VALUE', 'PERSON_VALUE', - 'DATE', 'LINE', 'CHKSUM', 'DOC_REF_ID', - 'DOC_URI', 'EXT_DOC_REF_CHKSUM'] + list(reserved.values()) - - def t_text(self, t): - r':\s*' - t.lexer.text_start = t.lexer.lexpos - len('') - t.lexer.begin('text') - - def t_text_end(self, t): - r'\s*' - t.type = 'TEXT' - t.value = t.lexer.lexdata[ - t.lexer.text_start:t.lexer.lexpos] - t.lexer.lineno += t.value.count('\n') - t.value = t.value.strip() - t.lexer.begin('INITIAL') - return t - - def t_text_any(self, t): - r'.|\n' - pass - - def t_text_error(self, t): - print('Lexer error in text state') - - def t_CHKSUM(self, t): - r':\s*SHA1:\s*[a-f0-9]{40,40}' - t.value = t.value[1:].strip() - return t - - def t_DOC_REF_ID(self, t): - r':\s*DocumentRef-([A-Za-z0-9\+\.\-]+)' - t.value = t.value[1:].strip() - return t - - def t_DOC_URI(self, t): - r'\s*((ht|f)tps?:\/\/\S*)' - t.value = t.value.strip() - return t - - def t_EXT_DOC_REF_CHKSUM(self, t): - r'\s*SHA1:\s*[a-f0-9]{40,40}' - t.value = t.value[1:].strip() - return t - - def t_TOOL_VALUE(self, t): - r':\s*Tool:.+' - t.value = t.value[1:].strip() - return t - - def t_ORG_VALUE(self, t): - r':\s*Organization:.+' - t.value = t.value[1:].strip() - return t - - def t_PERSON_VALUE(self, t): - r':\s*Person:.+' - t.value = t.value[1:].strip() - return t - - def t_DATE(self, t): - r':\s*\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ' - t.value = t.value[1:].strip() - return t - - def t_KEYWORD_AS_TAG(self, t): - r'[a-zA-Z]+' - t.type = self.reserved.get(t.value, 'UNKNOWN_TAG') - t.value = t.value.strip() - return t - - def t_LINE_OR_KEYWORD_VALUE(self, t): - r':.+' - t.value = t.value[1:].strip() - if t.value in self.reserved.keys(): - t.type = self.reserved[t.value] - else: - t.type = 'LINE' - return t - - def t_comment(self, t): - r'\#.*' - pass - - def t_newline(self, t): - r'\n+' - t.lexer.lineno += len(t.value) - - def t_whitespace(self, t): - r'\s+' - pass - - def build(self, **kwargs): - self.lexer = lex.lex(module=self, **kwargs) - - def token(self): - return self.lexer.token() - - def input(self, data): - self.lexer.input(data) - - def t_error(self, t): - t.lexer.skip(1) - t.value = 'Lexer error' - return t diff --git a/spdx/parsers/loggers.py b/spdx/parsers/loggers.py deleted file mode 100644 index c4a4f891f..000000000 --- a/spdx/parsers/loggers.py +++ /dev/null @@ -1,30 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - - -class StandardLogger(object): - - def log(self, msg): - print(msg) - - -class FileLogger(object): - - def __init__(self, logfile): - self.dest = logfile - - def log(self, msg): - self.dest.write(msg + '\n') diff --git a/spdx/parsers/rdf.py b/spdx/parsers/rdf.py deleted file mode 100644 index 40cd59c90..000000000 --- a/spdx/parsers/rdf.py +++ /dev/null @@ -1,1185 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import re - -import six -from six.moves import reduce - -from rdflib import Graph -from rdflib import Namespace -from rdflib import RDF -from rdflib import RDFS - -from spdx import document -from spdx import utils -from spdx.parsers.builderexceptions import CardinalityError -from spdx.parsers.builderexceptions import SPDXValueError - - -ERROR_MESSAGES = { - 'DOC_VERS_VALUE': 'Invalid specVersion \'{0}\' must be SPDX-M.N where M and N are numbers.', - 'DOC_D_LICS': 'Invalid dataLicense \'{0}\' must be http://spdx.org/licenses/CC0-1.0.', - 'DOC_SPDX_ID_VALUE': 'Invalid SPDXID value, SPDXID must be the document namespace appended ' - 'by "#SPDXRef-DOCUMENT", line: {0}', - 'DOC_NAMESPACE_VALUE': 'Invalid DocumentNamespace value {0}, must contain a scheme (e.g. "https:") ' - 'and should not contain the "#" delimiter.', - 'LL_VALUE': 'Invalid licenseListVersion \'{0}\' must be of the format N.N where N is a number', - 'CREATED_VALUE': 'Invalid created value \'{0}\' must be date in ISO 8601 format.', - 'CREATOR_VALUE': 'Invalid creator value \'{0}\' must be Organization, Tool or Person.', - 'EXT_DOC_REF_VALUE': 'Failed to extract {0} from ExternalDocumentRef.', - 'PKG_SPDX_ID_VALUE': 'SPDXID must be "SPDXRef-[idstring]" where [idstring] is a unique string containing ' - 'letters, numbers, ".", "-".', - 'PKG_SUPPL_VALUE': 'Invalid package supplier value \'{0}\' must be Organization, Person or NOASSERTION.', - 'PKG_ORIGINATOR_VALUE': 'Invalid package supplier value \'{0}\' must be Organization, Person or NOASSERTION.', - 'PKG_DOWN_LOC': 'Invalid package download location value \'{0}\' must be a url or NONE or NOASSERTION', - 'PKG_FILES_ANALYZED_VALUE': 'FilesAnalyzed must be a boolean value, line: {0}', - 'PKG_CONC_LIST': 'Package concluded license list must have more than one member', - 'LICS_LIST_MEMBER' : 'Declaritive or Conjunctive license set member must be a license url or identifier', - 'PKG_SINGLE_LICS' : 'Package concluded license must be a license url or spdx:noassertion or spdx:none.', - 'PKG_LICS_INFO_FILES' : 'Package licenseInfoFromFiles must be a license or spdx:none or spdx:noassertion', - 'FILE_SPDX_ID_VALUE': 'SPDXID must be "SPDXRef-[idstring]" where [idstring] is a unique string containing ' - 'letters, numbers, ".", "-".', - 'PKG_EXT_REF_CATEGORY': '\'{0}\' must be "SECURITY", "PACKAGE-MANAGER", or "OTHER".', - 'PKG_EXT_REF_TYPE': '{0} must be a unique string containing letters, numbers, ".", or "-".', - 'FILE_TYPE' : 'File type must be binary, other, source or archive term.', - 'FILE_SINGLE_LICS': 'File concluded license must be a license url or spdx:noassertion or spdx:none.', - 'REVIEWER_VALUE' : 'Invalid reviewer value \'{0}\' must be Organization, Tool or Person.', - 'REVIEW_DATE' : 'Invalid review date value \'{0}\' must be date in ISO 8601 format.', - 'ANNOTATOR_VALUE': 'Invalid annotator value \'{0}\' must be Organization, Tool or Person.', - 'ANNOTATION_DATE': 'Invalid annotation date value \'{0}\' must be date in ISO 8601 format.', - 'SNIPPET_SPDX_ID_VALUE' : 'SPDXID must be "SPDXRef-[idstring]" where [idstring] is a unique string ' - 'containing letters, numbers, ".", "-".', - 'SNIPPET_SINGLE_LICS' : 'Snippet Concluded License must be a license url or spdx:noassertion or spdx:none.', - 'SNIPPET_LIC_INFO' : 'License Information in Snippet must be a license url or a reference ' - 'to the license, denoted by LicenseRef-[idstring] or spdx:noassertion or spdx:none.', -} - - -class BaseParser(object): - """ - Base class for all parsers. - Contains logger, doap_namespace, spdx_namespace and model builder. - Also provides utility functions used by the deriving parsers. - """ - - def __init__(self, builder, logger): - self.logger = logger - self.doap_namespace = Namespace('http://usefulinc.com/ns/doap#') - self.spdx_namespace = Namespace("http://spdx.org/rdf/terms#") - self.builder = builder - - def more_than_one_error(self, field): - """ - Logs a more than one error. - field is the field/property that has more than one defined. - """ - msg = 'More than one {0} defined.'.format(field) - self.logger.log(msg) - self.error = True - - def value_error(self, key, bad_value): - """ - Report a value error using ERROR_MESSAGES dict. - key - key to use for ERROR_MESSAGES. - bad_value - is passed to format which is called on what key maps to - in ERROR_MESSAGES. - """ - msg = ERROR_MESSAGES[key].format(bad_value) - self.logger.log(msg) - self.error = True - - def to_special_value(self, value): - """ - Check if value is a special SPDX value such as - NONE, NOASSERTION or UNKNOWN if so returns proper model. - else returns value - """ - if value == self.spdx_namespace.none: - return utils.SPDXNone() - elif value == self.spdx_namespace.noassertion: - return utils.NoAssert() - elif value == self.spdx_namespace.unknown: - return utils.UnKnown() - else: - return six.text_type(value) - - -class LicenseParser(BaseParser): - """ - Helper class for parsing extracted licenses and license lists. - """ - - LICS_REF_REGEX = re.compile('LicenseRef-.+', re.UNICODE) - - def __init__(self, builder, logger): - super(LicenseParser, self).__init__(builder, logger) - - def handle_lics(self, lics): - """ - Return a License from a `lics` license resource. - """ - # Handle extracted licensing info type. - if (lics, RDF.type, self.spdx_namespace['ExtractedLicensingInfo']) in self.graph: - return self.parse_only_extr_license(lics) - - # Assume resource, hence the path separator - ident_start = lics.rfind('/') + 1 - if ident_start == 0: - # special values such as spdx:noassertion - special = self.to_special_value(lics) - if special == lics: - if self.LICS_REF_REGEX.match(lics): - # Is a license ref i.e LicenseRef-1 - return document.License.from_identifier(six.text_type(lics)) - else: - # Not a known license form - raise SPDXValueError('License') - else: - # is a special value - return special - else: - # license url - return document.License.from_identifier(lics[ident_start:]) - - def get_extr_license_ident(self, extr_lic): - """ - Return a license identifier from an ExtractedLicense or None. - """ - identifier_tripples = list(self.graph.triples((extr_lic, self.spdx_namespace['licenseId'], None))) - - if not identifier_tripples: - self.error = True - msg = 'Extracted license must have licenseId property.' - self.logger.log(msg) - return - - if len(identifier_tripples) > 1: - self.more_than_one_error('extracted license identifier_tripples') - return - - identifier_tripple = identifier_tripples[0] - _s, _p, identifier = identifier_tripple - return six.text_type(identifier) - - def get_extr_license_text(self, extr_lic): - """ - Return extracted text from an ExtractedLicense or None. - """ - text_tripples = list(self.graph.triples((extr_lic, self.spdx_namespace['extractedText'], None))) - if not text_tripples: - self.error = True - msg = 'Extracted license must have extractedText property' - self.logger.log(msg) - return - - if len(text_tripples) > 1: - self.more_than_one_error('extracted license text') - return - - text_tripple = text_tripples[0] - _s, _p, text = text_tripple - return six.text_type(text) - - def get_extr_lic_name(self, extr_lic): - """ - Return the license name from an ExtractedLicense or None - """ - extr_name_list = list(self.graph.triples((extr_lic, self.spdx_namespace['licenseName'], None))) - if len(extr_name_list) > 1: - self.more_than_one_error('extracted license name') - return - elif len(extr_name_list) == 0: - return - return six.text_type(self.to_special_value(extr_name_list[0][2])) - - def get_extr_lics_xref(self, extr_lic): - """ - Return a list of cross references. - """ - xrefs = list(self.graph.triples((extr_lic, RDFS.seeAlso, None))) - return list(map(lambda xref_triple: xref_triple[2], xrefs)) - - def get_extr_lics_comment(self, extr_lics): - """ - Return license comment or None. - """ - comment_list = list(self.graph.triples( - (extr_lics, RDFS.comment, None))) - if len(comment_list) > 1 : - self.more_than_one_error('extracted license comment') - return - elif len(comment_list) == 1: - return six.text_type(comment_list[0][2]) - else: - return - - def parse_only_extr_license(self, extr_lic): - """ - Return an ExtractedLicense object to represent a license object. - But does not add it to the SPDXDocument model. - Return None if failed. - """ - # Grab all possible values - ident = self.get_extr_license_ident(extr_lic) - text = self.get_extr_license_text(extr_lic) - comment = self.get_extr_lics_comment(extr_lic) - xrefs = self.get_extr_lics_xref(extr_lic) - name = self.get_extr_lic_name(extr_lic) - - if not ident: - # Must have identifier - return - - # Set fields - # FIXME: the constructor of the license should alwas accept a name - lic = document.ExtractedLicense(ident) - if text is not None: - lic.text = text - if name is not None: - lic.full_name = name - if comment is not None: - lic.comment = comment - lic.cross_ref = list(map(lambda x: six.text_type(x), xrefs)) - return lic - - def handle_extracted_license(self, extr_lic): - """ - Build and return an ExtractedLicense or None. - Note that this function adds the license to the document. - """ - lic = self.parse_only_extr_license(extr_lic) - if lic is not None: - self.doc.add_extr_lic(lic) - return lic - - def _handle_license_list(self, lics_set, cls=None): - """ - Return a license representing a `cls` object (LicenseConjunction - or LicenseDisjunction) from a list of license resources or None. - """ - licenses = [] - for _, _, lics_member in self.graph.triples( - (lics_set, self.spdx_namespace['member'], None)): - try: - licenses.append(self.handle_lics(lics_member)) - except CardinalityError: - self.value_error('LICS_LIST_MEMBER', lics_member) - break - if len(licenses) > 1: - return reduce(lambda a, b: cls(a, b), licenses) - else: - self.value_error('PKG_CONC_LIST', '') - return - - def handle_conjunctive_list(self, lics_set): - """ - Return a license representing the conjunction from a list of - license resources or None. - """ - return self._handle_license_list(lics_set, cls=document.LicenseConjunction) - - def handle_disjunctive_list(self, lics_set): - """ - Return a license representing the disjunction from a list of - license resources or None. - """ - return self._handle_license_list(lics_set, cls=document.LicenseDisjunction) - - -class PackageParser(LicenseParser): - """ - Helper class for parsing packages. - """ - - def __init__(self, builder, logger): - super(PackageParser, self).__init__(builder, logger) - - def parse_package(self, p_term): - """ - Parse package fields. - """ - # Check there is a pacakge name - if not (p_term, self.spdx_namespace['name'], None) in self.graph: - self.error = True - self.logger.log('Package must have a name.') - # Create dummy package so that we may continue parsing the rest of - # the package fields. - self.builder.create_package(self.doc, 'dummy_package') - else: - for _s, _p, o in self.graph.triples((p_term, self.spdx_namespace['name'], None)): - try: - self.builder.create_package(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('Package name') - break - # Set SPDXID - try: - if p_term.count('#', 0, len(p_term)) == 1: - pkg_spdx_id = p_term.split('#')[-1] - self.builder.set_pkg_spdx_id(self.doc, pkg_spdx_id) - else: - self.value_error('PKG_SPDX_ID_VALUE', p_term) - except SPDXValueError: - self.value_error('PKG_SPDX_ID_VALUE', p_term) - - self.p_pkg_vinfo(p_term, self.spdx_namespace['versionInfo']) - self.p_pkg_fname(p_term, self.spdx_namespace['packageFileName']) - self.p_pkg_suppl(p_term, self.spdx_namespace['supplier']) - self.p_pkg_originator(p_term, self.spdx_namespace['originator']) - self.p_pkg_down_loc(p_term, self.spdx_namespace['downloadLocation']) - self.p_pkg_files_analyzed(p_term, self.spdx_namespace['filesAnalyzed']) - self.p_pkg_homepg(p_term, self.doap_namespace['homepage']) - self.p_pkg_chk_sum(p_term, self.spdx_namespace['checksum']) - self.p_pkg_src_info(p_term, self.spdx_namespace['sourceInfo']) - self.p_pkg_verif_code(p_term, self.spdx_namespace['packageVerificationCode']) - self.p_pkg_lic_conc(p_term, self.spdx_namespace['licenseConcluded']) - self.p_pkg_lic_decl(p_term, self.spdx_namespace['licenseDeclared']) - self.p_pkg_lics_info_from_files(p_term, self.spdx_namespace['licenseInfoFromFiles']) - self.p_pkg_comments_on_lics(p_term, self.spdx_namespace['licenseComments']) - self.p_pkg_cr_text(p_term, self.spdx_namespace['copyrightText']) - self.p_pkg_summary(p_term, self.spdx_namespace['summary']) - self.p_pkg_descr(p_term, self.spdx_namespace['description']) - self.p_pkg_comment(p_term, self.spdx_namespace['comment']) - - def p_pkg_cr_text(self, p_term, predicate): - try: - for _, _, text in self.graph.triples((p_term, predicate, None)): - self.builder.set_pkg_cr_text(self.doc, six.text_type(self.to_special_value(text))) - except CardinalityError: - self.more_than_one_error('package copyright text') - - def p_pkg_summary(self, p_term, predicate): - try: - for _, _, summary in self.graph.triples((p_term, predicate, None)): - self.builder.set_pkg_summary(self.doc, six.text_type(summary)) - except CardinalityError: - self.more_than_one_error('package summary') - - def p_pkg_descr(self, p_term, predicate): - try: - for _, _, desc in self.graph.triples( - (p_term, predicate, None)): - self.builder.set_pkg_desc(self.doc, six.text_type(desc)) - except CardinalityError: - self.more_than_one_error('package description') - - def p_pkg_comment(self, p_term, predicate): - try: - for _, _, comment in self.graph.triples((p_term, predicate, None)): - self.builder.set_pkg_comment(self.doc, six.text_type(comment)) - except CardinalityError: - self.more_than_one_error('package comment') - - def p_pkg_comments_on_lics(self, p_term, predicate): - for _, _, comment in self.graph.triples((p_term, predicate, None)): - try: - self.builder.set_pkg_license_comment(self.doc, six.text_type(comment)) - except CardinalityError: - self.more_than_one_error('package comments on license') - break - - def p_pkg_lics_info_from_files(self, p_term, predicate): - for _, _, lics in self.graph.triples((p_term, predicate, None)): - try: - if (lics, RDF.type, self.spdx_namespace['ExtractedLicensingInfo']) in self.graph: - self.builder.set_pkg_license_from_file(self.doc, self.parse_only_extr_license(lics)) - else: - self.builder.set_pkg_license_from_file(self.doc, self.handle_lics(lics)) - - except SPDXValueError: - self.value_error('PKG_LICS_INFO_FILES', lics) - - def p_pkg_lic_decl(self, p_term, predicate): - self.handle_pkg_lic(p_term, predicate, self.builder.set_pkg_license_declared) - - def handle_pkg_lic(self, p_term, predicate, builder_func): - """ - Handle package lics concluded or declared. - """ - try: - for _, _, licenses in self.graph.triples((p_term, predicate, None)): - if (licenses, RDF.type, self.spdx_namespace['ConjunctiveLicenseSet']) in self.graph: - lics = self.handle_conjunctive_list(licenses) - builder_func(self.doc, lics) - - elif (licenses, RDF.type, self.spdx_namespace['DisjunctiveLicenseSet']) in self.graph: - lics = self.handle_disjunctive_list(licenses) - builder_func(self.doc, lics) - - else: - try: - lics = self.handle_lics(licenses) - builder_func(self.doc, lics) - except SPDXValueError: - self.value_error('PKG_SINGLE_LICS', licenses) - except CardinalityError: - self.more_than_one_error('package {0}'.format(predicate)) - - def p_pkg_lic_conc(self, p_term, predicate): - self.handle_pkg_lic(p_term, predicate, self.builder.set_pkg_licenses_concluded) - - def p_pkg_verif_code(self, p_term, predicate): - for _, _, verifcode in self.graph.triples((p_term, predicate, None)): - # Parse verification code - for _, _, code in self.graph.triples((verifcode, self.spdx_namespace['packageVerificationCodeValue'], None)): - try: - self.builder.set_pkg_verif_code(self.doc, six.text_type(code)) - except CardinalityError: - self.more_than_one_error('package verificaton code') - break - # Parse excluded file - for _, _, filename in self.graph.triples((verifcode, self.spdx_namespace['packageVerificationCodeExcludedFile'], None)): - try: - self.builder.set_pkg_excl_file(self.doc, six.text_type(filename)) - except CardinalityError: - self.more_than_one_error('package verificaton code excluded file') - break - - def p_pkg_src_info(self, p_term, predicate): - for _, _, o in self.graph.triples((p_term, predicate, None)): - try: - self.builder.set_pkg_source_info(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('package source info') - break - - def p_pkg_chk_sum(self, p_term, predicate): - for _s, _p, checksum in self.graph.triples((p_term, predicate, None)): - for _, _, value in self.graph.triples((checksum, self.spdx_namespace['checksumValue'], None)): - try: - self.builder.set_pkg_chk_sum(self.doc, six.text_type(value)) - except CardinalityError: - self.more_than_one_error('Package checksum') - break - - def p_pkg_homepg(self, p_term, predicate): - for _s, _p, o in self.graph.triples((p_term, predicate, None)): - try: - self.builder.set_pkg_home(self.doc, six.text_type(self.to_special_value(o))) - except CardinalityError: - self.more_than_one_error('Package home page') - break - except SPDXValueError: - self.value_error('PKG_HOME_PAGE', o) - - def p_pkg_down_loc(self, p_term, predicate): - for _s, _p, o in self.graph.triples((p_term, predicate, None)): - try: - self.builder.set_pkg_down_location(self.doc, six.text_type(self.to_special_value(o))) - except CardinalityError: - self.more_than_one_error('Package download location') - break - except SPDXValueError: - self.value_error('PKG_DOWN_LOC', o) - - def p_pkg_files_analyzed(self, p_term, predicate): - for _s, _p, o in self.graph.triples((p_term, predicate, None)): - try: - self.builder.set_pkg_files_analyzed(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('Package Files Analyzed') - break - except SPDXValueError: - self.value_error('PKG_FILES_ANALYZED_VALUE', o) - - def p_pkg_originator(self, p_term, predicate): - for _s, _p, o in self.graph.triples((p_term, predicate, None)): - try: - if o == "NOASSERTION": - self.builder.set_pkg_originator(self.doc, utils.NoAssert()) - else: - ent = self.builder.create_entity(self.doc, six.text_type(o)) - self.builder.set_pkg_originator(self.doc, ent) - except CardinalityError: - self.more_than_one_error('Package originator') - break - except SPDXValueError: - self.value_error('PKG_ORIGINATOR_VALUE', o) - - def p_pkg_suppl(self, p_term, predicate): - for _s, _p, o in self.graph.triples((p_term, predicate, None)): - try: - if o == "NOASSERTION": - self.builder.set_pkg_supplier(self.doc, utils.NoAssert()) - else: - ent = self.builder.create_entity(self.doc, six.text_type(o)) - self.builder.set_pkg_supplier(self.doc, ent) - except CardinalityError: - self.more_than_one_error('Package supplier') - break - except SPDXValueError: - self.value_error('PKG_SUPPL_VALUE', o) - - def p_pkg_fname(self, p_term, predicate): - for _s, _p, o in self.graph.triples((p_term, predicate, None)): - try: - self.builder.set_pkg_file_name(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('Package file name') - break - - def p_pkg_vinfo(self, p_term, predicate): - for _s, _p, o in self.graph.triples((p_term, predicate, None)): - try: - self.builder.set_pkg_vers(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('Package version info') - break - - -class FileParser(LicenseParser): - """ - Helper class for parsing files. - """ - - def __init__(self, builder, logger): - super(FileParser, self).__init__(builder, logger) - - def parse_file(self, f_term): - if not (f_term, self.spdx_namespace['fileName'], None) in self.graph: - self.error = True - self.logger.log('File must have a name.') - # Dummy name to continue - self.builder.set_file_name(self.doc, 'Dummy file') - else: - for _, _, name in self.graph.triples((f_term, self.spdx_namespace['fileName'], None)): - self.builder.set_file_name(self.doc, six.text_type(name)) - - self.p_file_spdx_id(f_term, self.spdx_namespace['File']) - self.p_file_type(f_term, self.spdx_namespace['fileType']) - self.p_file_chk_sum(f_term, self.spdx_namespace['checksum']) - self.p_file_lic_conc(f_term, self.spdx_namespace['licenseConcluded']) - self.p_file_lic_info(f_term, self.spdx_namespace['licenseInfoInFile']) - self.p_file_comments_on_lics(f_term, self.spdx_namespace['licenseComments']) - self.p_file_cr_text(f_term, self.spdx_namespace['copyrightText']) - self.p_file_artifact(f_term, self.spdx_namespace['artifactOf']) - self.p_file_comment(f_term, RDFS.comment) - self.p_file_notice(f_term, self.spdx_namespace['noticeText']) - self.p_file_contributor(f_term, self.spdx_namespace['fileContributor']) - self.p_file_depends(f_term, self.spdx_namespace['fileDependency']) - - def get_file_name(self, f_term): - """Returns first found fileName property or None if not found.""" - for _, _, name in self.graph.triples((f_term, self.spdx_namespace['fileName'], None)): - return name - return - - def p_file_depends(self, f_term, predicate): - """ - Set file dependencies. - """ - for _, _, other_file in self.graph.triples((f_term, predicate, None)): - name = self.get_file_name(other_file) - if name is not None: - self.builder.add_file_dep(six.text_type(name)) - else: - self.error = True - msg = 'File depends on file with no name' - self.logger.log(msg) - - def p_file_contributor(self, f_term, predicate): - """ - Parse all file contributors and adds them to the model. - """ - for _, _, contributor in self.graph.triples((f_term, predicate, None)): - self.builder.add_file_contribution(self.doc, six.text_type(contributor)) - - def p_file_notice(self, f_term, predicate): - """ - Set file notice text. - """ - try: - for _, _, notice in self.graph.triples((f_term, predicate, None)): - self.builder.set_file_notice(self.doc, six.text_type(notice)) - except CardinalityError: - self.more_than_one_error('file notice') - - def p_file_comment(self, f_term, predicate): - """ - Set file comment text. - """ - try: - for _, _, comment in self.graph.triples((f_term, predicate, None)): - self.builder.set_file_comment(self.doc, six.text_type(comment)) - except CardinalityError: - self.more_than_one_error('file comment') - - - def p_file_artifact(self, f_term, predicate): - """ - Handle file artifactOf. - Note: does not handle artifact of project URI. - """ - for _, _, project in self.graph.triples((f_term, predicate, None)): - if (project, RDF.type, self.doap_namespace['Project']): - self.p_file_project(project) - else: - self.error = True - msg = 'File must be artifact of doap:Project' - self.logger.log(msg) - - def p_file_project(self, project): - """ - Helper function for parsing doap:project name and homepage. - and setting them using the file builder. - """ - for _, _, name in self.graph.triples((project, self.doap_namespace['name'], None)): - self.builder.set_file_atrificat_of_project(self.doc, 'name', six.text_type(name)) - for _, _, homepage in self.graph.triples( - (project, self.doap_namespace['homepage'], None)): - self.builder.set_file_atrificat_of_project(self.doc, 'home', six.text_type(homepage)) - - def p_file_cr_text(self, f_term, predicate): - """ - Set file copyright text. - """ - try: - for _, _, cr_text in self.graph.triples((f_term, predicate, None)): - self.builder.set_file_copyright(self.doc, six.text_type(cr_text)) - except CardinalityError: - self.more_than_one_error('file copyright text') - - def p_file_comments_on_lics(self, f_term, predicate): - """ - Set file license comment. - """ - try: - for _, _, comment in self.graph.triples((f_term, predicate, None)): - self.builder.set_file_license_comment(self.doc, six.text_type(comment)) - except CardinalityError: - self.more_than_one_error('file comments on license') - - def p_file_lic_info(self, f_term, predicate): - """ - Set file license information. - """ - for _, _, info in self.graph.triples((f_term, predicate, None)): - lic = self.handle_lics(info) - if lic is not None: - self.builder.set_file_license_in_file(self.doc, lic) - - def p_file_spdx_id(self, f_term, predicate): - try: - try: - self.builder.set_file_spdx_id(self.doc, six.text_type(f_term)) - except SPDXValueError: - self.value_error('FILE_SPDX_ID_VALUE', f_term) - except CardinalityError: - self.more_than_one_error('FILE_SPDX_ID_VALUE') - - def p_file_type(self, f_term, predicate): - """ - Set file type. - """ - try: - for _, _, ftype in self.graph.triples((f_term, predicate, None)): - try: - if ftype.endswith('binary'): - ftype = 'BINARY' - elif ftype.endswith('source'): - ftype = 'SOURCE' - elif ftype.endswith('other'): - ftype = 'OTHER' - elif ftype.endswith('archive'): - ftype = 'ARCHIVE' - self.builder.set_file_type(self.doc, ftype) - except SPDXValueError: - self.value_error('FILE_TYPE', ftype) - except CardinalityError: - self.more_than_one_error('file type') - - def p_file_chk_sum(self, f_term, predicate): - """ - Set file checksum. Assumes SHA1 algorithm without checking. - """ - try: - for _s, _p, checksum in self.graph.triples((f_term, predicate, None)): - for _, _, value in self.graph.triples((checksum, self.spdx_namespace['checksumValue'], None)): - self.builder.set_file_chksum(self.doc, six.text_type(value)) - except CardinalityError: - self.more_than_one_error('File checksum') - - def p_file_lic_conc(self, f_term, predicate): - """ - Set file licenses concluded. - """ - try: - for _, _, licenses in self.graph.triples((f_term, predicate, None)): - if (licenses, RDF.type, self.spdx_namespace['ConjunctiveLicenseSet']) in self.graph: - lics = self.handle_conjunctive_list(licenses) - self.builder.set_concluded_license(self.doc, lics) - - elif (licenses, RDF.type, self.spdx_namespace['DisjunctiveLicenseSet']) in self.graph: - lics = self.handle_disjunctive_list(licenses) - self.builder.set_concluded_license(self.doc, lics) - - else: - try: - lics = self.handle_lics(licenses) - self.builder.set_concluded_license(self.doc, lics) - except SPDXValueError: - self.value_error('FILE_SINGLE_LICS', licenses) - except CardinalityError: - self.more_than_one_error('file {0}'.format(predicate)) - - -class SnippetParser(LicenseParser): - """ - Helper class for parsing snippet information. - """ - - def __init__(self, builder, logger): - super(SnippetParser, self).__init__(builder, logger) - - def parse_snippet(self, snippet_term): - try: - self.builder.create_snippet(self.doc, snippet_term) - except SPDXValueError: - self.value_error('SNIPPET_SPDX_ID_VALUE', snippet_term) - - for _s, _p, o in self.graph.triples((snippet_term, self.spdx_namespace['name'], None)): - try: - self.builder.set_snippet_name(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('snippetName') - break - - for _s, _p, o in self.graph.triples((snippet_term, self.spdx_namespace['licenseComments'], None)): - try: - self.builder.set_snippet_lic_comment(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('licenseComments') - break - - for _s, _p, o in self.graph.triples((snippet_term, RDFS.comment, None)): - try: - self.builder.set_snippet_comment(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('comment') - break - - for _s, _p, o in self.graph.triples((snippet_term, self.spdx_namespace['copyrightText'], None)): - try: - self.builder.set_snippet_copyright(self.doc, self.to_special_value(six.text_type(o))) - except CardinalityError: - self.more_than_one_error('copyrightText') - break - - try: - for _, _, licenses in self.graph.triples( - (snippet_term, self.spdx_namespace['licenseConcluded'], None)): - if (licenses, RDF.type, self.spdx_namespace['ConjunctiveLicenseSet']) in self.graph: - lics = self.handle_conjunctive_list(licenses) - self.builder.set_snip_concluded_license(self.doc, lics) - - elif (licenses, RDF.type, self.spdx_namespace['DisjunctiveLicenseSet']) in self.graph: - lics = self.handle_disjunctive_list(licenses) - self.builder.set_snip_concluded_license(self.doc, lics) - - else: - try: - lics = self.handle_lics(licenses) - self.builder.set_snip_concluded_license(self.doc, lics) - except SPDXValueError: - self.value_error('SNIPPET_SINGLE_LICS', licenses) - except CardinalityError: - self.more_than_one_error('package {0}'.format( - self.spdx_namespace['licenseConcluded'])) - - for _, _, info in self.graph.triples( - (snippet_term, self.spdx_namespace['licenseInfoInSnippet'], None)): - lic = self.handle_lics(info) - if lic is not None: - try: - self.builder.set_snippet_lics_info(self.doc, lic) - except SPDXValueError: - self.value_error('SNIPPET_LIC_INFO', lic) - - for _s, _p, o in self.graph.triples( - (snippet_term, self.spdx_namespace['snippetFromFile'], None)): - try: - self.builder.set_snip_from_file_spdxid(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('snippetFromFile') - break - - -class ReviewParser(BaseParser): - """ - Helper class for parsing review information. - """ - - def __init__(self, builder, logger): - super(ReviewParser, self).__init__(builder, logger) - - def parse_review(self, r_term): - reviewer = self.get_reviewer(r_term) - reviewed_date = self.get_review_date(r_term) - if reviewer is not None: - self.builder.add_reviewer(self.doc, reviewer) - if reviewed_date is not None: - try: - self.builder.add_review_date(self.doc, reviewed_date) - except SPDXValueError: - self.value_error('REVIEW_DATE', reviewed_date) - comment = self.get_review_comment(r_term) - if comment is not None: - self.builder.add_review_comment(self.doc, comment) - - def get_review_comment(self, r_term): - """ - Return review comment or None if found none or more than one. - Report errors. - """ - comment_list = list(self.graph.triples((r_term, RDFS.comment, None))) - if len(comment_list) > 1: - self.error = True - msg = 'Review can have at most one comment' - self.logger.log(msg) - return - else: - return six.text_type(comment_list[0][2]) - - def get_review_date(self, r_term): - """ - Return review date or None if not found. - Report error on failure. - Note does not check value format. - """ - reviewed_list = list(self.graph.triples((r_term, self.spdx_namespace['reviewDate'], None))) - if len(reviewed_list) != 1: - self.error = True - msg = 'Review must have exactlyone review date' - self.logger.log(msg) - return - return six.text_type(reviewed_list[0][2]) - - def get_reviewer(self, r_term): - """ - Return reviewer as creator object or None if failed. - Report errors on failure. - """ - reviewer_list = list(self.graph.triples((r_term, self.spdx_namespace['reviewer'], None))) - if len(reviewer_list) != 1: - self.error = True - msg = 'Review must have exactly one reviewer' - self.logger.log(msg) - return - try: - return self.builder.create_entity(self.doc, six.text_type(reviewer_list[0][2])) - except SPDXValueError: - self.value_error('REVIEWER_VALUE', reviewer_list[0][2]) - - -class AnnotationParser(BaseParser): - """ - Helper class for parsing annotation information. - """ - - def __init__(self, builder, logger): - super(AnnotationParser, self).__init__(builder, logger) - - def parse_annotation(self, r_term): - annotator = self.get_annotator(r_term) - annotation_date = self.get_annotation_date(r_term) - if annotator is not None: - self.builder.add_annotator(self.doc, annotator) - if annotation_date is not None: - try: - self.builder.add_annotation_date(self.doc, annotation_date) - except SPDXValueError: - self.value_error('ANNOTATION_DATE', annotation_date) - comment = self.get_annotation_comment(r_term) - if comment is not None: - self.builder.add_annotation_comment(self.doc, comment) - annotation_type = self.get_annotation_type(r_term) - self.builder.add_annotation_type(self.doc, annotation_type) - try: - self.builder.set_annotation_spdx_id(self.doc, six.text_type(r_term)) - except CardinalityError: - self.more_than_one_error('SPDX Identifier Reference') - - def get_annotation_type(self, r_term): - """ - Return annotation type or None if found none or more than one. - Report errors on failure. - """ - for _, _, typ in self.graph.triples(( - r_term, self.spdx_namespace['annotationType'], None)): - if typ is not None: - return six.text_type(typ) - else: - self.error = True - msg = 'Annotation must have exactly one annotation type.' - self.logger.log(msg) - return - - def get_annotation_comment(self, r_term): - """ - Return annotation comment or None if found none or more than one. - Report errors. - """ - comment_list = list(self.graph.triples((r_term, RDFS.comment, None))) - if len(comment_list) > 1: - self.error = True - msg = 'Annotation can have at most one comment.' - self.logger.log(msg) - return - else: - return six.text_type(comment_list[0][2]) - - def get_annotation_date(self, r_term): - """ - Return annotation date or None if not found. - Report error on failure. - Note does not check value format. - """ - annotation_date_list = list(self.graph.triples((r_term, self.spdx_namespace['annotationDate'], None))) - if len(annotation_date_list) != 1: - self.error = True - msg = 'Annotation must have exactly one annotation date.' - self.logger.log(msg) - return - return six.text_type(annotation_date_list[0][2]) - - def get_annotator(self, r_term): - """ - Return annotator as creator object or None if failed. - Report errors on failure. - """ - annotator_list = list(self.graph.triples((r_term, self.spdx_namespace['annotator'], None))) - if len(annotator_list) != 1: - self.error = True - msg = 'Annotation must have exactly one annotator' - self.logger.log(msg) - return - try: - return self.builder.create_entity(self.doc, six.text_type(annotator_list[0][2])) - except SPDXValueError: - self.value_error('ANNOTATOR_VALUE', annotator_list[0][2]) - - -class Parser(PackageParser, FileParser, SnippetParser, ReviewParser, AnnotationParser): - """ - RDF/XML file parser. - """ - - def __init__(self, builder, logger): - super(Parser, self).__init__(builder, logger) - - def parse(self, fil): - """ - Parse a file and returns a document object. - fil is a file like object. - """ - self.error = False - self.graph = Graph() - self.graph.parse(file=fil, format='xml') - self.doc = document.Document() - - for s, _p, o in self.graph.triples((None, RDF.type, self.spdx_namespace['SpdxDocument'])): - self.parse_doc_fields(s) - - for s, _p, o in self.graph.triples((None, RDF.type, self.spdx_namespace['ExternalDocumentRef'])): - self.parse_ext_doc_ref(s) - - for s, _p, o in self.graph.triples((None, RDF.type, self.spdx_namespace['CreationInfo'])): - self.parse_creation_info(s) - - for s, _p, o in self.graph.triples((None, None, self.spdx_namespace['ExtractedLicensingInfo'])): - self.handle_extracted_license(s) - - for s, _p, o in self.graph.triples((None, RDF.type, self.spdx_namespace['Package'])): - self.parse_package(s) - - for s, _p, o in self.graph.triples((None, RDF.type, self.spdx_namespace['ExternalRef'])): - self.parse_pkg_ext_ref(s) - - for s, _p, o in self.graph.triples((None, self.spdx_namespace['referencesFile'], None)): - self.parse_file(o) - - for s, _p, o in self.graph.triples((None, RDF.type, self.spdx_namespace['Snippet'])): - self.parse_snippet(s) - - for s, _p, o in self.graph.triples((None, self.spdx_namespace['reviewed'], None)): - self.parse_review(o) - - for s, _p, o in self.graph.triples((None, self.spdx_namespace['annotation'], None)): - self.parse_annotation(o) - - validation_messages = [] - # Report extra errors if self.error is False otherwise there will be - # redundent messages - validation_messages = self.doc.validate(validation_messages) - if not self.error: - if validation_messages: - for msg in validation_messages: - self.logger.log(msg) - self.error = True - return self.doc, self.error - - def parse_creation_info(self, ci_term): - """ - Parse creators, created and comment. - """ - for _s, _p, o in self.graph.triples((ci_term, self.spdx_namespace['creator'], None)): - try: - ent = self.builder.create_entity(self.doc, six.text_type(o)) - self.builder.add_creator(self.doc, ent) - except SPDXValueError: - self.value_error('CREATOR_VALUE', o) - - for _s, _p, o in self.graph.triples((ci_term, self.spdx_namespace['created'], None)): - try: - self.builder.set_created_date(self.doc, six.text_type(o)) - except SPDXValueError: - self.value_error('CREATED_VALUE', o) - except CardinalityError: - self.more_than_one_error('created') - break - - for _s, _p, o in self.graph.triples((ci_term, RDFS.comment, None)): - try: - self.builder.set_creation_comment(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('CreationInfo comment') - break - for _s, _p, o in self.graph.triples((ci_term, self.spdx_namespace['licenseListVersion'], None)): - try: - self.builder.set_lics_list_ver(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('licenseListVersion') - break - except SPDXValueError: - self.value_error('LL_VALUE', o) - - def parse_doc_fields(self, doc_term): - """ - Parse the version, data license, name, SPDX Identifier, namespace, - and comment. - """ - try: - self.builder.set_doc_spdx_id(self.doc, six.text_type(doc_term)) - except SPDXValueError: - self.value_error('DOC_SPDX_ID_VALUE', doc_term) - try: - if doc_term.count('#', 0, len(doc_term)) <= 1: - doc_namespace = doc_term.split('#')[0] - self.builder.set_doc_namespace(self.doc, doc_namespace) - else: - self.value_error('DOC_NAMESPACE_VALUE', doc_term) - except SPDXValueError: - self.value_error('DOC_NAMESPACE_VALUE', doc_term) - for _s, _p, o in self.graph.triples((doc_term, self.spdx_namespace['specVersion'], None)): - try: - self.builder.set_doc_version(self.doc, six.text_type(o)) - except SPDXValueError: - self.value_error('DOC_VERS_VALUE', o) - except CardinalityError: - self.more_than_one_error('specVersion') - break - for _s, _p, o in self.graph.triples((doc_term, self.spdx_namespace['dataLicense'], None)): - try: - self.builder.set_doc_data_lic(self.doc, six.text_type(o)) - except SPDXValueError: - self.value_error('DOC_D_LICS', o) - except CardinalityError: - self.more_than_one_error('dataLicense') - break - for _s, _p, o in self.graph.triples( - (doc_term, self.spdx_namespace['name'], None)): - try: - self.builder.set_doc_name(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('name') - break - for _s, _p, o in self.graph.triples((doc_term, RDFS.comment, None)): - try: - self.builder.set_doc_comment(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('Document comment') - break - - def parse_ext_doc_ref(self, ext_doc_ref_term): - """ - Parse the External Document ID, SPDX Document URI and Checksum. - """ - for _s, _p, o in self.graph.triples( - (ext_doc_ref_term, - self.spdx_namespace['externalDocumentId'], - None)): - try: - self.builder.set_ext_doc_id(self.doc, six.text_type(o)) - except SPDXValueError: - self.value_error('EXT_DOC_REF_VALUE', 'External Document ID') - break - - for _s, _p, o in self.graph.triples( - (ext_doc_ref_term, - self.spdx_namespace['spdxDocument'], - None)): - try: - self.builder.set_spdx_doc_uri(self.doc, six.text_type(o)) - except SPDXValueError: - self.value_error('EXT_DOC_REF_VALUE', 'SPDX Document URI') - break - - for _s, _p, checksum in self.graph.triples( - (ext_doc_ref_term, self.spdx_namespace['checksum'], None)): - for _, _, value in self.graph.triples( - (checksum, self.spdx_namespace['checksumValue'], None)): - try: - self.builder.set_chksum(self.doc, six.text_type(value)) - except SPDXValueError: - self.value_error('EXT_DOC_REF_VALUE', 'Checksum') - break - - def parse_pkg_ext_ref(self, pkg_ext_term): - """ - Parse the category, type, locator, and comment. - """ - for _s, _p, o in self.graph.triples((pkg_ext_term, - self.spdx_namespace['referenceCategory'], - None)): - try: - self.builder.set_pkg_ext_ref_category(self.doc, six.text_type(o)) - except SPDXValueError: - self.value_error('PKG_EXT_REF_CATEGORY', - 'Package External Reference Category') - break - - for _s, _p, o in self.graph.triples((pkg_ext_term, - self.spdx_namespace['referenceType'], - None)): - try: - self.builder.set_pkg_ext_ref_type(self.doc, six.text_type(o)) - except SPDXValueError: - self.value_error('PKG_EXT_REF_TYPE', - 'Package External Reference Type') - break - - for _s, _p, o in self.graph.triples((pkg_ext_term, - self.spdx_namespace['referenceLocator'], - None)): - self.builder.set_pkg_ext_ref_locator(self.doc, six.text_type(o)) - - for _s, _p, o in self.graph.triples((pkg_ext_term, RDFS.comment, None)): - try: - self.builder.set_pkg_ext_ref_comment(self.doc, six.text_type(o)) - except CardinalityError: - self.more_than_one_error('Package External Reference Comment') - break diff --git a/spdx/parsers/rdfbuilders.py b/spdx/parsers/rdfbuilders.py deleted file mode 100644 index 4b17eaa3f..000000000 --- a/spdx/parsers/rdfbuilders.py +++ /dev/null @@ -1,589 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import re - -from spdx import checksum -from spdx import document -from spdx import package -from spdx import version -from spdx.parsers.builderexceptions import CardinalityError -from spdx.parsers.builderexceptions import OrderError -from spdx.parsers.builderexceptions import SPDXValueError -from spdx.parsers import tagvaluebuilders -from spdx.parsers import validations - - -class DocBuilder(object): - VERS_STR_REGEX = re.compile(r'SPDX-(\d+)\.(\d+)', re.UNICODE) - - def __init__(self): - # FIXME: this state does not make sense - self.reset_document() - - def set_doc_version(self, doc, value): - """ - Set the document version. - Raise SPDXValueError if malformed value. - Raise CardinalityError if already defined. - """ - if not self.doc_version_set: - self.doc_version_set = True - m = self.VERS_STR_REGEX.match(value) - if m is None: - raise SPDXValueError('Document::Version') - else: - doc.version = version.Version(major=int(m.group(1)), - minor=int(m.group(2))) - return True - else: - raise CardinalityError('Document::Version') - - def set_doc_data_lic(self, doc, res): - """ - Set the document data license. - Raise SPDXValueError if malformed value. - Raise CardinalityError if already defined. - """ - if not self.doc_data_lics_set: - self.doc_data_lics_set = True - # TODO: what is this split? - res_parts = res.split('/') - if len(res_parts) != 0: - identifier = res_parts[-1] - doc.data_license = document.License.from_identifier(identifier) - else: - raise SPDXValueError('Document::License') - else: - raise CardinalityError('Document::License') - - def set_doc_name(self, doc, name): - """ - Set the document name. - Raise CardinalityError if already defined. - """ - if not self.doc_name_set: - doc.name = name - self.doc_name_set = True - return True - else: - raise CardinalityError('Document::Name') - - def set_doc_spdx_id(self, doc, doc_spdx_id_line): - """ - Set the document SPDX Identifier. - Raise value error if malformed value. - Raise CardinalityError if already defined. - """ - if not self.doc_spdx_id_set: - if validations.validate_doc_spdx_id(doc_spdx_id_line): - doc.spdx_id = doc_spdx_id_line - self.doc_spdx_id_set = True - return True - else: - raise SPDXValueError('Document::SPDXID') - else: - raise CardinalityError('Document::SPDXID') - - def set_doc_comment(self, doc, comment): - """ - Set document comment. - Raise CardinalityError if comment already set. - """ - if not self.doc_comment_set: - self.doc_comment_set = True - doc.comment = comment - else: - raise CardinalityError('Document::Comment') - - def set_doc_namespace(self, doc, namespace): - """ - Set the document namespace. - Raise SPDXValueError if malformed value. - Raise CardinalityError if already defined. - """ - if not self.doc_namespace_set: - self.doc_namespace_set = True - if validations.validate_doc_namespace(namespace): - doc.namespace = namespace - return True - else: - raise SPDXValueError('Document::Namespace') - else: - raise CardinalityError('Document::Comment') - - def reset_document(self): - """ - Reset the internal state to allow building new document - """ - # FIXME: this state does not make sense - self.doc_version_set = False - self.doc_comment_set = False - self.doc_namespace_set = False - self.doc_data_lics_set = False - self.doc_name_set = False - self.doc_spdx_id_set = False - - -class ExternalDocumentRefBuilder(tagvaluebuilders.ExternalDocumentRefBuilder): - - def set_chksum(self, doc, chk_sum): - """ - Set the external document reference's check sum, if not already set. - chk_sum - The checksum value in the form of a string. - """ - if chk_sum: - doc.ext_document_references[-1].check_sum = checksum.Algorithm( - 'SHA1', chk_sum) - else: - raise SPDXValueError('ExternalDocumentRef::Checksum') - - -class EntityBuilder(tagvaluebuilders.EntityBuilder): - - def __init__(self): - super(EntityBuilder, self).__init__() - - def create_entity(self, doc, value): - if self.tool_re.match(value): - return self.build_tool(doc, value) - elif self.person_re.match(value): - return self.build_person(doc, value) - elif self.org_re.match(value): - return self.build_org(doc, value) - else: - raise SPDXValueError('Entity') - - -class CreationInfoBuilder(tagvaluebuilders.CreationInfoBuilder): - - def __init__(self): - super(CreationInfoBuilder, self).__init__() - - def set_creation_comment(self, doc, comment): - """ - Set creation comment. - Raise CardinalityError if comment already set. - Raise SPDXValueError if not free form text. - """ - if not self.creation_comment_set: - self.creation_comment_set = True - doc.creation_info.comment = comment - return True - else: - raise CardinalityError('CreationInfo::Comment') - - -class PackageBuilder(tagvaluebuilders.PackageBuilder): - - def __init__(self): - super(PackageBuilder, self).__init__() - - def set_pkg_chk_sum(self, doc, chk_sum): - """ - Set the package check sum, if not already set. - chk_sum - A string - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_chk_sum_set: - self.package_chk_sum_set = True - doc.package.check_sum = checksum.Algorithm('SHA1', chk_sum) - else: - raise CardinalityError('Package::CheckSum') - - def set_pkg_source_info(self, doc, text): - """ - Set the package's source information, if not already set. - text - Free form text. - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_source_info_set: - self.package_source_info_set = True - doc.package.source_info = text - return True - else: - raise CardinalityError('Package::SourceInfo') - - def set_pkg_verif_code(self, doc, code): - """ - Set the package verification code, if not already set. - code - A string. - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_verif_set: - self.package_verif_set = True - doc.package.verif_code = code - else: - raise CardinalityError('Package::VerificationCode') - - def set_pkg_excl_file(self, doc, filename): - """ - Set the package's verification code excluded file. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - doc.package.add_exc_file(filename) - - def set_pkg_license_comment(self, doc, text): - """ - Set the package's license comment. - Raise OrderError if no package previously defined. - Raise CardinalityError if already set. - """ - self.assert_package_exists() - if not self.package_license_comment_set: - self.package_license_comment_set = True - doc.package.license_comment = text - return True - else: - raise CardinalityError('Package::LicenseComment') - - def set_pkg_cr_text(self, doc, text): - """ - Set the package's license comment. - Raise OrderError if no package previously defined. - Raise CardinalityError if already set. - """ - self.assert_package_exists() - if not self.package_cr_text_set: - self.package_cr_text_set = True - doc.package.cr_text = text - else: - raise CardinalityError('Package::CopyrightText') - - def set_pkg_summary(self, doc, text): - """ - Set the package summary. - Raise CardinalityError if summary already set. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_summary_set: - self.package_summary_set = True - doc.package.summary = text - else: - raise CardinalityError('Package::Summary') - - def set_pkg_desc(self, doc, text): - """ - Set the package's description. - Raise CardinalityError if description already set. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_desc_set: - self.package_desc_set = True - doc.package.description = text - else: - raise CardinalityError('Package::Description') - - def set_pkg_comment(self, doc, text): - """ - Set the package's comment. - Raise CardinalityError if comment already set. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_comment_set: - self.package_comment_set = True - doc.package.comment = text - else: - raise CardinalityError('Package::Comment') - - def set_pkg_ext_ref_category(self, doc, category): - """ - Set the package's external reference locator. - Raise OrderError if no package previously defined. - Raise SPDXValueError if malformed value. - """ - self.assert_package_exists() - category = category.split('_')[-1] - - if category.lower() == 'packagemanager': - category = 'PACKAGE-MANAGER' - - if validations.validate_pkg_ext_ref_category(category): - if (len(doc.package.pkg_ext_refs) and - doc.package.pkg_ext_refs[-1].category is None): - doc.package.pkg_ext_refs[-1].category = category - else: - doc.package.add_pkg_ext_refs( - package.ExternalPackageRef(category=category)) - else: - raise SPDXValueError('ExternalRef::Category') - - def set_pkg_ext_ref_type(self, doc, typ): - """ - Set the package's external reference type. - Raise OrderError if no package previously defined. - Raise SPDXValueError if malformed value. - """ - self.assert_package_exists() - if '#' in typ: - typ = typ.split('#')[-1] - else: - typ = typ.split('/')[-1] - - if validations.validate_pkg_ext_ref_type(typ): - if (len(doc.package.pkg_ext_refs) and - doc.package.pkg_ext_refs[-1].pkg_ext_ref_type is None): - doc.package.pkg_ext_refs[-1].pkg_ext_ref_type = typ - else: - doc.package.add_pkg_ext_refs( - package.ExternalPackageRef(pkg_ext_ref_type=typ)) - else: - raise SPDXValueError('ExternalRef::Type') - - def set_pkg_ext_ref_comment(self, doc, comment): - """ - Set the package's external reference comment. - Raise CardinalityError if comment already set. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not len(doc.package.pkg_ext_refs): - raise OrderError('Package::ExternalRef') - if not self.pkg_ext_comment_set: - self.pkg_ext_comment_set = True - doc.package.pkg_ext_refs[-1].comment = comment - return True - else: - raise CardinalityError('ExternalRef::Comment') - - -class FileBuilder(tagvaluebuilders.FileBuilder): - - def __init__(self): - super(FileBuilder, self).__init__() - - def set_file_chksum(self, doc, chk_sum): - """ - Set the file check sum, if not already set. - chk_sum - A string - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_chksum_set: - self.file_chksum_set = True - self.file(doc).chk_sum = checksum.Algorithm('SHA1', chk_sum) - return True - else: - raise CardinalityError('File::CheckSum') - else: - raise OrderError('File::CheckSum') - - def set_file_license_comment(self, doc, text): - """ - Raise OrderError if no package or file defined. - Raise CardinalityError if more than one per file. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_license_comment_set: - self.file_license_comment_set = True - self.file(doc).license_comment = text - return True - else: - raise CardinalityError('File::LicenseComment') - else: - raise OrderError('File::LicenseComment') - - def set_file_copyright(self, doc, text): - """ - Raise OrderError if no package or file defined. - Raise CardinalityError if more than one. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_copytext_set: - self.file_copytext_set = True - self.file(doc).copyright = text - return True - else: - raise CardinalityError('File::CopyRight') - else: - raise OrderError('File::CopyRight') - - def set_file_comment(self, doc, text): - """ - Raise OrderError if no package or no file defined. - Raise CardinalityError if more than one comment set. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_comment_set: - self.file_comment_set = True - self.file(doc).comment = text - return True - else: - raise CardinalityError('File::Comment') - else: - raise OrderError('File::Comment') - - def set_file_notice(self, doc, text): - """ - Raise OrderError if no package or file defined. - Raise CardinalityError if more than one. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_notice_set: - self.file_notice_set = True - self.file(doc).notice = tagvaluebuilders.str_from_text(text) - return True - else: - raise CardinalityError('File::Notice') - else: - raise OrderError('File::Notice') - - -class SnippetBuilder(tagvaluebuilders.SnippetBuilder): - - def __init__(self): - super(SnippetBuilder, self).__init__() - - def set_snippet_lic_comment(self, doc, lic_comment): - """ - Set the snippet's license comment. - Raise OrderError if no snippet previously defined. - Raise CardinalityError if already set. - """ - self.assert_snippet_exists() - if not self.snippet_lic_comment_set: - self.snippet_lic_comment_set = True - doc.snippet[-1].license_comment = lic_comment - else: - CardinalityError('Snippet::licenseComments') - - def set_snippet_comment(self, doc, comment): - """ - Set general comments about the snippet. - Raise OrderError if no snippet previously defined. - Raise CardinalityError if comment already set. - """ - self.assert_snippet_exists() - if not self.snippet_comment_set: - self.snippet_comment_set = True - doc.snippet[-1].comment = comment - return True - else: - raise CardinalityError('Snippet::comment') - - def set_snippet_copyright(self, doc, copyright): - """ - Set the snippet's copyright text. - Raise OrderError if no snippet previously defined. - Raise CardinalityError if already set. - """ - self.assert_snippet_exists() - if not self.snippet_copyright_set: - self.snippet_copyright_set = True - doc.snippet[-1].copyright = copyright - else: - raise CardinalityError('Snippet::copyrightText') - - -class ReviewBuilder(tagvaluebuilders.ReviewBuilder): - - def __init__(self): - super(ReviewBuilder, self).__init__() - - def add_review_comment(self, doc, comment): - """ - Set the review comment. - Raise CardinalityError if already set. - Raise OrderError if no reviewer defined before. - """ - if len(doc.reviews) != 0: - if not self.review_comment_set: - self.review_comment_set = True - doc.reviews[-1].comment = comment - return True - else: - raise CardinalityError('ReviewComment') - else: - raise OrderError('ReviewComment') - - -class AnnotationBuilder(tagvaluebuilders.AnnotationBuilder): - - def __init__(self): - super(AnnotationBuilder, self).__init__() - - def add_annotation_comment(self, doc, comment): - """ - Set the annotation comment. - Raise CardinalityError if already set. - Raise OrderError if no annotator defined before. - """ - if len(doc.annotations) != 0: - if not self.annotation_comment_set: - self.annotation_comment_set = True - doc.annotations[-1].comment = comment - return True - else: - raise CardinalityError('AnnotationComment') - else: - raise OrderError('AnnotationComment') - - def add_annotation_type(self, doc, annotation_type): - """ - Set the annotation type. - Raise CardinalityError if already set. - Raise OrderError if no annotator defined before. - """ - if len(doc.annotations) != 0: - if not self.annotation_type_set: - if annotation_type.endswith('annotationType_other'): - self.annotation_type_set = True - doc.annotations[-1].annotation_type = 'OTHER' - return True - elif annotation_type.endswith('annotationType_review'): - self.annotation_type_set = True - doc.annotations[-1].annotation_type = 'REVIEW' - return True - else: - raise SPDXValueError('Annotation::AnnotationType') - else: - raise CardinalityError('Annotation::AnnotationType') - else: - raise OrderError('Annotation::AnnotationType') - - -class Builder(DocBuilder, EntityBuilder, CreationInfoBuilder, PackageBuilder, - FileBuilder, SnippetBuilder, ReviewBuilder, ExternalDocumentRefBuilder, - AnnotationBuilder): - - def __init__(self): - super(Builder, self).__init__() - # FIXME: this state does not make sense - self.reset() - - def reset(self): - """ - Reset builder's state for building new documents. - Must be called between usage with different documents. - """ - # FIXME: this state does not make sense - self.reset_creation_info() - self.reset_document() - self.reset_package() - self.reset_file_stat() - self.reset_reviews() - self.reset_annotations() diff --git a/spdx/parsers/tagvalue.py b/spdx/parsers/tagvalue.py deleted file mode 100644 index bfed57d3e..000000000 --- a/spdx/parsers/tagvalue.py +++ /dev/null @@ -1,1736 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import re - -from ply import yacc -import six - -from spdx import config -from spdx import utils -from spdx.parsers.builderexceptions import CardinalityError -from spdx.parsers.builderexceptions import OrderError -from spdx.parsers.builderexceptions import SPDXValueError -from spdx.parsers.lexers.tagvalue import Lexer -from spdx import document - - -ERROR_MESSAGES = { - 'TOOL_VALUE': 'Invalid tool value {0} at line: {1}', - 'ORG_VALUE': 'Invalid organization value {0} at line: {1}', - 'PERSON_VALUE': 'Invalid person value {0} at line: {1}', - 'CREATED_VALUE_TYPE': 'Created value must be date in ISO 8601 format, line: {0}', - 'MORE_THAN_ONE': 'Only one {0} allowed, extra at line: {1}', - 'CREATOR_COMMENT_VALUE_TYPE': 'CreatorComment value must be free form text between tags, line:{0}', - 'DOC_LICENSE_VALUE': 'Invalid DataLicense value \'{0}\', line:{1} must be CC0-1.0', - 'DOC_LICENSE_VALUE_TYPE': 'DataLicense must be CC0-1.0, line: {0}', - 'DOC_VERSION_VALUE': 'Invalid SPDXVersion \'{0}\' must be SPDX-M.N where M and N are numbers. Line: {1}', - 'DOC_VERSION_VALUE_TYPE': 'Invalid SPDXVersion value, must be SPDX-M.N where M and N are numbers. Line: {0}', - 'DOC_NAME_VALUE': 'DocumentName must be single line of text, line: {0}', - 'DOC_SPDX_ID_VALUE': 'Invalid SPDXID value, SPDXID must be SPDXRef-DOCUMENT, line: {0}', - 'EXT_DOC_REF_VALUE': 'ExternalDocumentRef must contain External Document ID, SPDX Document URI and Checksum' - 'in the standard format, line:{0}.', - 'DOC_COMMENT_VALUE_TYPE': 'DocumentComment value must be free form text between tags, line:{0}', - 'DOC_NAMESPACE_VALUE': 'Invalid DocumentNamespace value {0}, must contain a scheme (e.g. "https:") ' - 'and should not contain the "#" delimiter, line:{1}', - 'DOC_NAMESPACE_VALUE_TYPE': 'Invalid DocumentNamespace value, must contain a scheme (e.g. "https:") ' - 'and should not contain the "#" delimiter, line: {0}', - 'REVIEWER_VALUE_TYPE': 'Invalid Reviewer value must be a Person, Organization or Tool. Line: {0}', - 'CREATOR_VALUE_TYPE': 'Invalid Reviewer value must be a Person, Organization or Tool. Line: {0}', - 'REVIEW_DATE_VALUE_TYPE': 'ReviewDate value must be date in ISO 8601 format, line: {0}', - 'REVIEW_COMMENT_VALUE_TYPE': 'ReviewComment value must be free form text between tags, line:{0}', - 'ANNOTATOR_VALUE_TYPE': 'Invalid Annotator value must be a Person, Organization or Tool. Line: {0}', - 'ANNOTATION_DATE_VALUE_TYPE': 'AnnotationDate value must be date in ISO 8601 format, line: {0}', - 'ANNOTATION_COMMENT_VALUE_TYPE': 'AnnotationComment value must be free form text between tags, line:{0}', - 'ANNOTATION_TYPE_VALUE': 'AnnotationType must be "REVIEW" or "OTHER". Line: {0}', - 'ANNOTATION_SPDX_ID_VALUE': 'SPDXREF must be ["DocumentRef-"[idstring]":"]SPDXID where' - '["DocumentRef-"[idstring]":"] is an optional reference to an external SPDX document and' - 'SPDXID is a unique string containing letters, numbers, ".","-".', - 'A_BEFORE_B': '{0} Can not appear before {1}, line: {2}', - 'PACKAGE_NAME_VALUE': 'PackageName must be single line of text, line: {0}', - 'PKG_SPDX_ID_VALUE': 'SPDXID must be "SPDXRef-[idstring]" where [idstring] is a unique string containing ' - 'letters, numbers, ".", "-".', - 'PKG_VERSION_VALUE': 'PackageVersion must be single line of text, line: {0}', - 'PKG_FILE_NAME_VALUE': 'PackageFileName must be single line of text, line: {0}', - 'PKG_SUPPL_VALUE': 'PackageSupplier must be Organization, Person or NOASSERTION, line: {0}', - 'PKG_ORIG_VALUE': 'PackageOriginator must be Organization, Person or NOASSERTION, line: {0}', - 'PKG_DOWN_VALUE': 'PackageDownloadLocation must be a url or NONE or NOASSERTION, line: {0}', - 'PKG_FILES_ANALYZED_VALUE': 'FilesAnalyzed must be a boolean value, line: {0}', - 'PKG_HOME_VALUE': 'PackageHomePage must be a url or NONE or NOASSERTION, line: {0}', - 'PKG_SRC_INFO_VALUE': 'PackageSourceInfo must be free form text, line: {0}', - 'PKG_CHKSUM_VALUE': 'PackageChecksum must be a single line of text, line: {0}', - 'PKG_LICS_CONC_VALUE': 'PackageLicenseConcluded must be NOASSERTION, NONE, license identifier or license list, line: {0}', - 'PKG_LIC_FFILE_VALUE': 'PackageLicenseInfoFromFiles must be, line: {0}', - 'PKG_LICS_DECL_VALUE': 'PackageLicenseDeclared must be NOASSERTION, NONE, license identifier or license list, line: {0}', - 'PKG_LICS_COMMENT_VALUE': 'PackageLicenseComments must be free form text, line: {0}', - 'PKG_SUM_VALUE': 'PackageSummary must be free form text, line: {0}', - 'PKG_DESC_VALUE': 'PackageDescription must be free form text, line: {0}', - 'PKG_COMMENT_VALUE': 'PackageComment must be free form text, line: {0}', - 'PKG_EXT_REF_VALUE': 'ExternalRef must contain category, type, and locator in the standard format, line:{0}.', - 'PKG_EXT_REF_COMMENT_VALUE' : 'ExternalRefComment must be free form text, line:{0}', - 'FILE_NAME_VALUE': 'FileName must be a single line of text, line: {0}', - 'FILE_COMMENT_VALUE': 'FileComment must be free form text, line:{0}', - 'FILE_TYPE_VALUE': 'FileType must be one of OTHER, BINARY, SOURCE or ARCHIVE, line: {0}', - 'FILE_SPDX_ID_VALUE': 'SPDXID must be "SPDXRef-[idstring]" where [idstring] is a unique string containing ' - 'letters, numbers, ".", "-".', - 'FILE_CHKSUM_VALUE': 'FileChecksum must be a single line of text starting with \'SHA1:\', line:{0}', - 'FILE_LICS_CONC_VALUE': 'LicenseConcluded must be NOASSERTION, NONE, license identifier or license list, line:{0}', - 'FILE_LICS_INFO_VALUE': 'LicenseInfoInFile must be NOASSERTION, NONE or license identifier, line: {0}', - 'FILE_LICS_COMMENT_VALUE': 'LicenseComments must be free form lext, line: {0}', - 'FILE_CR_TEXT_VALUE': 'FileCopyrightText must be one of NOASSERTION, NONE or free form text, line: {0}', - 'FILE_NOTICE_VALUE': 'FileNotice must be free form text, line: {0}', - 'FILE_CONTRIB_VALUE': 'FileContributor must be a single line, line: {0}', - 'FILE_DEP_VALUE': 'FileDependency must be a single line, line: {0}', - 'ART_PRJ_NAME_VALUE' : 'ArtifactOfProjectName must be a single line, line: {0}', - 'FILE_ART_OPT_ORDER' : 'ArtificatOfProjectHomePage and ArtificatOfProjectURI must immediatly follow ArtifactOfProjectName, line: {0}', - 'ART_PRJ_HOME_VALUE' : 'ArtificatOfProjectHomePage must be a URL or UNKNOWN, line: {0}', - 'ART_PRJ_URI_VALUE' : 'ArtificatOfProjectURI must be a URI or UNKNOWN, line: {0}', - 'UNKNOWN_TAG' : 'Found unknown tag : {0} at line: {1}', - 'LICS_ID_VALUE' : 'LicenseID must start with \'LicenseRef-\', line: {0}', - 'LICS_TEXT_VALUE' : 'ExtractedText must be free form text, line: {0}', - 'LICS_NAME_VALE' : 'LicenseName must be single line of text or NOASSERTION, line: {0}', - 'LICS_COMMENT_VALUE' : 'LicenseComment must be free form text, line: {0}', - 'LICS_CRS_REF_VALUE' : 'LicenseCrossReference must be uri as single line of text, line: {0}', - 'PKG_CPY_TEXT_VALUE' : 'Package copyright text must be free form text, line: {0}', - 'SNIP_SPDX_ID_VALUE' : 'SPDXID must be "SPDXRef-[idstring]" where [idstring] is a unique string ' - 'containing letters, numbers, ".", "-".', - 'SNIPPET_NAME_VALUE' : 'SnippetName must be a single line of text, line: {0}', - 'SNIP_COMMENT_VALUE' : 'SnippetComment must be free form text, line: {0}', - 'SNIP_COPYRIGHT_VALUE' : 'SnippetCopyrightText must be one of NOASSERTION, NONE or free form text, line: {0}', - 'SNIP_LICS_COMMENT_VALUE' : 'SnippetLicenseComments must be free form text, line: {0}', - 'SNIP_FILE_SPDXID_VALUE' : 'SnippetFromFileSPDXID must be ["DocumentRef-"[idstring]":"] SPDXID ' - 'where DocumentRef-[idstring]: is an optional reference to an external' - 'SPDX Document and SPDXID is a string containing letters, ' - 'numbers, ".", "-".', - 'SNIP_LICS_CONC_VALUE': 'SnippetLicenseConcluded must be NOASSERTION, NONE, license identifier ' - 'or license list, line:{0}', - 'SNIP_LICS_INFO_VALUE': 'LicenseInfoInSnippet must be NOASSERTION, NONE or license identifier, line: {0}', -} - - -class Parser(object): - - def __init__(self, builder, logger): - self.tokens = Lexer.tokens - self.builder = builder - self.logger = logger - self.error = False - self.license_list_parser = utils.LicenseListParser() - self.license_list_parser.build(write_tables=0, debug=0) - - def p_start_1(self, p): - 'start : start attrib ' - pass - - def p_start_2(self, p): - 'start : attrib ' - pass - - def p_attrib(self, p): - """attrib : spdx_version - | spdx_id - | data_lics - | doc_name - | ext_doc_ref - | doc_comment - | doc_namespace - | creator - | created - | creator_comment - | locs_list_ver - | reviewer - | review_date - | review_comment - | annotator - | annotation_date - | annotation_comment - | annotation_type - | annotation_spdx_id - | package_name - | package_version - | pkg_down_location - | pkg_files_analyzed - | pkg_home - | pkg_summary - | pkg_src_info - | pkg_file_name - | pkg_supplier - | pkg_orig - | pkg_chksum - | pkg_verif - | pkg_desc - | pkg_comment - | pkg_lic_decl - | pkg_lic_conc - | pkg_lic_ff - | pkg_lic_comment - | pkg_cr_text - | pkg_ext_ref - | pkg_ext_ref_comment - | file_name - | file_type - | file_chksum - | file_conc - | file_lics_info - | file_cr_text - | file_lics_comment - | file_notice - | file_comment - | file_contrib - | file_dep - | file_artifact - | snip_spdx_id - | snip_name - | snip_comment - | snip_cr_text - | snip_lic_comment - | snip_file_spdx_id - | snip_lics_conc - | snip_lics_info - | extr_lic_id - | extr_lic_text - | extr_lic_name - | lic_xref - | lic_comment - | unknown_tag - """ - pass - - def more_than_one_error(self, tag, line): - self.error = True - msg = ERROR_MESSAGES['MORE_THAN_ONE'].format(tag, line) - self.logger.log(msg) - - def order_error(self, first_tag, second_tag, line): - """Reports an OrderError. Error message will state that - first_tag came before second_tag. - """ - self.error = True - msg = ERROR_MESSAGES['A_BEFORE_B'].format(first_tag, second_tag, line) - self.logger.log(msg) - - def p_lic_xref_1(self, p): - """lic_xref : LICS_CRS_REF LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.add_lic_xref(self.document, value) - except OrderError: - self.order_error('LicenseCrossReference', 'LicenseName', p.lineno(1)) - - def p_lic_xref_2(self, p): - """lic_xref : LICS_CRS_REF error""" - self.error = True - msg = ERROR_MESSAGES['LICS_CRS_REF_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_lic_comment_1(self, p): - """lic_comment : LICS_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_lic_comment(self.document, value) - except OrderError: - self.order_error('LicenseComment', 'LicenseID', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('LicenseComment', p.lineno(1)) - - def p_lic_comment_2(self, p): - """lic_comment : LICS_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['LICS_COMMENT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_extr_lic_name_1(self, p): - """extr_lic_name : LICS_NAME extr_lic_name_value""" - try: - self.builder.set_lic_name(self.document, p[2]) - except OrderError: - self.order_error('LicenseName', 'LicenseID', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('LicenseName', p.lineno(1)) - - def p_extr_lic_name_2(self, p): - """extr_lic_name : LICS_NAME error""" - self.error = True - msg = ERROR_MESSAGES['LICS_NAME_VALE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_extr_lic_name_value_1(self, p): - """extr_lic_name_value : LINE""" - if six.PY2: - p[0] = p[1].decode(encoding='utf-8') - else: - p[0] = p[1] - - def p_extr_lic_name_value_2(self, p): - """extr_lic_name_value : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_extr_lic_text_1(self, p): - """extr_lic_text : LICS_TEXT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_lic_text(self.document, value) - except OrderError: - self.order_error('ExtractedText', 'LicenseID', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('ExtractedText', p.lineno(1)) - - def p_extr_lic_text_2(self, p): - """extr_lic_text : LICS_TEXT error""" - self.error = True - msg = ERROR_MESSAGES['LICS_TEXT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_extr_lic_id_1(self, p): - """extr_lic_id : LICS_ID LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_lic_id(self.document, value) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['LICS_ID_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_extr_lic_id_2(self, p): - """extr_lic_id : LICS_ID error""" - self.error = True - msg = ERROR_MESSAGES['LICS_ID_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_uknown_tag(self, p): - """unknown_tag : UNKNOWN_TAG LINE""" - self.error = True - msg = ERROR_MESSAGES['UNKNOWN_TAG'].format(p[1], p.lineno(1)) - self.logger.log(msg) - - def p_file_artifact_1(self, p): - """file_artifact : prj_name_art file_art_rest - | prj_name_art - """ - pass - - def p_file_artificat_2(self, p): - """file_artifact : prj_name_art error""" - self.error = True - msg = ERROR_MESSAGES['FILE_ART_OPT_ORDER'].format(p.lineno(2)) - self.logger.log(msg) - - def p_file_art_rest(self, p): - """file_art_rest : prj_home_art prj_uri_art - | prj_uri_art prj_home_art - | prj_home_art - | prj_uri_art - """ - pass - - def p_prj_uri_art_1(self, p): - """prj_uri_art : ART_PRJ_URI UN_KNOWN""" - try: - self.builder.set_file_atrificat_of_project(self.document, - 'uri', utils.UnKnown()) - except OrderError: - self.order_error('ArtificatOfProjectURI', 'FileName', p.lineno(1)) - - def p_prj_uri_art_2(self, p): - """prj_uri_art : ART_PRJ_URI LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_file_atrificat_of_project(self.document, 'uri', value) - except OrderError: - self.order_error('ArtificatOfProjectURI', 'FileName', p.lineno(1)) - - def p_prj_uri_art_3(self, p): - """prj_uri_art : ART_PRJ_URI error""" - self.error = True - msg = ERROR_MESSAGES['ART_PRJ_URI_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_prj_home_art_1(self, p): - """prj_home_art : ART_PRJ_HOME LINE""" - try: - self.builder.set_file_atrificat_of_project(self.document, 'home', p[2]) - except OrderError: - self.order_error('ArtificatOfProjectHomePage', 'FileName', p.lineno(1)) - - def p_prj_home_art_2(self, p): - """prj_home_art : ART_PRJ_HOME UN_KNOWN""" - try: - self.builder.set_file_atrificat_of_project(self.document, - 'home', utils.UnKnown()) - except OrderError: - self.order_error('ArtifactOfProjectName', 'FileName', p.lineno(1)) - - def p_prj_home_art_3(self, p): - """prj_home_art : ART_PRJ_HOME error""" - self.error = True - msg = ERROR_MESSAGES['ART_PRJ_HOME_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_prj_name_art_1(self, p): - """prj_name_art : ART_PRJ_NAME LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_file_atrificat_of_project(self.document, 'name', value) - except OrderError: - self.order_error('ArtifactOfProjectName', 'FileName', p.lineno(1)) - - def p_prj_name_art_2(self, p): - """prj_name_art : ART_PRJ_NAME error""" - self.error = True - msg = ERROR_MESSAGES['ART_PRJ_NAME_VALUE'].format(p.lineno()) - self.logger.log(msg) - - def p_file_dep_1(self, p): - """file_dep : FILE_DEP LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.add_file_dep(self.document, value) - except OrderError: - self.order_error('FileDependency', 'FileName', p.lineno(1)) - - def p_file_dep_2(self, p): - """file_dep : FILE_DEP error""" - self.error = True - msg = ERROR_MESSAGES['FILE_DEP_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_contrib_1(self, p): - """file_contrib : FILE_CONTRIB LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.add_file_contribution(self.document, value) - except OrderError: - self.order_error('FileContributor', 'FileName', p.lineno(1)) - - def p_file_contrib_2(self, p): - """file_contrib : FILE_CONTRIB error""" - self.error = True - msg = ERROR_MESSAGES['FILE_CONTRIB_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_notice_1(self, p): - """file_notice : FILE_NOTICE TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_file_notice(self.document, value) - except OrderError: - self.order_error('FileNotice', 'FileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('FileNotice', p.lineno(1)) - - def p_file_notice_2(self, p): - """file_notice : FILE_NOTICE error""" - self.error = True - msg = ERROR_MESSAGES['FILE_NOTICE_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_cr_text_1(self, p): - """file_cr_text : FILE_CR_TEXT file_cr_value""" - try: - self.builder.set_file_copyright(self.document, p[2]) - except OrderError: - self.order_error('FileCopyrightText', 'FileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('FileCopyrightText', p.lineno(1)) - - def p_file_cr_text_2(self, p): - """file_cr_text : FILE_CR_TEXT error""" - self.error = True - msg = ERROR_MESSAGES['FILE_CR_TEXT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_cr_value_1(self, p): - """file_cr_value : TEXT""" - if six.PY2: - p[0] = p[1].decode(encoding='utf-8') - else: - p[0] = p[1] - - def p_file_cr_value_2(self, p): - """file_cr_value : NONE""" - p[0] = utils.SPDXNone() - - def p_file_cr_value_3(self, p): - """file_cr_value : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_file_lics_comment_1(self, p): - """file_lics_comment : FILE_LICS_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_file_license_comment(self.document, value) - except OrderError: - self.order_error('LicenseComments', 'FileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('LicenseComments', p.lineno(1)) - - def p_file_lics_comment_2(self, p): - """file_lics_comment : FILE_LICS_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['FILE_LICS_COMMENT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_lics_info_1(self, p): - """file_lics_info : FILE_LICS_INFO file_lic_info_value""" - try: - self.builder.set_file_license_in_file(self.document, p[2]) - except OrderError: - self.order_error('LicenseInfoInFile', 'FileName', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['FILE_LICS_INFO_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_lics_info_2(self, p): - """file_lics_info : FILE_LICS_INFO error""" - self.error = True - msg = ERROR_MESSAGES['FILE_LICS_INFO_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_lic_info_value_1(self, p): - """file_lic_info_value : NONE""" - p[0] = utils.SPDXNone() - - def p_file_lic_info_value_2(self, p): - """file_lic_info_value : NO_ASSERT""" - p[0] = utils.NoAssert() - - # License Identifier - def p_file_lic_info_value_3(self, p): - """file_lic_info_value : LINE""" - if six.PY2: - value = p[1].decode(encoding='utf-8') - else: - value = p[1] - p[0] = document.License.from_identifier(value) - - def p_conc_license_1(self, p): - """conc_license : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_conc_license_2(self, p): - """conc_license : NONE""" - p[0] = utils.SPDXNone() - - def p_conc_license_3(self, p): - """conc_license : LINE""" - if six.PY2: - value = p[1].decode(encoding='utf-8') - else: - value = p[1] - ref_re = re.compile('LicenseRef-.+', re.UNICODE) - if (p[1] in config.LICENSE_MAP.keys()) or (ref_re.match(p[1]) is not None): - p[0] = document.License.from_identifier(value) - else: - p[0] = self.license_list_parser.parse(value) - - def p_file_name_1(self, p): - """file_name : FILE_NAME LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_file_name(self.document, value) - except OrderError: - self.order_error('FileName', 'PackageName', p.lineno(1)) - - def p_file_name_2(self, p): - """file_name : FILE_NAME error""" - self.error = True - msg = ERROR_MESSAGES['FILE_NAME_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_spdx_id(self, p): - """spdx_id : SPDX_ID LINE""" - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - if not self.builder.doc_spdx_id_set: - self.builder.set_doc_spdx_id(self.document, value) - elif not self.builder.package_spdx_id_set: - self.builder.set_pkg_spdx_id(self.document, value) - else: - self.builder.set_file_spdx_id(self.document, value) - - def p_file_comment_1(self, p): - """file_comment : FILE_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_file_comment(self.document, value) - except OrderError: - self.order_error('FileComment', 'FileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('FileComment', p.lineno(1)) - - def p_file_comment_2(self, p): - """file_comment : FILE_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['FILE_COMMENT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_type_1(self, p): - """file_type : FILE_TYPE file_type_value""" - try: - self.builder.set_file_type(self.document, p[2]) - except OrderError: - self.order_error('FileType', 'FileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('FileType', p.lineno(1)) - - def p_file_type_2(self, p): - """file_type : FILE_TYPE error""" - self.error = True - msg = ERROR_MESSAGES['FILE_TYPE_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_chksum_1(self, p): - """file_chksum : FILE_CHKSUM CHKSUM""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_file_chksum(self.document, value) - except OrderError: - self.order_error('FileChecksum', 'FileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('FileChecksum', p.lineno(1)) - - def p_file_chksum_2(self, p): - """file_chksum : FILE_CHKSUM error""" - self.error = True - msg = ERROR_MESSAGES['FILE_CHKSUM_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_conc_1(self, p): - """file_conc : FILE_LICS_CONC conc_license""" - try: - self.builder.set_concluded_license(self.document, p[2]) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['FILE_LICS_CONC_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - except OrderError: - self.order_error('LicenseConcluded', 'FileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('LicenseConcluded', p.lineno(1)) - - def p_file_conc_2(self, p): - """file_conc : FILE_LICS_CONC error""" - self.error = True - msg = ERROR_MESSAGES['FILE_LICS_CONC_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_file_type_value(self, p): - """file_type_value : OTHER - | SOURCE - | ARCHIVE - | BINARY - """ - if six.PY2: - p[0] = p[1].decode(encoding='utf-8') - else: - p[0] = p[1] - - def p_pkg_desc_1(self, p): - """pkg_desc : PKG_DESC TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_desc(self.document, value) - except CardinalityError: - self.more_than_one_error('PackageDescription', p.lineno(1)) - except OrderError: - self.order_error('PackageDescription', 'PackageFileName', p.lineno(1)) - - def p_pkg_desc_2(self, p): - """pkg_desc : PKG_DESC error""" - self.error = True - msg = ERROR_MESSAGES['PKG_DESC_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_comment_1(self, p): - """pkg_comment : PKG_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_comment(self.document, value) - except CardinalityError: - self.more_than_one_error('PackageComment', p.lineno(1)) - except OrderError: - self.order_error('PackageComment', 'PackageFileName', - p.lineno(1)) - - def p_pkg_comment_2(self, p): - """pkg_comment : PKG_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['PKG_COMMENT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_summary_1(self, p): - """pkg_summary : PKG_SUM TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_summary(self.document, value) - except OrderError: - self.order_error('PackageSummary', 'PackageFileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageSummary', p.lineno(1)) - - def p_pkg_summary_2(self, p): - """pkg_summary : PKG_SUM error""" - self.error = True - msg = ERROR_MESSAGES['PKG_SUM_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_cr_text_1(self, p): - """pkg_cr_text : PKG_CPY_TEXT pkg_cr_text_value""" - try: - self.builder.set_pkg_cr_text(self.document, p[2]) - except OrderError: - self.order_error('PackageCopyrightText', 'PackageFileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageCopyrightText', p.lineno(1)) - - def p_pkg_cr_text_2(self, p): - """pkg_cr_text : PKG_CPY_TEXT error""" - self.error = True - msg = ERROR_MESSAGES['PKG_CPY_TEXT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_ext_refs_1(self, p): - """pkg_ext_ref : PKG_EXT_REF LINE""" - try: - if six.PY2: - pkg_ext_info = p[2].decode(encoding='utf-8') - else: - pkg_ext_info = p[2] - if len(pkg_ext_info.split()) != 3: - raise SPDXValueError - else: - pkg_ext_category, pkg_ext_type, pkg_ext_locator = pkg_ext_info.split() - self.builder.add_pkg_ext_refs(self.document, pkg_ext_category, - pkg_ext_type, pkg_ext_locator) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['PKG_EXT_REF_VALUE'].format(p.lineno(2)) - self.logger.log(msg) - - def p_pkg_ext_refs_2(self, p): - """pkg_ext_ref : PKG_EXT_REF error""" - self.error = True - msg = ERROR_MESSAGES['PKG_EXT_REF_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_ext_ref_comment_1(self, p): - """pkg_ext_ref_comment : PKG_EXT_REF_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.add_pkg_ext_ref_comment(self.document, value) - except CardinalityError: - self.more_than_one_error('ExternalRefComment', p.lineno(1)) - - def p_pkg_ext_ref_comment_2(self, p): - """pkg_ext_ref_comment : PKG_EXT_REF_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['PKG_EXT_REF_COMMENT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_cr_text_value_1(self, p): - """pkg_cr_text_value : TEXT""" - if six.PY2: - p[0] = p[1].decode(encoding='utf-8') - else: - p[0] = p[1] - - def p_pkg_cr_text_value_2(self, p): - """pkg_cr_text_value : NONE""" - p[0] = utils.SPDXNone() - - def p_pkg_cr_text_value_3(self, p): - """pkg_cr_text_value : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_pkg_lic_comment_1(self, p): - """pkg_lic_comment : PKG_LICS_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_license_comment(self.document, value) - except OrderError: - self.order_error('PackageLicenseComments', 'PackageFileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageLicenseComments', p.lineno(1)) - - def p_pkg_lic_comment_2(self, p): - """pkg_lic_comment : PKG_LICS_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['PKG_LICS_COMMENT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_lic_decl_1(self, p): - """pkg_lic_decl : PKG_LICS_DECL conc_license""" - try: - self.builder.set_pkg_license_declared(self.document, p[2]) - except OrderError: - self.order_error('PackageLicenseDeclared', 'PackageName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageLicenseDeclared', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['PKG_LICS_DECL_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_lic_decl_2(self, p): - """pkg_lic_decl : PKG_LICS_DECL error""" - self.error = True - msg = ERROR_MESSAGES['PKG_LICS_DECL_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_lic_ff_1(self, p): - """pkg_lic_ff : PKG_LICS_FFILE pkg_lic_ff_value""" - try: - self.builder.set_pkg_license_from_file(self.document, p[2]) - except OrderError: - self.order_error('PackageLicenseInfoFromFiles', 'PackageName', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['PKG_LIC_FFILE_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_lic_ff_value_1(self, p): - """pkg_lic_ff_value : NONE""" - p[0] = utils.SPDXNone() - - def p_pkg_lic_ff_value_2(self, p): - """pkg_lic_ff_value : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_pkg_lic_ff_value_3(self, p): - """pkg_lic_ff_value : LINE""" - if six.PY2: - value = p[1].decode(encoding='utf-8') - else: - value = p[1] - p[0] = document.License.from_identifier(value) - - def p_pkg_lic_ff_2(self, p): - """pkg_lic_ff : PKG_LICS_FFILE error""" - self.error = True - msg = ERROR_MESSAGES['PKG_LIC_FFILE_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_lic_conc_1(self, p): - """pkg_lic_conc : PKG_LICS_CONC conc_license""" - try: - self.builder.set_pkg_licenses_concluded(self.document, p[2]) - except CardinalityError: - self.more_than_one_error('PackageLicenseConcluded', p.lineno(1)) - except OrderError: - self.order_error('PackageLicenseConcluded', 'PackageFileName', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['PKG_LICS_CONC_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_lic_conc_2(self, p): - """pkg_lic_conc : PKG_LICS_CONC error""" - self.error = True - msg = ERROR_MESSAGES['PKG_LICS_CONC_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_src_info_1(self, p): - """pkg_src_info : PKG_SRC_INFO TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_source_info(self.document, value) - except CardinalityError: - self.more_than_one_error('PackageSourceInfo', p.lineno(1)) - except OrderError: - self.order_error('PackageSourceInfo', 'PackageFileName', p.lineno(1)) - - def p_pkg_src_info_2(self, p): - """pkg_src_info : PKG_SRC_INFO error""" - self.error = True - msg = ERROR_MESSAGES['PKG_SRC_INFO_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_chksum_1(self, p): - """pkg_chksum : PKG_CHKSUM CHKSUM""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_chk_sum(self.document, value) - except OrderError: - self.order_error('PackageChecksum', 'PackageFileName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageChecksum', p.lineno(1)) - - def p_pkg_chksum_2(self, p): - """pkg_chksum : PKG_CHKSUM error""" - self.error = True - msg = ERROR_MESSAGES['PKG_CHKSUM_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_verif_1(self, p): - """pkg_verif : PKG_VERF_CODE LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_verif_code(self.document, value) - except OrderError: - self.order_error('PackageVerificationCode', 'PackageName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageVerificationCode', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['PKG_VERF_CODE_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_verif_2(self, p): - """pkg_verif : PKG_VERF_CODE error""" - self.error = True - msg = ERROR_MESSAGES['PKG_VERF_CODE_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_home_1(self, p): - """pkg_home : PKG_HOME pkg_home_value""" - try: - self.builder.set_pkg_home(self.document, p[2]) - except OrderError: - self.order_error('PackageHomePage', 'PackageName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageHomePage', p.lineno(1)) - - def p_pkg_home_2(self, p): - """pkg_home : PKG_HOME error""" - self.error = True - msg = ERROR_MESSAGES['PKG_HOME_VALUE'] - self.logger.log(msg) - - def p_pkg_home_value_1(self, p): - """pkg_home_value : LINE""" - if six.PY2: - p[0] = p[1].decode(encoding='utf-8') - else: - p[0] = p[1] - - def p_pkg_home_value_2(self, p): - """pkg_home_value : NONE""" - p[0] = utils.SPDXNone() - - def p_pkg_home_value_3(self, p): - """pkg_home_value : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_pkg_down_location_1(self, p): - """pkg_down_location : PKG_DOWN pkg_down_value""" - try: - self.builder.set_pkg_down_location(self.document, p[2]) - except OrderError: - self.order_error('PackageDownloadLocation', 'PackageName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageDownloadLocation', p.lineno(1)) - - def p_pkg_down_location_2(self, p): - """pkg_down_location : PKG_DOWN error""" - self.error = True - msg = ERROR_MESSAGES['PKG_DOWN_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_files_analyzed_1(self, p): - """pkg_files_analyzed : PKG_FILES_ANALYZED LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_files_analyzed(self.document, value) - except CardinalityError: - self.more_than_one_error('FilesAnalyzed', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['PKG_FILES_ANALYZED_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_files_analyzed_2(self, p): - """pkg_files_analyzed : PKG_FILES_ANALYZED error""" - self.error = True - msg = ERROR_MESSAGES['PKG_FILES_ANALYZED_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_down_value_1(self, p): - """pkg_down_value : LINE """ - if six.PY2: - p[0] = p[1].decode(encoding='utf-8') - else: - p[0] = p[1] - - def p_pkg_down_value_2(self, p): - """pkg_down_value : NONE""" - p[0] = utils.SPDXNone() - - def p_pkg_down_value_3(self, p): - """pkg_down_value : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_pkg_orig_1(self, p): - """pkg_orig : PKG_ORIG pkg_supplier_values""" - try: - self.builder.set_pkg_originator(self.document, p[2]) - except OrderError: - self.order_error('PackageOriginator', 'PackageName', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['PKG_ORIG_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - except CardinalityError: - self.more_than_one_error('PackageOriginator', p.lineno(1)) - - def p_pkg_orig_2(self, p): - """pkg_orig : PKG_ORIG error""" - self.error = True - msg = ERROR_MESSAGES['PKG_ORIG_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_supplier_1(self, p): - """pkg_supplier : PKG_SUPPL pkg_supplier_values""" - try: - self.builder.set_pkg_supplier(self.document, p[2]) - except OrderError: - self.order_error('PackageSupplier', 'PackageName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageSupplier', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['PKG_SUPPL_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_supplier_2(self, p): - """pkg_supplier : PKG_SUPPL error""" - self.error = True - msg = ERROR_MESSAGES['PKG_SUPPL_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_pkg_supplier_values_1(self, p): - """pkg_supplier_values : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_pkg_supplier_values_2(self, p): - """pkg_supplier_values : entity""" - p[0] = p[1] - - def p_pkg_file_name(self, p): - """pkg_file_name : PKG_FILE_NAME LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_file_name(self.document, value) - except OrderError: - self.order_error('PackageFileName', 'PackageName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageFileName', p.lineno(1)) - - def p_pkg_file_name_1(self, p): - """pkg_file_name : PKG_FILE_NAME error""" - self.error = True - msg = ERROR_MESSAGES['PKG_FILE_NAME_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_package_version_1(self, p): - """package_version : PKG_VERSION LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_pkg_vers(self.document, value) - except OrderError: - self.order_error('PackageVersion', 'PackageName', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('PackageVersion', p.lineno(1)) - - def p_package_version_2(self, p): - """package_version : PKG_VERSION error""" - self.error = True - msg = ERROR_MESSAGES['PKG_VERSION_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_package_name(self, p): - """package_name : PKG_NAME LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.create_package(self.document, value) - except CardinalityError: - self.more_than_one_error('PackageName', p.lineno(1)) - - def p_package_name_1(self, p): - """package_name : PKG_NAME error""" - self.error = True - msg = ERROR_MESSAGES['PACKAGE_NAME_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snip_spdx_id(self, p): - """snip_spdx_id : SNIPPET_SPDX_ID LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.create_snippet(self.document, value) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['SNIP_SPDX_ID_VALUE'].format(p.lineno(2)) - self.logger.log(msg) - - def p_snip_spdx_id_1(self, p): - """snip_spdx_id : SNIPPET_SPDX_ID error""" - self.error = True - msg = ERROR_MESSAGES['SNIP_SPDX_ID_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snippet_name(self, p): - """snip_name : SNIPPET_NAME LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_snippet_name(self.document, value) - except OrderError: - self.order_error('SnippetName', 'SnippetSPDXID', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('SnippetName', p.lineno(1)) - - def p_snippet_name_1(self, p): - """snip_name : SNIPPET_NAME error""" - self.error = True - msg = ERROR_MESSAGES['SNIPPET_NAME_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snippet_comment(self, p): - """snip_comment : SNIPPET_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_snippet_comment(self.document, value) - except OrderError: - self.order_error('SnippetComment', 'SnippetSPDXID', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['SNIP_COMMENT_VALUE'].format(p.lineno(2)) - self.logger.log(msg) - except CardinalityError: - self.more_than_one_error('SnippetComment', p.lineno(1)) - - def p_snippet_comment_1(self, p): - """snip_comment : SNIPPET_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['SNIP_COMMENT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snippet_cr_text(self, p): - """snip_cr_text : SNIPPET_CR_TEXT snip_cr_value""" - try: - self.builder.set_snippet_copyright(self.document, p[2]) - except OrderError: - self.order_error('SnippetCopyrightText', 'SnippetSPDXID', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['SNIP_COPYRIGHT_VALUE'].format(p.lineno(2)) - self.logger.log(msg) - except CardinalityError: - self.more_than_one_error('SnippetCopyrightText', p.lineno(1)) - - def p_snippet_cr_text_1(self, p): - """snip_cr_text : SNIPPET_CR_TEXT error""" - self.error = True - msg = ERROR_MESSAGES['SNIP_COPYRIGHT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snippet_cr_value_1(self, p): - """snip_cr_value : TEXT""" - if six.PY2: - p[0] = p[1].decode(encoding='utf-8') - else: - p[0] = p[1] - - def p_snippet_cr_value_2(self, p): - """snip_cr_value : NONE""" - p[0] = utils.SPDXNone() - - def p_snippet_cr_value_3(self, p): - """snip_cr_value : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_snippet_lic_comment(self, p): - """snip_lic_comment : SNIPPET_LICS_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_snippet_lic_comment(self.document, value) - except OrderError: - self.order_error('SnippetLicenseComments', 'SnippetSPDXID', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['SNIP_LICS_COMMENT_VALUE'].format(p.lineno(2)) - self.logger.log(msg) - except CardinalityError: - self.more_than_one_error('SnippetLicenseComments', p.lineno(1)) - - def p_snippet_lic_comment_1(self, p): - """snip_lic_comment : SNIPPET_LICS_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['SNIP_LICS_COMMENT_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snip_from_file_spdxid(self, p): - """snip_file_spdx_id : SNIPPET_FILE_SPDXID LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_snip_from_file_spdxid(self.document, value) - except OrderError: - self.order_error('SnippetFromFileSPDXID', 'SnippetSPDXID', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['SNIP_FILE_SPDXID_VALUE'].format(p.lineno(2)) - self.logger.log(msg) - except CardinalityError: - self.more_than_one_error('SnippetFromFileSPDXID', p.lineno(1)) - - def p_snip_from_file_spdxid_1(self, p): - """snip_file_spdx_id : SNIPPET_FILE_SPDXID error""" - self.error = True - msg = ERROR_MESSAGES['SNIP_FILE_SPDXID_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snippet_concluded_license(self, p): - """snip_lics_conc : SNIPPET_LICS_CONC conc_license""" - try: - self.builder.set_snip_concluded_license(self.document, p[2]) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['SNIP_LICS_CONC_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - except OrderError: - self.order_error('SnippetLicenseConcluded', - 'SnippetSPDXID', p.lineno(1)) - except CardinalityError: - self.more_than_one_error('SnippetLicenseConcluded', p.lineno(1)) - - def p_snippet_concluded_license_1(self, p): - """snip_lics_conc : SNIPPET_LICS_CONC error""" - self.error = True - msg = ERROR_MESSAGES['SNIP_LICS_CONC_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snippet_lics_info(self, p): - """snip_lics_info : SNIPPET_LICS_INFO snip_lic_info_value""" - try: - self.builder.set_snippet_lics_info(self.document, p[2]) - except OrderError: - self.order_error( - 'LicenseInfoInSnippet', 'SnippetSPDXID', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['SNIP_LICS_INFO_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snippet_lics_info_1(self, p): - """snip_lics_info : SNIPPET_LICS_INFO error""" - self.error = True - msg = ERROR_MESSAGES['SNIP_LICS_INFO_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_snip_lic_info_value_1(self, p): - """snip_lic_info_value : NONE""" - p[0] = utils.SPDXNone() - - def p_snip_lic_info_value_2(self, p): - """snip_lic_info_value : NO_ASSERT""" - p[0] = utils.NoAssert() - - def p_snip_lic_info_value_3(self, p): - """snip_lic_info_value : LINE""" - if six.PY2: - value = p[1].decode(encoding='utf-8') - else: - value = p[1] - p[0] = document.License.from_identifier(value) - - def p_reviewer_1(self, p): - """reviewer : REVIEWER entity""" - self.builder.add_reviewer(self.document, p[2]) - - def p_reviewer_2(self, p): - """reviewer : REVIEWER error""" - self.error = True - msg = ERROR_MESSAGES['REVIEWER_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_review_date_1(self, p): - """review_date : REVIEW_DATE DATE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.add_review_date(self.document, value) - except CardinalityError: - self.more_than_one_error('ReviewDate', p.lineno(1)) - except OrderError: - self.order_error('ReviewDate', 'Reviewer', p.lineno(1)) - - def p_review_date_2(self, p): - """review_date : REVIEW_DATE error""" - self.error = True - msg = ERROR_MESSAGES['REVIEW_DATE_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_review_comment_1(self, p): - """review_comment : REVIEW_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.add_review_comment(self.document, value) - except CardinalityError: - self.more_than_one_error('ReviewComment', p.lineno(1)) - except OrderError: - self.order_error('ReviewComment', 'Reviewer', p.lineno(1)) - - def p_review_comment_2(self, p): - """review_comment : REVIEW_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['REVIEW_COMMENT_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_annotator_1(self, p): - """annotator : ANNOTATOR entity""" - self.builder.add_annotator(self.document, p[2]) - - def p_annotator_2(self, p): - """annotator : ANNOTATOR error""" - self.error = True - msg = ERROR_MESSAGES['ANNOTATOR_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_annotation_date_1(self, p): - """annotation_date : ANNOTATION_DATE DATE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.add_annotation_date(self.document, value) - except CardinalityError: - self.more_than_one_error('AnnotationDate', p.lineno(1)) - except OrderError: - self.order_error('AnnotationDate', 'Annotator', p.lineno(1)) - - def p_annotation_date_2(self, p): - """annotation_date : ANNOTATION_DATE error""" - self.error = True - msg = ERROR_MESSAGES['ANNOTATION_DATE_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_annotation_comment_1(self, p): - """annotation_comment : ANNOTATION_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.add_annotation_comment(self.document, value) - except CardinalityError: - self.more_than_one_error('AnnotationComment', p.lineno(1)) - except OrderError: - self.order_error('AnnotationComment', 'Annotator', p.lineno(1)) - - def p_annotation_comment_2(self, p): - """annotation_comment : ANNOTATION_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['ANNOTATION_COMMENT_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_annotation_type_1(self, p): - """annotation_type : ANNOTATION_TYPE LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.add_annotation_type(self.document, value) - except CardinalityError: - self.more_than_one_error('AnnotationType', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['ANNOTATION_TYPE_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - except OrderError: - self.order_error('AnnotationType', 'Annotator', p.lineno(1)) - - def p_annotation_type_2(self, p): - """annotation_type : ANNOTATION_TYPE error""" - self.error = True - msg = ERROR_MESSAGES['ANNOTATION_TYPE_VALUE'].format( - p.lineno(1)) - self.logger.log(msg) - - def p_annotation_spdx_id_1(self, p): - """annotation_spdx_id : ANNOTATION_SPDX_ID LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_annotation_spdx_id(self.document, value) - except CardinalityError: - self.more_than_one_error('SPDXREF', p.lineno(1)) - except OrderError: - self.order_error('SPDXREF', 'Annotator', p.lineno(1)) - - def p_annotation_spdx_id_2(self, p): - """annotation_spdx_id : ANNOTATION_SPDX_ID error""" - self.error = True - msg = ERROR_MESSAGES['ANNOTATION_SPDX_ID_VALUE'].format( - p.lineno(1)) - self.logger.log(msg) - - def p_lics_list_ver_1(self, p): - """locs_list_ver : LIC_LIST_VER LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_lics_list_ver(self.document, value) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['LIC_LIST_VER_VALUE'].format( - p[2], p.lineno(2)) - self.logger.log(msg) - except CardinalityError: - self.more_than_one_error('LicenseListVersion', p.lineno(1)) - - def p_lics_list_ver_2(self, p): - """locs_list_ver : LIC_LIST_VER error""" - self.error = True - msg = ERROR_MESSAGES['LIC_LIST_VER_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_doc_comment_1(self, p): - """doc_comment : DOC_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_doc_comment(self.document, value) - except CardinalityError: - self.more_than_one_error('DocumentComment', p.lineno(1)) - - def p_doc_comment_2(self, p): - """doc_comment : DOC_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['DOC_COMMENT_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_doc_namespace_1(self, p): - """doc_namespace : DOC_NAMESPACE LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_doc_namespace(self.document, value) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['DOC_NAMESPACE_VALUE'].format(p[2], p.lineno(2)) - self.logger.log(msg) - except CardinalityError: - self.more_than_one_error('DocumentNamespace', p.lineno(1)) - - def p_doc_namespace_2(self, p): - """doc_namespace : DOC_NAMESPACE error""" - self.error = True - msg = ERROR_MESSAGES['DOC_NAMESPACE_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_data_license_1(self, p): - """data_lics : DOC_LICENSE LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_doc_data_lics(self.document, value) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['DOC_LICENSE_VALUE'].format(p[2], p.lineno(2)) - self.logger.log(msg) - except CardinalityError: - self.more_than_one_error('DataLicense', p.lineno(1)) - - def p_data_license_2(self, p): - """data_lics : DOC_LICENSE error""" - self.error = True - msg = ERROR_MESSAGES['DOC_LICENSE_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_doc_name_1(self, p): - """doc_name : DOC_NAME LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_doc_name(self.document, value) - except CardinalityError: - self.more_than_one_error('DocumentName', p.lineno(1)) - - def p_doc_name_2(self, p): - """doc_name : DOC_NAME error""" - self.error = True - msg = ERROR_MESSAGES['DOC_NAME_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_ext_doc_refs_1(self, p): - """ext_doc_ref : EXT_DOC_REF DOC_REF_ID DOC_URI EXT_DOC_REF_CHKSUM""" - try: - if six.PY2: - doc_ref_id = p[2].decode(encoding='utf-8') - doc_uri = p[3].decode(encoding='utf-8') - ext_doc_chksum = p[4].decode(encoding='utf-8') - else: - doc_ref_id = p[2] - doc_uri = p[3] - ext_doc_chksum = p[4] - - self.builder.add_ext_doc_refs(self.document, doc_ref_id, doc_uri, - ext_doc_chksum) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['EXT_DOC_REF_VALUE'].format(p.lineno(2)) - self.logger.log(msg) - - def p_ext_doc_refs_2(self, p): - """ext_doc_ref : EXT_DOC_REF error""" - self.error = True - msg = ERROR_MESSAGES['EXT_DOC_REF_VALUE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_spdx_version_1(self, p): - """spdx_version : DOC_VERSION LINE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_doc_version(self.document, value) - except CardinalityError: - self.more_than_one_error('SPDXVersion', p.lineno(1)) - except SPDXValueError: - self.error = True - msg = ERROR_MESSAGES['DOC_VERSION_VALUE'].format(p[2], p.lineno(1)) - self.logger.log(msg) - - def p_spdx_version_2(self, p): - """spdx_version : DOC_VERSION error""" - self.error = True - msg = ERROR_MESSAGES['DOC_VERSION_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_creator_comment_1(self, p): - """creator_comment : CREATOR_COMMENT TEXT""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_creation_comment(self.document, value) - except CardinalityError: - self.more_than_one_error('CreatorComment', p.lineno(1)) - - def p_creator_comment_2(self, p): - """creator_comment : CREATOR_COMMENT error""" - self.error = True - msg = ERROR_MESSAGES['CREATOR_COMMENT_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_creator_1(self, p): - """creator : CREATOR entity""" - self.builder.add_creator(self.document, p[2]) - - def p_creator_2(self, p): - """creator : CREATOR error""" - self.error = True - msg = ERROR_MESSAGES['CREATOR_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_created_1(self, p): - """created : CREATED DATE""" - try: - if six.PY2: - value = p[2].decode(encoding='utf-8') - else: - value = p[2] - self.builder.set_created_date(self.document, value) - except CardinalityError: - self.more_than_one_error('Created', p.lineno(1)) - - def p_created_2(self, p): - """created : CREATED error""" - self.error = True - msg = ERROR_MESSAGES['CREATED_VALUE_TYPE'].format(p.lineno(1)) - self.logger.log(msg) - - def p_entity_1(self, p): - """entity : TOOL_VALUE - """ - try: - if six.PY2: - value = p[1].decode(encoding='utf-8') - else: - value = p[1] - p[0] = self.builder.build_tool(self.document, value) - except SPDXValueError: - msg = ERROR_MESSAGES['TOOL_VALUE'].format(p[1], p.lineno(1)) - self.logger.log(msg) - self.error = True - p[0] = None - - def p_entity_2(self, p): - """entity : ORG_VALUE - """ - try: - if six.PY2: - value = p[1].decode(encoding='utf-8') - else: - value = p[1] - p[0] = self.builder.build_org(self.document, value) - except SPDXValueError: - msg = ERROR_MESSAGES['ORG_VALUE'].format(p[1], p.lineno(1)) - self.logger.log(msg) - self.error = True - p[0] = None - - def p_entity_3(self, p): - """entity : PERSON_VALUE - """ - try: - if six.PY2: - value = p[1].decode(encoding='utf-8') - else: - value = p[1] - p[0] = self.builder.build_person(self.document, value) - except SPDXValueError: - msg = ERROR_MESSAGES['PERSON_VALUE'].format(p[1], p.lineno(1)) - self.logger.log(msg) - self.error = True - p[0] = None - - def p_error(self, p): - pass - - def build(self, **kwargs): - self.lex = Lexer() - self.lex.build(reflags=re.UNICODE) - self.yacc = yacc.yacc(module=self, **kwargs) - - def parse(self, text): - self.document = document.Document() - self.error = False - self.yacc.parse(text, lexer=self.lex) - # FIXME: this state does not make sense - self.builder.reset() - validation_messages = [] - # Report extra errors if self.error is False otherwise there will be - # redundent messages - validation_messages = self.document.validate(validation_messages) - if not self.error: - if validation_messages: - for msg in validation_messages: - self.logger.log(msg) - self.error = True - return self.document, self.error diff --git a/spdx/parsers/tagvaluebuilders.py b/spdx/parsers/tagvaluebuilders.py deleted file mode 100644 index 079fd512e..000000000 --- a/spdx/parsers/tagvaluebuilders.py +++ /dev/null @@ -1,1508 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import re - -from six import string_types - -from spdx import annotation -from spdx import checksum -from spdx import creationinfo -from spdx import document -from spdx import file -from spdx import package -from spdx import review -from spdx import snippet -from spdx import utils -from spdx import version - -from spdx.document import ExternalDocumentRef -from spdx.parsers.builderexceptions import CardinalityError -from spdx.parsers.builderexceptions import OrderError -from spdx.parsers.builderexceptions import SPDXValueError -from spdx.parsers import validations - - -def checksum_from_sha1(value): - """ - Return an spdx.checksum.Algorithm instance representing the SHA1 - checksum or None if does not match CHECKSUM_RE. - """ - # More constrained regex at lexer level - CHECKSUM_RE = re.compile('SHA1:\\s*([\\S]+)', re.UNICODE) - match = CHECKSUM_RE.match(value) - if match: - return checksum.Algorithm(identifier='SHA1', value=match.group(1)) - else: - return None - - -def str_from_text(text): - """ - Return content of a free form text block as a string. - """ - REGEX = re.compile('((.|\n)+)', re.UNICODE) - match = REGEX.match(text) - if match: - return match.group(1) - else: - return None - - -class DocBuilder(object): - """ - Set the fields of the top level document model. - """ - VERS_STR_REGEX = re.compile(r'SPDX-(\d+)\.(\d+)', re.UNICODE) - - def __init__(self): - # FIXME: this state does not make sense - self.reset_document() - - def set_doc_version(self, doc, value): - """ - Set the document version. - Raise SPDXValueError if malformed value. - Raise CardinalityError if already defined. - """ - if not self.doc_version_set: - self.doc_version_set = True - m = self.VERS_STR_REGEX.match(value) - if m is None: - raise SPDXValueError('Document::Version') - else: - doc.version = version.Version(major=int(m.group(1)), - minor=int(m.group(2))) - return True - else: - raise CardinalityError('Document::Version') - - def set_doc_data_lics(self, doc, lics): - """ - Set the document data license. - Raise value error if malformed value - Raise CardinalityError if already defined. - """ - if not self.doc_data_lics_set: - self.doc_data_lics_set = True - if validations.validate_data_lics(lics): - doc.data_license = document.License.from_identifier(lics) - return True - else: - raise SPDXValueError('Document::DataLicense') - else: - raise CardinalityError('Document::DataLicense') - - def set_doc_name(self, doc, name): - """ - Set the document name. - Raise CardinalityError if already defined. - """ - if not self.doc_name_set: - doc.name = name - self.doc_name_set = True - return True - else: - raise CardinalityError('Document::Name') - - def set_doc_spdx_id(self, doc, doc_spdx_id_line): - """ - Set the document SPDX Identifier. - Raise value error if malformed value. - Raise CardinalityError if already defined. - """ - if not self.doc_spdx_id_set: - if doc_spdx_id_line == 'SPDXRef-DOCUMENT': - doc.spdx_id = doc_spdx_id_line - self.doc_spdx_id_set = True - return True - else: - raise SPDXValueError('Document::SPDXID') - else: - raise CardinalityError('Document::SPDXID') - - def set_doc_comment(self, doc, comment): - """ - Set document comment. - Raise CardinalityError if comment already set. - Raise SPDXValueError if comment is not free form text. - """ - if not self.doc_comment_set: - self.doc_comment_set = True - if validations.validate_doc_comment(comment): - doc.comment = str_from_text(comment) - return True - else: - raise SPDXValueError('Document::Comment') - else: - raise CardinalityError('Document::Comment') - - def set_doc_namespace(self, doc, namespace): - """ - Set the document namespace. - Raise SPDXValueError if malformed value. - Raise CardinalityError if already defined. - """ - if not self.doc_namespace_set: - self.doc_namespace_set = True - if validations.validate_doc_namespace(namespace): - doc.namespace = namespace - return True - else: - raise SPDXValueError('Document::Namespace') - else: - raise CardinalityError('Document::Comment') - - def reset_document(self): - """ - Reset the state to allow building new documents - """ - # FIXME: this state does not make sense - self.doc_version_set = False - self.doc_comment_set = False - self.doc_namespace_set = False - self.doc_data_lics_set = False - self.doc_name_set = False - self.doc_spdx_id_set = False - - -class ExternalDocumentRefBuilder(object): - - def set_ext_doc_id(self, doc, ext_doc_id): - """ - Set the `external_document_id` attribute of the `ExternalDocumentRef` object. - """ - doc.add_ext_document_reference( - ExternalDocumentRef( - external_document_id=ext_doc_id)) - - def set_spdx_doc_uri(self, doc, spdx_doc_uri): - """ - Set the `spdx_document_uri` attribute of the `ExternalDocumentRef` object. - """ - if validations.validate_doc_namespace(spdx_doc_uri): - doc.ext_document_references[-1].spdx_document_uri = spdx_doc_uri - else: - raise SPDXValueError('Document::ExternalDocumentRef') - - def set_chksum(self, doc, chksum): - """ - Set the `check_sum` attribute of the `ExternalDocumentRef` object. - """ - doc.ext_document_references[-1].check_sum = checksum_from_sha1( - chksum) - - def add_ext_doc_refs(self, doc, ext_doc_id, spdx_doc_uri, chksum): - self.set_ext_doc_id(doc, ext_doc_id) - self.set_spdx_doc_uri(doc, spdx_doc_uri) - self.set_chksum(doc, chksum) - - -class EntityBuilder(object): - - tool_re = re.compile(r'Tool:\s*(.+)', re.UNICODE) - person_re = re.compile(r'Person:\s*(([^(])+)(\((.*)\))?', re.UNICODE) - org_re = re.compile(r'Organization:\s*(([^(])+)(\((.*)\))?', re.UNICODE) - PERSON_NAME_GROUP = 1 - PERSON_EMAIL_GROUP = 4 - ORG_NAME_GROUP = 1 - ORG_EMAIL_GROUP = 4 - TOOL_NAME_GROUP = 1 - - def build_tool(self, doc, entity): - """ - Build a tool object out of a string representation. - Return built tool. - Raise SPDXValueError if failed to extract tool name or name is malformed - """ - match = self.tool_re.match(entity) - if match and validations.validate_tool_name(match.group(self.TOOL_NAME_GROUP)): - name = match.group(self.TOOL_NAME_GROUP) - return creationinfo.Tool(name) - else: - raise SPDXValueError('Failed to extract tool name') - - def build_org(self, doc, entity): - """ - Build an organization object of of a string representation. - Return built organization. - Raise SPDXValueError if failed to extractname. - """ - match = self.org_re.match(entity) - if match and validations.validate_org_name(match.group(self.ORG_NAME_GROUP)): - name = match.group(self.ORG_NAME_GROUP).strip() - email = match.group(self.ORG_EMAIL_GROUP) - if (email is not None) and (len(email) != 0): - return creationinfo.Organization(name=name, email=email.strip()) - else: - return creationinfo.Organization(name=name, email=None) - else: - raise SPDXValueError('Failed to extract Organization name') - - def build_person(self, doc, entity): - """ - Build an organization object of of a string representation. - Return built organization. Raise SPDXValueError if failed to extract name. - """ - match = self.person_re.match(entity) - if match and validations.validate_person_name(match.group(self.PERSON_NAME_GROUP)): - name = match.group(self.PERSON_NAME_GROUP).strip() - email = match.group(self.PERSON_EMAIL_GROUP) - if (email is not None) and (len(email) != 0): - return creationinfo.Person(name=name, email=email.strip()) - else: - return creationinfo.Person(name=name, email=None) - else: - raise SPDXValueError('Failed to extract person name') - - -class CreationInfoBuilder(object): - - def __init__(self): - # FIXME: this state does not make sense - self.reset_creation_info() - - def add_creator(self, doc, creator): - """ - Add a creator to the document's creation info. - Return true if creator is valid. - Creator must be built by an EntityBuilder. - Raise SPDXValueError if not a creator type. - """ - if validations.validate_creator(creator): - doc.creation_info.add_creator(creator) - return True - else: - raise SPDXValueError('CreationInfo::Creator') - - def set_created_date(self, doc, created): - """ - Set created date. - Raise CardinalityError if created date already set. - Raise SPDXValueError if created is not a date. - """ - if not self.created_date_set: - self.created_date_set = True - date = utils.datetime_from_iso_format(created) - if date is not None: - doc.creation_info.created = date - return True - else: - raise SPDXValueError('CreationInfo::Date') - else: - raise CardinalityError('CreationInfo::Created') - - def set_creation_comment(self, doc, comment): - """ - Set creation comment. - Raise CardinalityError if comment already set. - Raise SPDXValueError if not free form text. - """ - if not self.creation_comment_set: - self.creation_comment_set = True - if validations.validate_creation_comment(comment): - doc.creation_info.comment = str_from_text(comment) - return True - else: - raise SPDXValueError('CreationInfo::Comment') - else: - raise CardinalityError('CreationInfo::Comment') - - def set_lics_list_ver(self, doc, value): - """ - Set the license list version. - Raise CardinalityError if already set. - Raise SPDXValueError if incorrect value. - """ - if not self.lics_list_ver_set: - self.lics_list_ver_set = True - vers = version.Version.from_str(value) - if vers is not None: - doc.creation_info.license_list_version = vers - return True - else: - raise SPDXValueError('CreationInfo::LicenseListVersion') - else: - raise CardinalityError('CreationInfo::LicenseListVersion') - - def reset_creation_info(self): - """ - Reset builder state to allow building new creation info. - """ - # FIXME: this state does not make sense - self.created_date_set = False - self.creation_comment_set = False - self.lics_list_ver_set = False - - -class ReviewBuilder(object): - - def __init__(self): - # FIXME: this state does not make sense - self.reset_reviews() - - def reset_reviews(self): - """ - Reset the builder's state to allow building new reviews. - """ - # FIXME: this state does not make sense - self.review_date_set = False - self.review_comment_set = False - - def add_reviewer(self, doc, reviewer): - """ - Adds a reviewer to the SPDX Document. - Reviwer is an entity created by an EntityBuilder. - Raise SPDXValueError if not a valid reviewer type. - """ - # Each reviewer marks the start of a new review object. - # FIXME: this state does not make sense - self.reset_reviews() - if validations.validate_reviewer(reviewer): - doc.add_review(review.Review(reviewer=reviewer)) - return True - else: - raise SPDXValueError('Review::Reviewer') - - def add_review_date(self, doc, reviewed): - """ - Set the review date. - Raise CardinalityError if already set. - Raise OrderError if no reviewer defined before. - Raise SPDXValueError if invalid reviewed value. - """ - if len(doc.reviews) != 0: - if not self.review_date_set: - self.review_date_set = True - date = utils.datetime_from_iso_format(reviewed) - if date is not None: - doc.reviews[-1].review_date = date - return True - else: - raise SPDXValueError('Review::ReviewDate') - else: - raise CardinalityError('Review::ReviewDate') - else: - raise OrderError('Review::ReviewDate') - - def add_review_comment(self, doc, comment): - """ - Set the review comment. - Raise CardinalityError if already set. - Raise OrderError if no reviewer defined before. - Raise SPDXValueError if comment is not free form text. - """ - if len(doc.reviews) != 0: - if not self.review_comment_set: - self.review_comment_set = True - if validations.validate_review_comment(comment): - doc.reviews[-1].comment = str_from_text(comment) - return True - else: - raise SPDXValueError('ReviewComment::Comment') - else: - raise CardinalityError('ReviewComment') - else: - raise OrderError('ReviewComment') - - -class AnnotationBuilder(object): - - def __init__(self): - # FIXME: this state does not make sense - self.reset_annotations() - - def reset_annotations(self): - """ - Reset the builder's state to allow building new annotations. - """ - # FIXME: this state does not make sense - self.annotation_date_set = False - self.annotation_comment_set = False - self.annotation_type_set = False - self.annotation_spdx_id_set = False - - def add_annotator(self, doc, annotator): - """ - Add an annotator to the SPDX Document. - Annotator is an entity created by an EntityBuilder. - Raise SPDXValueError if not a valid annotator type. - """ - # Each annotator marks the start of a new annotation object. - # FIXME: this state does not make sense - self.reset_annotations() - if validations.validate_annotator(annotator): - doc.add_annotation(annotation.Annotation(annotator=annotator)) - return True - else: - raise SPDXValueError('Annotation::Annotator') - - def add_annotation_date(self, doc, annotation_date): - """ - Set the annotation date. - Raise CardinalityError if already set. - Raise OrderError if no annotator defined before. - Raise SPDXValueError if invalid value. - """ - if len(doc.annotations) != 0: - if not self.annotation_date_set: - self.annotation_date_set = True - date = utils.datetime_from_iso_format(annotation_date) - if date is not None: - doc.annotations[-1].annotation_date = date - return True - else: - raise SPDXValueError('Annotation::AnnotationDate') - else: - raise CardinalityError('Annotation::AnnotationDate') - else: - raise OrderError('Annotation::AnnotationDate') - - def add_annotation_comment(self, doc, comment): - """ - Set the annotation comment. - Raise CardinalityError if already set. - Raise OrderError if no annotator defined before. - Raise SPDXValueError if comment is not free form text. - """ - if len(doc.annotations) != 0: - if not self.annotation_comment_set: - self.annotation_comment_set = True - if validations.validate_annotation_comment(comment): - doc.annotations[-1].comment = str_from_text(comment) - return True - else: - raise SPDXValueError('AnnotationComment::Comment') - else: - raise CardinalityError('AnnotationComment::Comment') - else: - raise OrderError('AnnotationComment::Comment') - - def add_annotation_type(self, doc, annotation_type): - """ - Set the annotation type. - Raise CardinalityError if already set. - Raise OrderError if no annotator defined before. - Raise SPDXValueError if invalid value. - """ - if len(doc.annotations) != 0: - if not self.annotation_type_set: - self.annotation_type_set = True - if validations.validate_annotation_type(annotation_type): - doc.annotations[-1].annotation_type = annotation_type - return True - else: - raise SPDXValueError('Annotation::AnnotationType') - else: - raise CardinalityError('Annotation::AnnotationType') - else: - raise OrderError('Annotation::AnnotationType') - - def set_annotation_spdx_id(self, doc, spdx_id): - """ - Set the annotation SPDX Identifier. - Raise CardinalityError if already set. - Raise OrderError if no annotator defined before. - """ - if len(doc.annotations) != 0: - if not self.annotation_spdx_id_set: - self.annotation_spdx_id_set = True - doc.annotations[-1].spdx_id = spdx_id - return True - else: - raise CardinalityError('Annotation::SPDXREF') - else: - raise OrderError('Annotation::SPDXREF') - - -class PackageBuilder(object): - VERIF_CODE_REGEX = re.compile(r"([0-9a-f]+)\s*(\(\s*(.+)\))?", re.UNICODE) - VERIF_CODE_CODE_GRP = 1 - VERIF_CODE_EXC_FILES_GRP = 3 - - def __init__(self): - # FIXME: this state does not make sense - self.reset_package() - - def reset_package(self): - """Resets the builder's state in order to build new packages.""" - # FIXME: this state does not make sense - self.package_set = False - self.package_spdx_id_set = False - self.package_vers_set = False - self.package_file_name_set = False - self.package_supplier_set = False - self.package_originator_set = False - self.package_down_location_set = False - self.package_files_analyzed_set = False - self.package_home_set = False - self.package_verif_set = False - self.package_chk_sum_set = False - self.package_source_info_set = False - self.package_conc_lics_set = False - self.package_license_declared_set = False - self.package_license_comment_set = False - self.package_cr_text_set = False - self.package_summary_set = False - self.package_desc_set = False - self.package_comment_set = False - self.pkg_ext_comment_set = False - - def create_package(self, doc, name): - """ - Create a package for the SPDX Document. - name - any string. - Raise CardinalityError if package already defined. - """ - if not self.package_set: - self.package_set = True - doc.package = package.Package(name=name) - return True - else: - raise CardinalityError('Package::Name') - - def set_pkg_spdx_id(self, doc, spdx_id): - """ - Set the Package SPDX Identifier. - Raise SPDXValueError if malformed value. - Raise CardinalityError if already defined. - """ - self.assert_package_exists() - if not self.package_spdx_id_set: - if validations.validate_pkg_spdx_id(spdx_id): - doc.package.spdx_id = spdx_id - self.package_spdx_id_set = True - return True - else: - raise SPDXValueError('Package::SPDXID') - else: - raise CardinalityError('Package::SPDXID') - - def set_pkg_vers(self, doc, version): - """ - Set package version, if not already set. - version - Any string. - Raise CardinalityError if already has a version. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_vers_set: - self.package_vers_set = True - doc.package.version = version - return True - else: - raise CardinalityError('Package::Version') - - def set_pkg_file_name(self, doc, name): - """ - Set the package file name, if not already set. - name - Any string. - Raise CardinalityError if already has a file_name. - Raise OrderError if no pacakge previously defined. - """ - self.assert_package_exists() - if not self.package_file_name_set: - self.package_file_name_set = True - doc.package.file_name = name - return True - else: - raise CardinalityError('Package::FileName') - - def set_pkg_supplier(self, doc, entity): - """ - Set the package supplier, if not already set. - entity - Organization, Person or NoAssert. - Raise CardinalityError if already has a supplier. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_supplier_set: - self.package_supplier_set = True - if validations.validate_pkg_supplier(entity): - doc.package.supplier = entity - return True - else: - raise SPDXValueError('Package::Supplier') - else: - raise CardinalityError('Package::Supplier') - - def set_pkg_originator(self, doc, entity): - """ - Set the package originator, if not already set. - entity - Organization, Person or NoAssert. - Raise CardinalityError if already has an originator. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_originator_set: - self.package_originator_set = True - if validations.validate_pkg_originator(entity): - doc.package.originator = entity - return True - else: - raise SPDXValueError('Package::Originator') - else: - raise CardinalityError('Package::Originator') - - def set_pkg_down_location(self, doc, location): - """ - Set the package download location, if not already set. - location - A string - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_down_location_set: - self.package_down_location_set = True - doc.package.download_location = location - return True - else: - raise CardinalityError('Package::DownloadLocation') - - def set_pkg_files_analyzed(self, doc, files_analyzed): - """ - Set the package files analyzed, if not already set. - Raise SPDXValueError if malformed value, CardinalityError if - already defined. - """ - self.assert_package_exists() - if not self.package_files_analyzed_set: - if files_analyzed: - if validations.validate_pkg_files_analyzed(files_analyzed): - self.package_files_analyzed_set = True - doc.package.files_analyzed = files_analyzed - print(doc.package.files_analyzed) - return True - else: - raise SPDXValueError('Package::FilesAnalyzed') - else: - raise CardinalityError('Package::FilesAnalyzed') - - def set_pkg_home(self, doc, location): - """Set the package homepage location if not already set. - location - A string or None or NoAssert. - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - Raise SPDXValueError if location has incorrect value. - """ - self.assert_package_exists() - if not self.package_home_set: - self.package_home_set = True - if validations.validate_pkg_homepage(location): - doc.package.homepage = location - return True - else: - raise SPDXValueError('Package::HomePage') - else: - raise CardinalityError('Package::HomePage') - - def set_pkg_verif_code(self, doc, code): - """ - Set the package verification code, if not already set. - code - A string. - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - Raise Value error if doesn't match verifcode form - """ - self.assert_package_exists() - if not self.package_verif_set: - self.package_verif_set = True - match = self.VERIF_CODE_REGEX.match(code) - if match: - doc.package.verif_code = match.group(self.VERIF_CODE_CODE_GRP) - if match.group(self.VERIF_CODE_EXC_FILES_GRP) is not None: - doc.package.verif_exc_files = match.group(self.VERIF_CODE_EXC_FILES_GRP).split(',') - return True - else: - raise SPDXValueError('Package::VerificationCode') - else: - raise CardinalityError('Package::VerificationCode') - - def set_pkg_chk_sum(self, doc, chk_sum): - """ - Set the package check sum, if not already set. - chk_sum - A string - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_chk_sum_set: - self.package_chk_sum_set = True - doc.package.check_sum = checksum_from_sha1(chk_sum) - return True - else: - raise CardinalityError('Package::CheckSum') - - def set_pkg_source_info(self, doc, text): - """ - Set the package's source information, if not already set. - text - Free form text. - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - SPDXValueError if text is not free form text. - """ - self.assert_package_exists() - if not self.package_source_info_set: - self.package_source_info_set = True - if validations.validate_pkg_src_info(text): - doc.package.source_info = str_from_text(text) - return True - else: - raise SPDXValueError('Pacckage::SourceInfo') - else: - raise CardinalityError('Package::SourceInfo') - - def set_pkg_licenses_concluded(self, doc, licenses): - """ - Set the package's concluded licenses. - licenses - License info. - Raise CardinalityError if already defined. - Raise OrderError if no package previously defined. - Raise SPDXValueError if data malformed. - """ - self.assert_package_exists() - if not self.package_conc_lics_set: - self.package_conc_lics_set = True - if validations.validate_lics_conc(licenses): - doc.package.conc_lics = licenses - return True - else: - raise SPDXValueError('Package::ConcludedLicenses') - else: - raise CardinalityError('Package::ConcludedLicenses') - - def set_pkg_license_from_file(self, doc, lic): - """ - Add a license from a file to the package. - Raise SPDXValueError if data malformed. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if validations.validate_lics_from_file(lic): - doc.package.licenses_from_files.append(lic) - return True - else: - raise SPDXValueError('Package::LicensesFromFile') - - def set_pkg_license_declared(self, doc, lic): - """ - Set the package's declared license. - Raise SPDXValueError if data malformed. - Raise OrderError if no package previously defined. - Raise CardinalityError if already set. - """ - self.assert_package_exists() - if not self.package_license_declared_set: - self.package_license_declared_set = True - if validations.validate_lics_conc(lic): - doc.package.license_declared = lic - return True - else: - raise SPDXValueError('Package::LicenseDeclared') - else: - raise CardinalityError('Package::LicenseDeclared') - - def set_pkg_license_comment(self, doc, text): - """ - Set the package's license comment. - Raise OrderError if no package previously defined. - Raise CardinalityError if already set. - Raise SPDXValueError if text is not free form text. - """ - self.assert_package_exists() - if not self.package_license_comment_set: - self.package_license_comment_set = True - if validations.validate_pkg_lics_comment(text): - doc.package.license_comment = str_from_text(text) - return True - else: - raise SPDXValueError('Package::LicenseComment') - else: - raise CardinalityError('Package::LicenseComment') - - def set_pkg_cr_text(self, doc, text): - """ - Set the package's copyright text. - Raise OrderError if no package previously defined. - Raise CardinalityError if already set. - Raise value error if text is not one of [None, NOASSERT, TEXT]. - """ - self.assert_package_exists() - if not self.package_cr_text_set: - self.package_cr_text_set = True - if validations.validate_pkg_cr_text(text): - if isinstance(text, string_types): - doc.package.cr_text = str_from_text(text) - else: - doc.package.cr_text = text # None or NoAssert - else: - raise SPDXValueError('Package::CopyrightText') - else: - raise CardinalityError('Package::CopyrightText') - - def set_pkg_summary(self, doc, text): - """ - Set the package summary. - Raise SPDXValueError if text is not free form text. - Raise CardinalityError if summary already set. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_summary_set: - self.package_summary_set = True - if validations.validate_pkg_summary(text): - doc.package.summary = str_from_text(text) - else: - raise SPDXValueError('Package::Summary') - else: - raise CardinalityError('Package::Summary') - - def set_pkg_desc(self, doc, text): - """ - Set the package's description. - Raise SPDXValueError if text is not free form text. - Raise CardinalityError if description already set. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_desc_set: - self.package_desc_set = True - if validations.validate_pkg_desc(text): - doc.package.description = str_from_text(text) - else: - raise SPDXValueError('Package::Description') - else: - raise CardinalityError('Package::Description') - - def set_pkg_comment(self, doc, text): - """ - Set the package's comment. - Raise SPDXValueError if text is not free form text. - Raise CardinalityError if comment already set. - Raise OrderError if no package previously defined. - """ - self.assert_package_exists() - if not self.package_comment_set: - self.package_comment_set = True - if validations.validate_pkg_comment(text): - doc.package.comment = str_from_text(text) - else: - raise SPDXValueError('Package::Comment') - else: - raise CardinalityError('Package::Comment') - - def set_pkg_ext_ref_category(self, doc, category): - """ - Set the `category` attribute of the `ExternalPackageRef` object. - """ - self.assert_package_exists() - if validations.validate_pkg_ext_ref_category(category): - if (len(doc.package.pkg_ext_refs) and - doc.package.pkg_ext_refs[-1].category is None): - doc.package.pkg_ext_refs[-1].category = category - else: - doc.package.add_pkg_ext_refs( - package.ExternalPackageRef(category=category)) - else: - raise SPDXValueError('ExternalRef::Category') - - def set_pkg_ext_ref_type(self, doc, pkg_ext_ref_type): - """ - Set the `pkg_ext_ref_type` attribute of the `ExternalPackageRef` object. - """ - self.assert_package_exists() - if validations.validate_pkg_ext_ref_type(pkg_ext_ref_type): - if (len(doc.package.pkg_ext_refs) and - doc.package.pkg_ext_refs[-1].pkg_ext_ref_type is None): - doc.package.pkg_ext_refs[-1].pkg_ext_ref_type = pkg_ext_ref_type - else: - doc.package.add_pkg_ext_refs(package.ExternalPackageRef( - pkg_ext_ref_type=pkg_ext_ref_type)) - else: - raise SPDXValueError('ExternalRef::Type') - - def set_pkg_ext_ref_locator(self, doc, locator): - """ - Set the `locator` attribute of the `ExternalPackageRef` object. - """ - self.assert_package_exists() - if (len(doc.package.pkg_ext_refs) and - doc.package.pkg_ext_refs[-1].locator is None): - doc.package.pkg_ext_refs[-1].locator = locator - else: - doc.package.add_pkg_ext_refs(package.ExternalPackageRef( - locator=locator)) - - def add_pkg_ext_ref_comment(self, doc, comment): - """ - Set the `comment` attribute of the `ExternalPackageRef` object. - """ - self.assert_package_exists() - if not len(doc.package.pkg_ext_refs): - raise OrderError('Package::ExternalRef') - else: - if validations.validate_pkg_ext_ref_comment(comment): - doc.package.pkg_ext_refs[-1].comment = str_from_text(comment) - else: - raise SPDXValueError('ExternalRef::Comment') - - def add_pkg_ext_refs(self, doc, category, pkg_ext_ref_type, locator): - self.set_pkg_ext_ref_category(doc, category) - self.set_pkg_ext_ref_type(doc, pkg_ext_ref_type) - self.set_pkg_ext_ref_locator(doc, locator) - - def assert_package_exists(self): - if not self.package_set: - raise OrderError('Package') - - -class FileBuilder(object): - - def __init__(self): - # FIXME: this state does not make sense - self.reset_file_stat() - - def set_file_name(self, doc, name): - """ - Raise OrderError if no package defined. - """ - if self.has_package(doc): - doc.package.files.append(file.File(name)) - # A file name marks the start of a new file instance. - # The builder must be reset - # FIXME: this state does not make sense - self.reset_file_stat() - return True - else: - raise OrderError('File::Name') - - def set_file_spdx_id(self, doc, spdx_id): - """ - Set the file SPDX Identifier. - Raise OrderError if no package or no file defined. - Raise SPDXValueError if malformed value. - Raise CardinalityError if more than one spdx_id set. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_spdx_id_set: - self.file_spdx_id_set = True - if validations.validate_file_spdx_id(spdx_id): - self.file(doc).spdx_id = spdx_id - return True - else: - raise SPDXValueError('File::SPDXID') - else: - raise CardinalityError('File::SPDXID') - else: - raise OrderError('File::SPDXID') - - def set_file_comment(self, doc, text): - """ - Raise OrderError if no package or no file defined. - Raise CardinalityError if more than one comment set. - Raise SPDXValueError if text is not free form text. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_comment_set: - self.file_comment_set = True - if validations.validate_file_comment(text): - self.file(doc).comment = str_from_text(text) - return True - else: - raise SPDXValueError('File::Comment') - else: - raise CardinalityError('File::Comment') - else: - raise OrderError('File::Comment') - - def set_file_type(self, doc, type_value): - """ - Raise OrderError if no package or file defined. - Raise CardinalityError if more than one type set. - Raise SPDXValueError if type is unknown. - """ - type_dict = { - 'SOURCE': file.FileType.SOURCE, - 'BINARY': file.FileType.BINARY, - 'ARCHIVE': file.FileType.ARCHIVE, - 'OTHER': file.FileType.OTHER - } - if self.has_package(doc) and self.has_file(doc): - if not self.file_type_set: - self.file_type_set = True - if type_value in type_dict.keys(): - self.file(doc).type = type_dict[type_value] - return True - else: - raise SPDXValueError('File::Type') - else: - raise CardinalityError('File::Type') - else: - raise OrderError('File::Type') - - def set_file_chksum(self, doc, chksum): - """ - Raise OrderError if no package or file defined. - Raise CardinalityError if more than one chksum set. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_chksum_set: - self.file_chksum_set = True - self.file(doc).chk_sum = checksum_from_sha1(chksum) - return True - else: - raise CardinalityError('File::CheckSum') - else: - raise OrderError('File::CheckSum') - - def set_concluded_license(self, doc, lic): - """ - Raise OrderError if no package or file defined. - Raise CardinalityError if already set. - Raise SPDXValueError if malformed. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_conc_lics_set: - self.file_conc_lics_set = True - if validations.validate_lics_conc(lic): - self.file(doc).conc_lics = lic - return True - else: - raise SPDXValueError('File::ConcludedLicense') - else: - raise CardinalityError('File::ConcludedLicense') - else: - raise OrderError('File::ConcludedLicense') - - def set_file_license_in_file(self, doc, lic): - """ - Raise OrderError if no package or file defined. - Raise SPDXValueError if malformed value. - """ - if self.has_package(doc) and self.has_file(doc): - if validations.validate_file_lics_in_file(lic): - self.file(doc).add_lics(lic) - return True - else: - raise SPDXValueError('File::LicenseInFile') - else: - raise OrderError('File::LicenseInFile') - - def set_file_license_comment(self, doc, text): - """ - Raise OrderError if no package or file defined. - Raise SPDXValueError if text is not free form text. - Raise CardinalityError if more than one per file. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_license_comment_set: - self.file_license_comment_set = True - if validations.validate_file_lics_comment(text): - self.file(doc).license_comment = str_from_text(text) - else: - raise SPDXValueError('File::LicenseComment') - else: - raise CardinalityError('File::LicenseComment') - else: - raise OrderError('File::LicenseComment') - - def set_file_copyright(self, doc, text): - """ - Raise OrderError if no package or file defined. - Raise SPDXValueError if not free form text or NONE or NO_ASSERT. - Raise CardinalityError if more than one. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_copytext_set: - self.file_copytext_set = True - if validations.validate_file_cpyright(text): - if isinstance(text, string_types): - self.file(doc).copyright = str_from_text(text) - else: - self.file(doc).copyright = text # None or NoAssert - return True - else: - raise SPDXValueError('File::CopyRight') - else: - raise CardinalityError('File::CopyRight') - else: - raise OrderError('File::CopyRight') - - def set_file_notice(self, doc, text): - """ - Raise OrderError if no package or file defined. - Raise SPDXValueError if not free form text. - Raise CardinalityError if more than one. - """ - if self.has_package(doc) and self.has_file(doc): - if not self.file_notice_set: - self.file_notice_set = True - if validations.validate_file_notice(text): - self.file(doc).notice = str_from_text(text) - else: - raise SPDXValueError('File::Notice') - else: - raise CardinalityError('File::Notice') - else: - raise OrderError('File::Notice') - - def add_file_contribution(self, doc, value): - """ - Raise OrderError if no package or file defined. - """ - if self.has_package(doc) and self.has_file(doc): - self.file(doc).add_contrib(value) - else: - raise OrderError('File::Contributor') - - def add_file_dep(self, doc, value): - """ - Raise OrderError if no package or file defined. - """ - if self.has_package(doc) and self.has_file(doc): - self.file(doc).add_depend(value) - else: - raise OrderError('File::Dependency') - - def set_file_atrificat_of_project(self, doc, symbol, value): - """ - Set a file name, uri or home artificat. - Raise OrderError if no package or file defined. - """ - if self.has_package(doc) and self.has_file(doc): - self.file(doc).add_artifact(symbol, value) - else: - raise OrderError('File::Artificat') - - - def file(self, doc): - """ - Return the last file in the document's package's file list. - """ - return doc.package.files[-1] - - def has_file(self, doc): - """ - Return true if the document's package has at least one file. - Does not test if the document has a package. - """ - return len(doc.package.files) != 0 - - def has_package(self, doc): - """ - Return true if the document has a package. - """ - return doc.package is not None - - def reset_file_stat(self): - """ - Reset the builder's state to enable building new files. - """ - # FIXME: this state does not make sense - self.file_spdx_id_set = False - self.file_comment_set = False - self.file_type_set = False - self.file_chksum_set = False - self.file_conc_lics_set = False - self.file_license_comment_set = False - self.file_notice_set = False - self.file_copytext_set = False - - -class LicenseBuilder(object): - - def __init__(self): - # FIXME: this state does not make sense - self.reset_extr_lics() - - def extr_lic(self, doc): - """ - Retrieve last license in extracted license list. - """ - return doc.extracted_licenses[-1] - - def has_extr_lic(self, doc): - return len(doc.extracted_licenses) != 0 - - def set_lic_id(self, doc, lic_id): - """ - Add a new extracted license to the document. - Raise SPDXValueError if data format is incorrect. - """ - # FIXME: this state does not make sense - self.reset_extr_lics() - if validations.validate_extracted_lic_id(lic_id): - doc.add_extr_lic(document.ExtractedLicense(lic_id)) - return True - else: - raise SPDXValueError('ExtractedLicense::id') - - def set_lic_text(self, doc, text): - """ - Set license extracted text. - Raise SPDXValueError if text is not free form text. - Raise OrderError if no license ID defined. - """ - if self.has_extr_lic(doc): - if not self.extr_text_set: - self.extr_text_set = True - if validations.validate_is_free_form_text(text): - self.extr_lic(doc).text = str_from_text(text) - return True - else: - raise SPDXValueError('ExtractedLicense::text') - else: - raise CardinalityError('ExtractedLicense::text') - else: - raise OrderError('ExtractedLicense::text') - - def set_lic_name(self, doc, name): - """ - Set license name. - Raise SPDXValueError if name is not str or utils.NoAssert - Raise OrderError if no license id defined. - """ - if self.has_extr_lic(doc): - if not self.extr_lic_name_set: - self.extr_lic_name_set = True - if validations.validate_extr_lic_name(name): - self.extr_lic(doc).full_name = name - return True - else: - raise SPDXValueError('ExtractedLicense::Name') - else: - raise CardinalityError('ExtractedLicense::Name') - else: - raise OrderError('ExtractedLicense::Name') - - def set_lic_comment(self, doc, comment): - """ - Set license comment. - Raise SPDXValueError if comment is not free form text. - Raise OrderError if no license ID defined. - """ - if self.has_extr_lic(doc): - if not self.extr_lic_comment_set: - self.extr_lic_comment_set = True - if validations.validate_is_free_form_text(comment): - self.extr_lic(doc).comment = str_from_text(comment) - return True - else: - raise SPDXValueError('ExtractedLicense::comment') - else: - raise CardinalityError('ExtractedLicense::comment') - else: - raise OrderError('ExtractedLicense::comment') - - def add_lic_xref(self, doc, ref): - """ - Add a license cross reference. - Raise OrderError if no License ID defined. - """ - if self.has_extr_lic(doc): - self.extr_lic(doc).add_xref(ref) - return True - else: - raise OrderError('ExtractedLicense::CrossRef') - - def reset_extr_lics(self): - # FIXME: this state does not make sense - self.extr_text_set = False - self.extr_lic_name_set = False - self.extr_lic_comment_set = False - - -class SnippetBuilder(object): - - def __init__(self): - # FIXME: this state does not make sense - self.reset_snippet() - - def create_snippet(self, doc, spdx_id): - """ - Create a snippet for the SPDX Document. - spdx_id - To uniquely identify any element in an SPDX document which - may be referenced by other elements. - Raise SPDXValueError if the data is a malformed value. - """ - self.reset_snippet() - spdx_id = spdx_id.split('#')[-1] - if validations.validate_snippet_spdx_id(spdx_id): - doc.add_snippet(snippet.Snippet(spdx_id=spdx_id)) - self.snippet_spdx_id_set = True - return True - else: - raise SPDXValueError('Snippet::SnippetSPDXID') - - def set_snippet_name(self, doc, name): - """ - Set name of the snippet. - Raise OrderError if no snippet previously defined. - Raise CardinalityError if the name is already set. - """ - self.assert_snippet_exists() - if not self.snippet_name_set: - self.snippet_name_set = True - doc.snippet[-1].name = name - return True - else: - raise CardinalityError('SnippetName') - - def set_snippet_comment(self, doc, comment): - """ - Set general comments about the snippet. - Raise OrderError if no snippet previously defined. - Raise SPDXValueError if the data is a malformed value. - Raise CardinalityError if comment already set. - """ - self.assert_snippet_exists() - if not self.snippet_comment_set: - self.snippet_comment_set = True - if validations.validate_snip_comment(comment): - doc.snippet[-1].comment = str_from_text(comment) - return True - else: - raise SPDXValueError('Snippet::SnippetComment') - else: - raise CardinalityError('Snippet::SnippetComment') - - def set_snippet_copyright(self, doc, text): - """Set the snippet's copyright text. - Raise OrderError if no snippet previously defined. - Raise CardinalityError if already set. - Raise SPDXValueError if text is not one of [None, NOASSERT, TEXT]. - """ - self.assert_snippet_exists() - if not self.snippet_copyright_set: - self.snippet_copyright_set = True - if validations.validate_snippet_copyright(text): - if isinstance(text, string_types): - doc.snippet[-1].copyright = str_from_text(text) - else: - doc.snippet[-1].copyright = text # None or NoAssert - else: - raise SPDXValueError('Snippet::SnippetCopyrightText') - else: - raise CardinalityError('Snippet::SnippetCopyrightText') - - def set_snippet_lic_comment(self, doc, text): - """ - Set the snippet's license comment. - Raise OrderError if no snippet previously defined. - Raise CardinalityError if already set. - Raise SPDXValueError if the data is a malformed value. - """ - self.assert_snippet_exists() - if not self.snippet_lic_comment_set: - self.snippet_lic_comment_set = True - if validations.validate_snip_lic_comment(text): - doc.snippet[-1].license_comment = str_from_text(text) - return True - else: - raise SPDXValueError('Snippet::SnippetLicenseComments') - else: - raise CardinalityError('Snippet::SnippetLicenseComments') - - def set_snip_from_file_spdxid(self, doc, snip_from_file_spdxid): - """ - Set the snippet's 'Snippet from File SPDX Identifier'. - Raise OrderError if no snippet previously defined. - Raise CardinalityError if already set. - Raise SPDXValueError if the data is a malformed value. - """ - self.assert_snippet_exists() - snip_from_file_spdxid = snip_from_file_spdxid.split('#')[-1] - if not self.snip_file_spdxid_set: - self.snip_file_spdxid_set = True - if validations.validate_snip_file_spdxid(snip_from_file_spdxid): - doc.snippet[-1].snip_from_file_spdxid = snip_from_file_spdxid - return True - else: - raise SPDXValueError('Snippet::SnippetFromFileSPDXID') - else: - raise CardinalityError('Snippet::SnippetFromFileSPDXID') - - def set_snip_concluded_license(self, doc, conc_lics): - """ - Raise OrderError if no snippet previously defined. - Raise CardinalityError if already set. - Raise SPDXValueError if the data is a malformed value. - """ - self.assert_snippet_exists() - if not self.snippet_conc_lics_set: - self.snippet_conc_lics_set = True - if validations.validate_lics_conc(conc_lics): - doc.snippet[-1].conc_lics = conc_lics - return True - else: - raise SPDXValueError('Snippet::SnippetLicenseConcluded') - else: - raise CardinalityError('Snippet::SnippetLicenseConcluded') - - def set_snippet_lics_info(self, doc, lics_info): - """ - Raise OrderError if no snippet previously defined. - Raise SPDXValueError if the data is a malformed value. - """ - self.assert_snippet_exists() - if validations.validate_snip_lics_info(lics_info): - doc.snippet[-1].add_lics(lics_info) - return True - else: - raise SPDXValueError('Snippet::LicenseInfoInSnippet') - - def reset_snippet(self): - # FIXME: this state does not make sense - self.snippet_spdx_id_set = False - self.snippet_name_set = False - self.snippet_comment_set = False - self.snippet_copyright_set = False - self.snippet_lic_comment_set = False - self.snip_file_spdxid_set = False - self.snippet_conc_lics_set = False - - def assert_snippet_exists(self): - if not self.snippet_spdx_id_set: - raise OrderError('Snippet') - - -class Builder(DocBuilder, CreationInfoBuilder, EntityBuilder, ReviewBuilder, - PackageBuilder, FileBuilder, LicenseBuilder, SnippetBuilder, - ExternalDocumentRefBuilder, AnnotationBuilder): - - """ - SPDX document builder. - """ - - def __init__(self): - super(Builder, self).__init__() - # FIXME: this state does not make sense - self.reset() - - def reset(self): - """ - Reset builder's state for building new documents. - Must be called between usage with different documents. - """ - # FIXME: this state does not make sense - self.reset_creation_info() - self.reset_document() - self.reset_package() - self.reset_file_stat() - self.reset_reviews() - self.reset_annotations() - self.reset_extr_lics() - self.reset_snippet() diff --git a/spdx/parsers/validations.py b/spdx/parsers/validations.py deleted file mode 100644 index 8084f88cd..000000000 --- a/spdx/parsers/validations.py +++ /dev/null @@ -1,319 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import re - -import rdflib -import six - -from spdx import creationinfo -from spdx import utils -from spdx import document - - -def validate_is_free_form_text(value, optional=False): - TEXT_RE = re.compile(r'(.|\n)*', re.UNICODE) - if value is None: - return optional - else: - return TEXT_RE.match(value) is not None - - -def validate_tool_name(value, optional=False): - striped_value = value.strip() - if optional: - if len(striped_value) == 0: - return True - else: - return False - else: - return not (len(striped_value) == 0) - - -def validate_person_name(value, optional=False): - return validate_tool_name(value, optional) - - -def validate_org_name(value, optional=False): - return validate_tool_name(value, optional) - - -def validate_data_lics(value): - return value == 'CC0-1.0' - - -def validate_doc_name(value, optional=False): - return validate_tool_name(value, optional) - - -def validate_pkg_supplier(value, optional=False): - if optional and value is None: - return True - elif isinstance(value, (utils.NoAssert, creationinfo.Person, creationinfo.Organization)): - return True - else: - return False - - -def validate_pkg_originator(value, optional=False): - return validate_pkg_supplier(value, optional) - - -def validate_pkg_homepage(value, optional=False): - if value is None: - return optional - elif isinstance(value, (six.string_types, utils.NoAssert, utils.SPDXNone)): - return True - else: - return False - - -def validate_pkg_cr_text(value, optional=False): - if isinstance(value, (utils.NoAssert, utils.SPDXNone)): - return True - elif validate_is_free_form_text(value, optional): - return True - elif value is None: - return optional - else: - return False - - -def validate_pkg_summary(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_pkg_desc(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_pkg_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_pkg_ext_ref_category(value, optional=False): - if value.upper() in ['SECURITY', 'OTHER', 'PACKAGE-MANAGER']: - return True - else: - return False - - -def validate_pkg_ext_ref_type(value, optional=False): - if re.match(r'^[A-Za-z0-9.\-]+$', value) is not None: - return True - else: - return False - - -def validate_pkg_ext_ref_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_doc_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_doc_spdx_id(value, optional=False): - if value is None: - return optional - elif value.endswith('#SPDXRef-DOCUMENT'): - return True - else: - return False - - -def validate_doc_namespace(value, optional=False): - if value is None: - return optional - elif ((value.startswith('http://') or value.startswith( - 'https://') or - value.startswith('ftp://')) and ('#' not in value)): - return True - else: - return False - - -def validate_creator(value, optional=False): - if value is None: - return optional - else: - return isinstance(value, creationinfo.Creator) - - -def validate_creation_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_reviewer(value, optional=False): - return validate_creator(value, optional) - - -def validate_review_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_annotator(value, optional=False): - return validate_creator(value, optional) - - -def validate_annotation_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_annotation_type(value, optional=False): - value = value.strip() - if value == 'REVIEW' or value == 'OTHER': - return True - else: - return False - - -def validate_pkg_spdx_id(value, optional=False): - value = value.split('#')[-1] - TEXT_RE = re.compile(r'SPDXRef-([A-Za-z0-9\.\-]+)', re.UNICODE) - if value is None: - return optional - else: - return TEXT_RE.match(value) is not None - - -def validate_pkg_files_analyzed(value, optional=False): - if value in ['True', 'true', 'False', 'false']: - return True - else: - return optional - - -def validate_pkg_src_info(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_pkg_lics_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_file_spdx_id(value, optional=False): - value = value.split('#')[-1] - TEXT_RE = re.compile(r'SPDXRef-([A-Za-z0-9.\-]+)', re.UNICODE) - if value is None: - return optional - else: - return TEXT_RE.match(value) is not None - - -def validate_file_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_file_lics_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_file_cpyright(value, optional=False): - if isinstance(value, (utils.NoAssert, utils.SPDXNone)): - return True - elif validate_is_free_form_text(value, optional): - return True - else: - return False - - -def validate_lics_from_file(value, optional=False): - if value is None: - return optional - elif isinstance(value, (document.License, utils.SPDXNone, utils.NoAssert)): - return True - else: - return False - -def validate_file_notice(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_lics_conc(value, optional=False): - if value is None: - return optional - elif isinstance(value, (utils.NoAssert, utils.SPDXNone, document.License)): - return True - else: - return False - - -def validate_file_lics_in_file(value, optional=False): - if value is None: - return optional - elif isinstance(value, (utils.NoAssert, utils.SPDXNone, document.License)): - return True - else: - return False - - -def validate_extracted_lic_id(value, optional=False): - if value is None: - return optional - else: - return value.startswith('LicenseRef-') - - -def validate_extr_lic_name(value, optional=False): - if value is None: - return optional - else: - return isinstance(value, (six.string_types, utils.NoAssert, rdflib.Literal)) - - -def validate_snippet_spdx_id(value, optional=False): - value = value.split('#')[-1] - if re.match(r'^SPDXRef[A-Za-z0-9.\-]+$', value) is not None: - return True - else: - return False - - -def validate_snip_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_snippet_copyright(value, optional=False): - if validate_is_free_form_text(value, optional): - return True - elif isinstance(value, (utils.NoAssert, utils.SPDXNone)): - return True - elif value is None: - return optional - else: - return False - - -def validate_snip_lic_comment(value, optional=False): - return validate_is_free_form_text(value, optional) - - -def validate_snip_file_spdxid(value, optional=False): - if re.match( - r'(DocumentRef[A-Za-z0-9.\-]+:){0,1}SPDXRef[A-Za-z0-9.\-]+', value) is not None: - return True - else: - return False - - -def validate_snip_lics_info(value, optional=False): - if value is None: - return optional - elif isinstance(value, (utils.NoAssert, utils.SPDXNone, document.License)): - return True - else: - return False diff --git a/spdx/parsers/xmlparser.py b/spdx/parsers/xmlparser.py deleted file mode 100644 index df3e16b85..000000000 --- a/spdx/parsers/xmlparser.py +++ /dev/null @@ -1,64 +0,0 @@ - -# Copyright (c) Xavier Figueroa -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from collections import OrderedDict - -import xmltodict - -from spdx.parsers import jsonyamlxml - - -class Parser(jsonyamlxml.Parser): - """ - Wrapper class for jsonyamlxml.Parser to provide an interface similar to - RDF and TV Parser classes (i.e., spdx.parsers..Parser) for XML parser. - It also avoids to repeat jsonyamlxml.Parser.parse code for JSON, YAML and XML parsers - """ - def __init__(self, builder, logger): - super(Parser, self).__init__(builder, logger) - self.LIST_LIKE_FIELDS = { - 'creators', 'externalDocumentRefs', 'extractedLicenseInfos', - 'seeAlso', 'annotations', 'snippets', 'licenseInfoFromSnippet', 'reviewers', 'fileTypes', - 'licenseInfoFromFiles', 'artifactOf', 'fileContributors', 'fileDependencies', - 'excludedFilesNames', 'files', 'documentDescribes' - } - - def parse(self, file): - parsed_xml = xmltodict.parse(file.read(), strip_whitespace=False, encoding='utf-8') - fixed_object = self._set_in_list(parsed_xml, self.LIST_LIKE_FIELDS) - self.document_object = fixed_object.get('SpdxDocument').get('Document') - return super(Parser, self).parse() - - def _set_in_list(self, data, keys): - """ - xmltodict parse list-like fields in different way when there is only one - of them than when there are several of them. - Set in lists those fields that are expected to be in them. - """ - if isinstance(data, (dict, OrderedDict)): - new_data = OrderedDict() - for k, v in data.items(): - if k in keys and not isinstance(v, list): - new_data[k] = [self._set_in_list(v, keys)] - else: - new_data[k] = self._set_in_list(v, keys) - return new_data - elif isinstance(data, list): - new_data = [] - for element in data: - new_data.append(self._set_in_list(element, keys)) - return new_data - return data diff --git a/spdx/parsers/yamlparser.py b/spdx/parsers/yamlparser.py deleted file mode 100644 index 8fc6cb208..000000000 --- a/spdx/parsers/yamlparser.py +++ /dev/null @@ -1,33 +0,0 @@ - -# Copyright (c) Xavier Figueroa -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import yaml - -from spdx.parsers import jsonyamlxml - - -class Parser(jsonyamlxml.Parser): - """ - Wrapper class for jsonyamlxml.Parser to provide an interface similar to - RDF and TV Parser classes (i.e., spdx.parsers..Parser) for YAML parser. - It also avoids to repeat jsonyamlxml.Parser.parse code for JSON, YAML and XML parsers - """ - def __init__(self, builder, logger): - super(Parser, self).__init__(builder, logger) - - def parse(self, file): - self.document_object = yaml.safe_load(file).get('Document') - return super(Parser, self).parse() diff --git a/spdx/review.py b/spdx/review.py deleted file mode 100644 index ae7a1b597..000000000 --- a/spdx/review.py +++ /dev/null @@ -1,83 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from datetime import datetime -from functools import total_ordering - -from spdx.utils import datetime_iso_format - - -@total_ordering -class Review(object): - - """ - Document review information. - Fields: - - reviewer: Person, Organization or tool that reviewed the SPDX file. - Mandatory one. - - review_date: Review date, mandatory one. Type: datetime. - - comment: Review comment. Optional one. Type: str. - """ - - def __init__(self, reviewer=None, review_date=None, comment=None): - self.reviewer = reviewer - self.review_date = review_date - self.comment = comment - - def __eq__(self, other): - return ( - isinstance(other, Review) and self.reviewer == other.reviewer - and self.review_date == other.review_date - and self.comment == other.comment - ) - - def __lt__(self, other): - return ( - (self.reviewer, self.review_date, self.comment) < - (other.reviewer, other.review_date, other.comment,) - ) - - def set_review_date_now(self): - self.review_date = datetime.utcnow() - - @property - def review_date_iso_format(self): - return datetime_iso_format(self.review_date) - - @property - def has_comment(self): - return self.comment is not None - - def validate(self, messages): - """Returns True if all the fields are valid. - Appends any error messages to messages parameter. - """ - messages = self.validate_reviewer(messages) - messages = self.validate_review_date(messages) - - return messages - - def validate_reviewer(self, messages): - if self.reviewer is None: - messages = messages + ['Review missing reviewer.'] - - return messages - - def validate_review_date(self, messages): - if self.review_date is None: - messages = messages + ['Review missing review date.'] - - return messages diff --git a/spdx/snippet.py b/spdx/snippet.py deleted file mode 100644 index 099c6c4ea..000000000 --- a/spdx/snippet.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright (c) 2018 Yash M. Nisar -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import six - -from spdx import document -from spdx import utils - - -class Snippet(object): - """ - Represents an analyzed snippet. - Fields: - - spdx_id: Uniquely identify any element in an SPDX document which may be - referenced by other elements. Mandatory, one per snippet if the snippet - is present. - - name: Name of the snippet. Optional, one. Type: str. - - comment: General comments about the snippet. Optional, one. Type: str. - - copyright: Copyright text. Mandatory, one. Type: str. - - license_comment: Relevant background references or analysis that went - in to arriving at the Concluded License for a snippet. Optional, one. - - snip_from_file_spdxid: Uniquely identify the file in an SPDX document - which this snippet is associated with. Mandatory, one. Type: str. - Type: str. - - conc_lics: Contains the license the SPDX file creator has concluded as - governing the snippet or alternative values if the governing license - cannot be determined. Mandatory one. Type: document.License or - utils.NoAssert or utils.SPDXNone. - - licenses_in_snippet: The list of licenses found in the snippet. - Mandatory, one or more. Type: document.License or utils.SPDXNone or - utils.NoAssert. - """ - - def __init__(self, spdx_id=None, copyright=None, - snip_from_file_spdxid=None, conc_lics=None): - self.spdx_id = spdx_id - self.name = None - self.comment = None - self.copyright = copyright - self.license_comment = None - self.snip_from_file_spdxid = snip_from_file_spdxid - self.conc_lics = conc_lics - self.licenses_in_snippet = [] - - def add_lics(self, lics): - self.licenses_in_snippet.append(lics) - - def validate(self, messages=None): - """ - Validate fields of the snippet and update the messages list with user - friendly error messages for display. - """ - messages = self.validate_spdx_id(messages) - messages = self.validate_copyright_text(messages) - messages = self.validate_snip_from_file_spdxid(messages) - messages = self.validate_concluded_license(messages) - messages = self.validate_licenses_in_snippet(messages) - - return messages - - def validate_spdx_id(self, messages=None): - if self.spdx_id is None: - messages = messages + ['Snippet has no SPDX Identifier.'] - - return messages - - def validate_copyright_text(self, messages=None): - if not isinstance( - self.copyright, - (six.string_types, six.text_type, utils.NoAssert, - utils.SPDXNone)): - messages = messages + [ - 'Snippet copyright must be str or unicode or utils.NoAssert or utils.SPDXNone' - ] - - return messages - - def validate_snip_from_file_spdxid(self, messages=None): - if self.snip_from_file_spdxid is None: - messages = messages + ['Snippet has no Snippet from File SPDX Identifier.'] - - return messages - - def validate_concluded_license(self, messages=None): - if not isinstance(self.conc_lics, (document.License, utils.NoAssert, - utils.SPDXNone)): - messages = messages + [ - 'Snippet Concluded License must be one of ' - 'document.License, utils.NoAssert or utils.SPDXNone' - ] - - return messages - - def validate_licenses_in_snippet(self, messages=None): - if len(self.licenses_in_snippet) == 0: - messages = messages + ['Snippet must have at least one license in file.'] - else: - for lic in self.licenses_in_snippet: - if not isinstance(lic, (document.License, utils.NoAssert, - utils.SPDXNone)): - messages = messages + [ - 'Licenses in Snippet must be one of ' - 'document.License, utils.NoAssert or utils.SPDXNone' - ] - - return messages - - def has_optional_field(self, field): - return getattr(self, field, None) is not None diff --git a/spdx/tv_to_rdf.py b/spdx/tv_to_rdf.py deleted file mode 100755 index aba71553a..000000000 --- a/spdx/tv_to_rdf.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2017 BMW AG -# Author: Thomas Hafner -# -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import sys - -from spdx.parsers.loggers import StandardLogger -from spdx.writers.rdf import write_document -from spdx.parsers.tagvalue import Parser -from spdx.parsers.tagvaluebuilders import Builder - - -def tv_to_rdf(infile_name, outfile_name): - """ - Convert a SPDX file from tag/value format to RDF format. - Return True on sucess, False otherwise. - """ - parser = Parser(Builder(), StandardLogger()) - parser.build() - with open(infile_name) as infile: - data = infile.read() - document, error = parser.parse(data) - if not error: - with open(outfile_name, mode='w') as outfile: - write_document(document, outfile) - return True - else: - print('Errors encountered while parsing RDF file.') - messages = [] - document.validate(messages) - print('\n'.join(messages)) - return False - - -def main(): - args = sys.argv[1:] - if not args: - print( - 'Usage: spdx-tv2rdf \n' - 'Convert an SPDX tag/value document to RDF.' - ) - sys.exit(1) - - tvfile = args[0] - rdffile = args[1] - success = tv_to_rdf(tvfile, rdffile) - sys.exit(0 if success else 1) - - -if __name__ == '__main__': - main() diff --git a/spdx/utils.py b/spdx/utils.py deleted file mode 100644 index 3e5c16972..000000000 --- a/spdx/utils.py +++ /dev/null @@ -1,197 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import datetime -import re - -from ply import lex -from ply import yacc - -from spdx import document - - -def datetime_iso_format(date): - """ - Return an ISO-8601 representation of a datetime object. - """ - return "{0:0>4}-{1:0>2}-{2:0>2}T{3:0>2}:{4:0>2}:{5:0>2}Z".format( - date.year, date.month, date.day, date.hour, - date.minute, date.second) - - -# Matches an iso 8601 date representation -DATE_ISO_REGEX = re.compile( - r'(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z', re.UNICODE) - - -# Groups for retrivieng values from DATE_ISO_REGEX matches. -DATE_ISO_YEAR_GRP = 1 -DATE_ISO_MONTH_GRP = 2 -DATE_ISO_DAY_GRP = 3 -DATE_ISO_HOUR_GRP = 4 -DATE_ISO_MIN_GRP = 5 -DATE_ISO_SEC_GRP = 6 - - -def datetime_from_iso_format(string): - """ - Return a datetime object from an iso 8601 representation. - Return None if string is non conforming. - """ - match = DATE_ISO_REGEX.match(string) - if match: - date = datetime.datetime(year=int(match.group(DATE_ISO_YEAR_GRP)), - month=int(match.group(DATE_ISO_MONTH_GRP)), - day=int(match.group(DATE_ISO_DAY_GRP)), - hour=int(match.group(DATE_ISO_HOUR_GRP)), - second=int(match.group(DATE_ISO_SEC_GRP)), - minute=int(match.group(DATE_ISO_MIN_GRP))) - return date - else: - return None - - -class NoAssert(object): - """ - Represent SPDX NOASSERTION value. - """ - def to_value(self): - return 'NOASSERTION' - - def __str__(self): - return self.to_value() - - -class UnKnown(object): - """ - Represent SPDX UNKNOWN value. - """ - def to_value(self): - return 'UNKNOWN' - - def __str__(self): - return self.to_value() - -class SPDXNone(object): - """ - Represent SPDX None value. - """ - def to_value(self): - return 'NONE' - - def __str__(self): - return self.to_value() - - -class LicenseListLexer(object): - - tokens = ['LP', 'RP', 'AND', 'OR', 'LICENSE'] - - def t_LP(self, t): - r'\(' - return t - - def t_RP(self, t): - r'\)' - return t - - def t_AND(self, t): - r'\s(and|AND)\s' - t.value = t.value.strip() - return t - - def t_OR(self, t): - r'\s(or|OR)\s' - t.value = t.value.strip() - return t - - def t_whitespace(self, t): - r'\s+' - pass - - def t_LICENSE(self, t): - r'[A-Za-z.0-9\-+]+' - t.value = t.value.strip() - return t - - def t_error(self, t): - pass - - def input(self, data): - """Set input, data - str.""" - self.lexer.input(data) - - def token(self): - """Get the next token or None if exhausted input.""" - return self.lexer.token() - - def build(self, **kwargs): - """Build lexer, must be called before input or token methods. - Only need to build once. - """ - self.lexer = lex.lex(module=self, **kwargs) - - -class LicenseListParser(object): - - def __init__(self): - self.lex = LicenseListLexer() - self.lex.build(reflags=re.UNICODE) - self.tokens = self.lex.tokens - - def p_disjunction_1(self, p): - """disjunction : disjunction OR conjunction - """ - p[0] = document.LicenseDisjunction(p[1], p[3]) - - def p_disjunction_2(self, p): - """disjunction : conjunction - """ - p[0] = p[1] - - def p_conjunction_1(self, p): - """conjunction : conjunction AND license_atom - """ - p[0] = document.LicenseConjunction(p[1], p[3]) - - def p_conjunction_2(self, p): - """conjunction : license_atom - """ - p[0] = p[1] - - def p_license_atom_1(self, p): - """license_atom : LICENSE - """ - p[0] = document.License.from_identifier(p[1]) - - def p_license_atom_2(self, p): - """license_atom : LP disjunction RP - """ - p[0] = p[2] - - def p_error(self, p): - pass - - def build(self, **kwargs): - """Must be called before parse.""" - self.yacc = yacc.yacc(module=self, **kwargs) - - def parse(self, data): - """Parses a license list and returns a License or None if it failed.""" - try: - return self.yacc.parse(data, lexer=self.lex) - except: - return None diff --git a/spdx/version.py b/spdx/version.py deleted file mode 100644 index 3ec92cc39..000000000 --- a/spdx/version.py +++ /dev/null @@ -1,62 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from functools import total_ordering -import re - - -@total_ordering -class Version(object): - """ - Version number composed of major and minor. - Fields: - - major: Major number, int. - - minor: Minor number, int. - """ - VERS_STR_REGEX = re.compile(r'(\d+)\.(\d+)') - - def __init__(self, major, minor): - self.major = int(major) - self.minor = int(minor) - - @classmethod - def from_str(cls, value): - """Constructs a Version from a string. - Returns None if string not in N.N form where N represents a - number. - """ - m = cls.VERS_STR_REGEX.match(value) - if m is not None: - return cls(int(m.group(1)), int(m.group(2))) - else: - return None - - def __repr__(self): - return 'Version' + repr((self.major, self.minor)) - - def __str__(self): - return 'SPDX-{major}.{minor}'.format(**self.__dict__) - - def __eq__(self, other): - return ( - isinstance(other, self.__class__) and - self.major == other.major and - self.minor == other.minor - ) - - def __lt__(self, other): - return (self.major < other.major - or (self.major == other.major and self.minor < other.minor)) diff --git a/spdx/writers/json.py b/spdx/writers/json.py deleted file mode 100644 index 03833a62c..000000000 --- a/spdx/writers/json.py +++ /dev/null @@ -1,33 +0,0 @@ - -# Copyright (c) Xavier Figueroa -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import json - -from spdx.writers.tagvalue import InvalidDocumentError -from spdx.writers.jsonyamlxml import Writer - - -def write_document(document, out, validate=True): - - if validate: - messages = [] - messages = document.validate(messages) - if messages: - raise InvalidDocumentError(messages) - - writer = Writer(document) - document_object = writer.create_document() - json.dump(document_object, out, indent=4) diff --git a/spdx/writers/jsonyamlxml.py b/spdx/writers/jsonyamlxml.py deleted file mode 100644 index fbcd19379..000000000 --- a/spdx/writers/jsonyamlxml.py +++ /dev/null @@ -1,407 +0,0 @@ - -# Copyright (c) Xavier Figueroa -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from rdflib import Literal - -from spdx import document - - -class BaseWriter(object): - """ - Base class for all Writer classes. - Provide utility functions and stores shared fields. - - document: spdx.document class. Source of data to be written - - document_object: python dictionary representation of the entire spdx.document - """ - - def __init__(self, document): - self.document = document - self.document_object = dict() - - def license(self, license_field): - """ - Return a string representation of a license or spdx.utils special object - """ - if isinstance(license_field, (document.LicenseDisjunction, document.LicenseConjunction)): - return '({})'.format(license_field) - - if isinstance(license_field, document.License): - license_str = license_field.identifier.__str__() - else: - license_str = license_field.__str__() - return license_str - - def checksum(self, checksum_field): - """ - Return a dictionary representation of a spdx.checksum.Algorithm object - """ - checksum_object = dict() - checksum_object['algorithm'] = 'checksumAlgorithm_' + checksum_field.identifier.lower() - checksum_object['value'] = checksum_field.value - return checksum_object - - def spdx_id(self, spdx_id_field): - return spdx_id_field.__str__().split('#')[-1] - -class CreationInfoWriter(BaseWriter): - """ - Represent spdx.creationinfo as json-serializable objects - """ - - def __init__(self, document): - super(CreationInfoWriter, self).__init__(document) - - def create_creation_info(self): - creation_info_object = dict() - creation_info = self.document.creation_info - creation_info_object['creators'] = list(map(str, creation_info.creators)) - creation_info_object['created'] = creation_info.created_iso_format - - if creation_info.license_list_version: - creation_info_object['licenseListVersion'] = '{0}.{1}'.format(creation_info.license_list_version.major, creation_info.license_list_version.minor) - - if creation_info.has_comment: - creation_info_object['comment'] = creation_info.comment - - return creation_info_object - -class PackageWriter(BaseWriter): - """ - Represent spdx.package as python objects - """ - - def __init__(self, document): - super(PackageWriter, self).__init__(document) - - def package_verification_code(self, package): - """ - Represent the package verification code information as - as python dictionary - """ - - package_verification_code_object = dict() - - package_verification_code_object['value'] = package.verif_code - - if package.verif_exc_files: - package_verification_code_object['excludedFilesNames'] = package.verif_exc_files - - return package_verification_code_object - - def create_package_info(self): - package_object = dict() - package = self.document.package - package_object['id'] = self.spdx_id(package.spdx_id) - package_object['name'] = package.name - package_object['downloadLocation'] = package.download_location.__str__() - package_object['packageVerificationCode'] = self.package_verification_code(package) - package_object['licenseConcluded'] = self.license(package.conc_lics) - package_object['licenseInfoFromFiles'] = list(map(self.license, package.licenses_from_files)) - package_object['licenseDeclared'] = self.license(package.license_declared) - package_object['copyrightText'] = package.cr_text.__str__() - - if package.has_optional_field('version'): - package_object['versionInfo'] = package.version - - if package.has_optional_field('summary'): - package_object['summary'] = package.summary - - if package.has_optional_field('source_info'): - package_object['sourceInfo'] = package.source_info - - if package.has_optional_field('file_name'): - package_object['packageFileName'] = package.file_name - - if package.has_optional_field('supplier'): - package_object['supplier'] = package.supplier.__str__() - - if package.has_optional_field('originator'): - package_object['originator'] = package.originator.__str__() - - if package.has_optional_field('check_sum'): - package_object['checksums'] = [self.checksum(package.check_sum)] - package_object['sha1'] = package.check_sum.value - - if package.has_optional_field('description'): - package_object['description'] = package.description - - if package.has_optional_field('license_comment'): - package_object['licenseComments'] = package.license_comment - - if package.has_optional_field('homepage'): - package_object['homepage'] = package.homepage.__str__() - - return package_object - -class FileWriter(BaseWriter): - """ - Represent spdx.file as json-serializable objects - """ - - def __init__(self, document): - super(FileWriter, self).__init__(document) - - def create_artifact_info(self, file): - """ - Create the artifact json-serializable representation from a spdx.file.File object - """ - artifact_of_objects = [] - - for i in range(len(file.artifact_of_project_name)): - artifact_of_object = dict() - artifact_of_object['name'] = file.artifact_of_project_name[i].__str__() - artifact_of_object['homePage'] = file.artifact_of_project_home[i].__str__() - artifact_of_object['projectUri'] = file.artifact_of_project_uri[i].__str__() - artifact_of_objects.append(artifact_of_object) - - return artifact_of_objects - - def create_file_info(self): - file_types = { 1: 'fileType_source', 2: 'fileType_binary', 3: 'fileType_archive', 4: 'fileType_other'} - file_objects = [] - files = self.document.files - - for file in files: - file_object = dict() - - file_object['name'] = file.name - file_object['id'] = self.spdx_id(file.spdx_id) - file_object['checksums'] = [self.checksum(file.chk_sum)] - file_object['licenseConcluded'] = self.license(file.conc_lics) - file_object['licenseInfoFromFiles'] = list(map(self.license, file.licenses_in_file)) - file_object['copyrightText'] = file.copyright.__str__() - file_object['sha1'] = file.chk_sum.value - - if file.has_optional_field('comment'): - file_object['comment'] = file.comment - - if file.has_optional_field('type'): - file_object['fileTypes'] = [file_types.get(file.type)] - - if file.has_optional_field('license_comment'): - file_object['licenseComments'] = file.license_comment - - if file.has_optional_field('notice'): - file_object['noticeText'] = file.notice - - if file.contributors: - file_object['fileContributors'] = file.contributors.__str__() - - if file.dependencies: - file_object['fileDependencies'] = file.dependencies - - valid_artifacts = file.artifact_of_project_name and len(file.artifact_of_project_name) == len(file.artifact_of_project_home) and len(file.artifact_of_project_home) == len(file.artifact_of_project_uri) - - if valid_artifacts: - file_object['artifactOf'] = self.create_artifact_info(file) - - file_objects.append({"File": file_object}) - - return file_objects - -class ReviewInfoWriter(BaseWriter): - """ - Represent spdx.review as json-serializable objects - """ - - def __init__(self, document): - super(ReviewInfoWriter, self).__init__(document) - - def create_review_info(self): - review_info_objects = [] - reviews = self.document.reviews - - for review in reviews: - review_object = dict() - review_object['reviewer'] = review.reviewer.__str__() - review_object['reviewDate'] = review.review_date_iso_format - if review.has_comment: - review_object['comment'] = review.comment - - review_info_objects.append(review_object) - - return review_info_objects - -class AnnotationInfoWriter(BaseWriter): - """ - Represent spdx.annotation as json-serializable objects - """ - - def __init__(self, document): - super(AnnotationInfoWriter, self).__init__(document) - - def create_annotation_info(self): - """ - The way how tools-python manages its models makes difficult to classify - annotations (by document, files and packages) and some of them could end up omitted. - This method sets every annotation as part of the spdx document itself, - avoiding them to be omitted. - """ - annotation_objects = [] - - for annotation in self.document.annotations: - annotation_object = dict() - annotation_object['id'] = self.spdx_id(annotation.spdx_id) - annotation_object['annotator'] = annotation.annotator.__str__() - annotation_object['annotationDate'] = annotation.annotation_date_iso_format - annotation_object['annotationType'] = annotation.annotation_type - annotation_object['comment'] = annotation.comment - - annotation_objects.append(annotation_object) - - return annotation_objects - -class SnippetWriter(BaseWriter): - """ - Represent spdx.annotation as json-serializable objects - """ - def __init__(self, document): - super(SnippetWriter, self).__init__(document) - - def create_snippet_info(self): - snippet_info_objects = [] - snippets = self.document.snippet - - for snippet in snippets: - snippet_object = dict() - snippet_object['id'] = self.spdx_id(snippet.spdx_id) - snippet_object['copyrightText'] = snippet.copyright - snippet_object['fileId'] = self.spdx_id(snippet.snip_from_file_spdxid) - snippet_object['licenseConcluded'] = self.license(snippet.conc_lics) - snippet_object['licenseInfoFromSnippet'] = list(map(self.license, snippet.licenses_in_snippet)) - - if snippet.has_optional_field('name'): - snippet_object['name'] = snippet.name - - if snippet.has_optional_field('comment'): - snippet_object['comment'] = snippet.comment - - if snippet.has_optional_field('license_comment'): - snippet_object['licenseComments'] = snippet.license_comment - - snippet_info_objects.append(snippet_object) - - return snippet_info_objects - -class ExtractedLicenseWriter(BaseWriter): - """ - Represent spdx.document.ExtractedLicense as json-serializable objects - """ - - def __init__(self, document): - super(ExtractedLicenseWriter, self).__init__(document) - - def create_extracted_license(self): - extracted_license_objects = [] - extracted_licenses = self.document.extracted_licenses - - for extracted_license in extracted_licenses: - extracted_license_object = dict() - - if isinstance(extracted_license.identifier, Literal): - extracted_license_object['licenseId'] = extracted_license.identifier.toPython() - else: - extracted_license_object['licenseId'] = extracted_license.identifier - - if isinstance(extracted_license.text, Literal): - extracted_license_object['extractedText'] = extracted_license.text.toPython() - else: - extracted_license_object['extractedText'] = extracted_license.text - - if extracted_license.full_name: - if isinstance(extracted_license.full_name, Literal): - extracted_license_object['name'] = extracted_license.full_name.toPython() - else: - extracted_license_object['name'] = extracted_license.full_name - - if extracted_license.cross_ref: - if isinstance(extracted_license.cross_ref, Literal): - extracted_license_object['seeAlso'] = extracted_license.cross_ref.toPython() - else: - extracted_license_object['seeAlso'] = extracted_license.cross_ref - - if extracted_license.comment: - if isinstance(extracted_license.comment, Literal): - extracted_license_object['comment'] = extracted_license.comment.toPython() - else: - extracted_license_object['comment'] = extracted_license.comment - - extracted_license_objects.append(extracted_license_object) - - return extracted_license_objects - -class Writer(CreationInfoWriter, ReviewInfoWriter, FileWriter, PackageWriter, - AnnotationInfoWriter, SnippetWriter, ExtractedLicenseWriter): - """ - Wrapper for the other writers. - Represent a whole SPDX Document as json-serializable objects to then - be written as json or yaml files. - """ - - def __init__(self, document): - super(Writer, self).__init__(document) - - def create_ext_document_references(self): - """ - Create the External Document References json-serializable representation - """ - ext_document_references_field = self.document.ext_document_references - ext_document_reference_objects = [] - for ext_document_reference in ext_document_references_field: - ext_document_reference_object = dict() - ext_document_reference_object['externalDocumentId'] = ext_document_reference.external_document_id - ext_document_reference_object['spdxDocumentNamespace'] = ext_document_reference.spdx_document_uri - - ext_document_reference_object['checksum'] = self.checksum(ext_document_reference.check_sum) - - ext_document_reference_objects.append(ext_document_reference_object) - - return ext_document_reference_objects - - def create_document(self): - self.document_object = dict() - - self.document_object['specVersion'] = self.document.version.__str__() - self.document_object['namespace'] = self.document.namespace.__str__() - self.document_object['creationInfo'] = self.create_creation_info() - self.document_object['dataLicense'] = self.license(self.document.data_license) - self.document_object['id'] = self.spdx_id(self.document.spdx_id) - self.document_object['name'] = self.document.name - - package_info_object = self.create_package_info() - package_info_object['files'] = self.create_file_info() - - self.document_object['documentDescribes'] = [{'Package': package_info_object}] - - if self.document.has_comment: - self.document_object['comment'] = self.document.comment - - if self.document.ext_document_references: - self.document_object['externalDocumentRefs'] = self.create_ext_document_references() - - if self.document.extracted_licenses: - self.document_object['extractedLicenseInfos'] = self.create_extracted_license() - - if self.document.reviews: - self.document_object['reviewers'] = self.create_review_info() - - if self.document.snippet: - self.document_object['snippets'] = self.create_snippet_info() - - if self.document.annotations: - self.document_object['annotations'] = self.create_annotation_info() - - return {'Document' : self.document_object} diff --git a/spdx/writers/rdf.py b/spdx/writers/rdf.py deleted file mode 100644 index 99f031cda..000000000 --- a/spdx/writers/rdf.py +++ /dev/null @@ -1,786 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from rdflib import BNode -from rdflib import Graph -from rdflib import Literal -from rdflib import Namespace -from rdflib import RDF -from rdflib import RDFS -from rdflib import URIRef -from rdflib.compare import to_isomorphic - -from spdx import file -from spdx import document -from spdx import config -from spdx import utils -from spdx.writers.tagvalue import InvalidDocumentError - - -class BaseWriter(object): - """ - Base class for all Writer classes. - Provide utility functions and stores shared fields. - """ - - def __init__(self, document, out): - self.document = document - self.out = out - self.doap_namespace = Namespace('http://usefulinc.com/ns/doap#') - self.spdx_namespace = Namespace("http://spdx.org/rdf/terms#") - self.graph = Graph() - - def create_checksum_node(self, chksum): - """ - Return a node representing spdx.checksum. - """ - chksum_node = BNode() - type_triple = (chksum_node, RDF.type, self.spdx_namespace.Checksum) - self.graph.add(type_triple) - algorithm_triple = (chksum_node, self.spdx_namespace.algorithm, Literal(chksum.identifier)) - self.graph.add(algorithm_triple) - value_triple = (chksum_node, self.spdx_namespace.checksumValue, Literal(chksum.value)) - self.graph.add(value_triple) - return chksum_node - - def to_special_value(self, value): - """ - Return proper spdx term or Literal - """ - if isinstance(value, utils.NoAssert): - return self.spdx_namespace.noassertion - elif isinstance(value, utils.SPDXNone): - return self.spdx_namespace.none - else: - return Literal(value) - - -class LicenseWriter(BaseWriter): - """ - Handle all License classes from spdx.document module. - """ - - def __init__(self, document, out): - super(LicenseWriter, self).__init__(document, out) - - def licenses_from_tree_helper(self, current, licenses): - if (isinstance(current, (document.LicenseConjunction, - document.LicenseDisjunction))): - self.licenses_from_tree_helper(current.license_1, licenses) - self.licenses_from_tree_helper(current.license_2, licenses) - else: - licenses.add(self.create_license_helper(current)) - - def licenses_from_tree(self, tree): - """ - Traverse conjunctions and disjunctions like trees and return a - set of all licenses in it as nodes. - """ - # FIXME: this is unordered! - licenses = set() - self.licenses_from_tree_helper(tree, licenses) - return licenses - - def create_conjunction_node(self, conjunction): - """ - Return a node representing a conjunction of licenses. - """ - node = BNode() - type_triple = (node, RDF.type, self.spdx_namespace.ConjunctiveLicenseSet) - self.graph.add(type_triple) - licenses = self.licenses_from_tree(conjunction) - for lic in licenses: - member_triple = (node, self.spdx_namespace.member, lic) - self.graph.add(member_triple) - return node - - def create_disjunction_node(self, disjunction): - """ - Return a node representing a disjunction of licenses. - """ - node = BNode() - type_triple = (node, RDF.type, self.spdx_namespace.DisjunctiveLicenseSet) - self.graph.add(type_triple) - licenses = self.licenses_from_tree(disjunction) - for lic in licenses: - member_triple = (node, self.spdx_namespace.member, lic) - self.graph.add(member_triple) - return node - - def create_license_helper(self, lic): - """ - Handle single(no conjunction/disjunction) licenses. - Return the created node. - """ - if isinstance(lic, document.ExtractedLicense): - return self.create_extracted_license(lic) - if lic.identifier.rstrip('+') in config.LICENSE_MAP: - return URIRef(lic.url) - else: - matches = [l for l in self.document.extracted_licenses if l.identifier == lic.identifier] - if len(matches) != 0: - return self.create_extracted_license(matches[0]) - else: - raise InvalidDocumentError('Missing extracted license: {0}'.format(lic.identifier)) - - def create_extracted_license(self, lic): - """ - Handle extracted license. - Return the license node. - """ - licenses = list(self.graph.triples((None, self.spdx_namespace.licenseId, lic.identifier))) - if len(licenses) != 0: - return licenses[0][0] # return subject in first triple - else: - license_node = BNode() - type_triple = (license_node, RDF.type, self.spdx_namespace.ExtractedLicensingInfo) - self.graph.add(type_triple) - ident_triple = (license_node, self.spdx_namespace.licenseId, Literal(lic.identifier)) - self.graph.add(ident_triple) - text_triple = (license_node, self.spdx_namespace.extractedText, Literal(lic.text)) - self.graph.add(text_triple) - if lic.full_name is not None: - name_triple = (license_node, self.spdx_namespace.licenseName, self.to_special_value(lic.full_name)) - self.graph.add(name_triple) - for ref in lic.cross_ref: - triple = (license_node, RDFS.seeAlso, URIRef(ref)) - self.graph.add(triple) - if lic.comment is not None: - comment_triple = (license_node, RDFS.comment, Literal(lic.comment)) - self.graph.add(comment_triple) - return license_node - - def create_license_node(self, lic): - """ - Return a node representing a license. - Could be a single license (extracted or part of license list.) or - a conjunction/disjunction of licenses. - """ - if isinstance(lic, document.LicenseConjunction): - return self.create_conjunction_node(lic) - elif isinstance(lic, document.LicenseDisjunction): - return self.create_disjunction_node(lic) - else: - return self.create_license_helper(lic) - - def license_or_special(self, lic): - """ - Check for special values spdx:none and spdx:noassertion. - Return the term for the special value or the result of passing - license to create_license_node. - """ - if isinstance(lic, utils.NoAssert): - return self.spdx_namespace.noassertion - elif isinstance(lic, utils.SPDXNone): - return self.spdx_namespace.none - else: - return self.create_license_node(lic) - - -class FileWriter(LicenseWriter): - """ - Write spdx.file.File - """ - FILE_TYPES = { - file.FileType.SOURCE: 'fileType_source', - file.FileType.OTHER: 'fileType_other', - file.FileType.BINARY: 'fileType_binary', - file.FileType.ARCHIVE: 'fileType_archive' - } - - def __init__(self, document, out): - super(FileWriter, self).__init__(document, out) - - def create_file_node(self, doc_file): - """ - Create a node for spdx.file. - """ - file_node = URIRef('http://www.spdx.org/files#{id}'.format( - id=str(doc_file.spdx_id))) - type_triple = (file_node, RDF.type, self.spdx_namespace.File) - self.graph.add(type_triple) - - name_triple = (file_node, self.spdx_namespace.fileName, Literal(doc_file.name)) - self.graph.add(name_triple) - - if doc_file.has_optional_field('comment'): - comment_triple = (file_node, RDFS.comment, Literal(doc_file.comment)) - self.graph.add(comment_triple) - - if doc_file.has_optional_field('type'): - ftype = self.spdx_namespace[self.FILE_TYPES[doc_file.type]] - ftype_triple = (file_node, self.spdx_namespace.fileType, ftype) - self.graph.add(ftype_triple) - - self.graph.add((file_node, self.spdx_namespace.checksum, self.create_checksum_node(doc_file.chk_sum))) - - conc_lic_node = self.license_or_special(doc_file.conc_lics) - conc_lic_triple = (file_node, self.spdx_namespace.licenseConcluded, conc_lic_node) - self.graph.add(conc_lic_triple) - - license_info_nodes = map(self.license_or_special, doc_file.licenses_in_file) - for lic in license_info_nodes: - triple = (file_node, self.spdx_namespace.licenseInfoInFile, lic) - self.graph.add(triple) - - if doc_file.has_optional_field('license_comment'): - comment_triple = (file_node, self.spdx_namespace.licenseComments, Literal(doc_file.license_comment)) - self.graph.add(comment_triple) - - cr_text_node = self.to_special_value(doc_file.copyright) - cr_text_triple = (file_node, self.spdx_namespace.copyrightText, cr_text_node) - self.graph.add(cr_text_triple) - - if doc_file.has_optional_field('notice'): - notice_triple = (file_node, self.spdx_namespace.noticeText, doc_file.notice) - self.graph.add(notice_triple) - - contrib_nodes = map(lambda c: Literal(c), doc_file.contributors) - contrib_triples = [(file_node, self.spdx_namespace.fileContributor, node) for node in contrib_nodes] - for triple in contrib_triples: - self.graph.add(triple) - - return file_node - - def files(self): - """ - Return list of file nodes. - """ - return map(self.create_file_node, self.document.files) - - def add_file_dependencies_helper(self, doc_file): - """ - Handle dependencies for a single file. - - doc_file - instance of spdx.file.File. - """ - subj_triples = list(self.graph.triples((None, self.spdx_namespace.fileName, Literal(doc_file.name)))) - if len(subj_triples) != 1: - raise InvalidDocumentError('Could not find dependency subject {0}'.format(doc_file.name)) - subject_node = subj_triples[0][0] - for dependency in doc_file.dependencies: - dep_triples = list(self.graph.triples((None, self.spdx_namespace.fileName, Literal(dependency)))) - if len(dep_triples) == 1: - dep_node = dep_triples[0][0] - dep_triple = (subject_node, self.spdx_namespace.fileDependency, dep_node) - self.graph.add(dep_triple) - else: - print('Warning could not resolve file dependency {0} -> {1}'.format(doc_file.name, dependency)) - - def add_file_dependencies(self): - """ - Add file dependencies to the graph. - Called after all files have been added. - """ - for doc_file in self.document.files: - self.add_file_dependencies_helper(doc_file) - - -class SnippetWriter(LicenseWriter): - - """ - Write spdx.snippet.Snippet - """ - - def __init__(self, document, out): - super(SnippetWriter, self).__init__(document, out) - - def create_snippet_node(self, snippet): - """ - Return a snippet node. - """ - snippet_node = URIRef('http://spdx.org/rdf/terms/Snippet#' + snippet.spdx_id) - type_triple = (snippet_node, RDF.type, self.spdx_namespace.Snippet) - self.graph.add(type_triple) - - if snippet.has_optional_field('comment'): - comment_triple = (snippet_node, RDFS.comment, Literal(snippet.comment)) - self.graph.add(comment_triple) - - if snippet.has_optional_field('name'): - name_triple = (snippet_node, self.spdx_namespace.name, Literal(snippet.name)) - self.graph.add(name_triple) - - if snippet.has_optional_field('license_comment'): - lic_comment_triple = (snippet_node, self.spdx_namespace.licenseComments, - Literal(snippet.license_comment)) - self.graph.add(lic_comment_triple) - - cr_text_node = self.to_special_value(snippet.copyright) - cr_text_triple = (snippet_node, self.spdx_namespace.copyrightText, cr_text_node) - self.graph.add(cr_text_triple) - - snip_from_file_triple = (snippet_node, self.spdx_namespace.snippetFromFile, - Literal(snippet.snip_from_file_spdxid)) - self.graph.add(snip_from_file_triple) - - conc_lic_node = self.license_or_special(snippet.conc_lics) - conc_lic_triple = ( - snippet_node, self.spdx_namespace.licenseConcluded, conc_lic_node) - self.graph.add(conc_lic_triple) - - license_info_nodes = map(self.license_or_special, - snippet.licenses_in_snippet) - for lic in license_info_nodes: - triple = ( - snippet_node, self.spdx_namespace.licenseInfoInSnippet, lic) - self.graph.add(triple) - - return snippet_node - - def snippets(self): - """ - Return list of snippet nodes. - """ - return map(self.create_snippet_node, self.document.snippet) - - -class ReviewInfoWriter(BaseWriter): - - """ - Write spdx.review.Review - """ - - def __init__(self, document, out): - super(ReviewInfoWriter, self).__init__(document, out) - - def create_review_node(self, review): - """ - Return a review node. - """ - review_node = BNode() - type_triple = (review_node, RDF.type, self.spdx_namespace.Review) - self.graph.add(type_triple) - - reviewer_node = Literal(review.reviewer.to_value()) - self.graph.add((review_node, self.spdx_namespace.reviewer, reviewer_node)) - reviewed_date_node = Literal(review.review_date_iso_format) - reviewed_triple = (review_node, self.spdx_namespace.reviewDate, reviewed_date_node) - self.graph.add(reviewed_triple) - if review.has_comment: - comment_node = Literal(review.comment) - comment_triple = (review_node, RDFS.comment, comment_node) - self.graph.add(comment_triple) - - return review_node - - def reviews(self): - "Returns a list of review nodes" - return map(self.create_review_node, self.document.reviews) - - -class AnnotationInfoWriter(BaseWriter): - """ - Write spdx.annotation.Annotation - """ - - def __init__(self, document, out): - super(AnnotationInfoWriter, self).__init__(document, out) - - def create_annotation_node(self, annotation): - """ - Return an annotation node. - """ - annotation_node = URIRef(str(annotation.spdx_id)) - type_triple = (annotation_node, RDF.type, self.spdx_namespace.Annotation) - self.graph.add(type_triple) - - annotator_node = Literal(annotation.annotator.to_value()) - self.graph.add((annotation_node, self.spdx_namespace.annotator, annotator_node)) - annotation_date_node = Literal(annotation.annotation_date_iso_format) - annotation_triple = (annotation_node, self.spdx_namespace.annotationDate, annotation_date_node) - self.graph.add(annotation_triple) - if annotation.has_comment: - comment_node = Literal(annotation.comment) - comment_triple = (annotation_node, RDFS.comment, comment_node) - self.graph.add(comment_triple) - annotation_type_node = Literal(annotation.annotation_type) - annotation_type_triple = (annotation_node, self.spdx_namespace.annotationType, annotation_type_node) - self.graph.add(annotation_type_triple) - - return annotation_node - - def annotations(self): - """ - Return a list of annotation nodes - """ - return map(self.create_annotation_node, self.document.annotations) - - -class CreationInfoWriter(BaseWriter): - - """ - Write class spdx.creationinfo.CreationInfo - """ - - def __init__(self, document, out): - super(CreationInfoWriter, self).__init__(document, out) - - def creators(self): - """ - Return a list of creator nodes. - Note: Does not add anything to the graph. - """ - return map(lambda c: Literal(c.to_value()), self.document.creation_info.creators) - - def create_creation_info(self): - """ - Add and return a creation info node to graph - """ - ci_node = BNode() - # Type property - type_triple = (ci_node, RDF.type, self.spdx_namespace.CreationInfo) - self.graph.add(type_triple) - - created_date = Literal(self.document.creation_info.created_iso_format) - created_triple = (ci_node, self.spdx_namespace.created, created_date) - self.graph.add(created_triple) - - creators = self.creators() - for creator in creators: - self.graph.add((ci_node, self.spdx_namespace.creator, creator)) - - if self.document.creation_info.has_comment: - comment_node = Literal(self.document.creation_info.comment) - comment_triple = (ci_node, RDFS.comment, comment_node) - self.graph.add(comment_triple) - - return ci_node - - -class ExternalDocumentRefWriter(BaseWriter): - """ - Write class spdx.external_document_ref.ExternalDocumentRef - """ - - def __init__(self, document, out): - super(ExternalDocumentRefWriter, self).__init__(document, out) - - def create_external_document_ref_node(self, ext_document_references): - """ - Add and return a creation info node to graph - """ - ext_doc_ref_node = BNode() - type_triple = (ext_doc_ref_node, RDF.type, self.spdx_namespace.ExternalDocumentRef) - self.graph.add(type_triple) - - ext_doc_id = Literal( - ext_document_references.external_document_id) - ext_doc_id_triple = ( - ext_doc_ref_node, self.spdx_namespace.externalDocumentId, ext_doc_id) - self.graph.add(ext_doc_id_triple) - - doc_uri = Literal( - ext_document_references.spdx_document_uri) - doc_uri_triple = ( - ext_doc_ref_node, self.spdx_namespace.spdxDocument, doc_uri) - self.graph.add(doc_uri_triple) - - checksum_node = self.create_checksum_node( - ext_document_references.check_sum) - self.graph.add( - (ext_doc_ref_node, self.spdx_namespace.checksum, checksum_node)) - - return ext_doc_ref_node - - def ext_doc_refs(self): - """ - Return a list of review nodes - """ - return map(self.create_external_document_ref_node, - self.document.ext_document_references) - - -class PackageWriter(LicenseWriter): - - """ - Write spdx.package.Package - """ - - def __init__(self, document, out): - super(PackageWriter, self).__init__(document, out) - - def package_verif_node(self, package): - """ - Return a node representing package verification code. - """ - verif_node = BNode() - type_triple = (verif_node, RDF.type, self.spdx_namespace.PackageVerificationCode) - self.graph.add(type_triple) - value_triple = (verif_node, self.spdx_namespace.packageVerificationCodeValue, Literal(package.verif_code)) - self.graph.add(value_triple) - excl_file_nodes = map( - lambda excl: Literal(excl), package.verif_exc_files) - excl_predicate = self.spdx_namespace.packageVerificationCodeExcludedFile - excl_file_triples = [(verif_node, excl_predicate, xcl_file) for xcl_file in excl_file_nodes] - for trp in excl_file_triples: - self.graph.add(trp) - return verif_node - - def handle_package_literal_optional(self, package, package_node, predicate, field): - """ - Check if optional field is set. - If so it adds the triple (package_node, predicate, $) to the graph. - Where $ is a literal or special value term of the value of the field. - """ - if package.has_optional_field(field): - value = getattr(package, field, None) - value_node = self.to_special_value(value) - triple = (package_node, predicate, value_node) - self.graph.add(triple) - - def handle_pkg_optional_fields(self, package, package_node): - """ - Write package optional fields. - """ - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.versionInfo, 'version') - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.packageFileName, 'file_name') - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.supplier, 'supplier') - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.originator, 'originator') - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.sourceInfo, 'source_info') - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.licenseComments, 'license_comment') - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.summary, 'summary') - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.description, 'description') - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.comment, 'comment') - self.handle_package_literal_optional(package, package_node, self.spdx_namespace.filesAnalyzed, 'files_analyzed') - - - if package.has_optional_field('check_sum'): - checksum_node = self.create_checksum_node(package.check_sum) - self.graph.add((package_node, self.spdx_namespace.checksum, checksum_node)) - - if package.has_optional_field('homepage'): - homepage_node = URIRef(self.to_special_value(package.homepage)) - homepage_triple = (package_node, self.doap_namespace.homepage, homepage_node) - self.graph.add(homepage_triple) - - def create_package_node(self, package): - """ - Return a Node representing the package. - Files must have been added to the graph before this method is called. - """ - package_node = URIRef('http://www.spdx.org/tools#SPDXRef-Package') - type_triple = (package_node, RDF.type, self.spdx_namespace.Package) - self.graph.add(type_triple) - # Package SPDXID - if package.spdx_id: - pkg_spdx_id = URIRef(package.spdx_id) - pkg_spdx_id_triple = (package_node, self.spdx_namespace.Package, - pkg_spdx_id) - self.graph.add(pkg_spdx_id_triple) - # Handle optional fields: - self.handle_pkg_optional_fields(package, package_node) - # package name - name_triple = (package_node, self.spdx_namespace.name, Literal(package.name)) - self.graph.add(name_triple) - # Package download location - down_loc_node = (package_node, self.spdx_namespace.downloadLocation, self.to_special_value(package.download_location)) - self.graph.add(down_loc_node) - # Handle package verification - verif_node = self.package_verif_node(package) - verif_triple = (package_node, self.spdx_namespace.packageVerificationCode, verif_node) - self.graph.add(verif_triple) - # Handle concluded license - conc_lic_node = self.license_or_special(package.conc_lics) - conc_lic_triple = (package_node, self.spdx_namespace.licenseConcluded, conc_lic_node) - self.graph.add(conc_lic_triple) - # Handle declared license - decl_lic_node = self.license_or_special(package.license_declared) - decl_lic_triple = (package_node, self.spdx_namespace.licenseDeclared, decl_lic_node) - self.graph.add(decl_lic_triple) - # Package licenses from files - licenses_from_files_nodes = map(lambda el: self.license_or_special(el), package.licenses_from_files) - lic_from_files_predicate = self.spdx_namespace.licenseInfoFromFiles - lic_from_files_triples = [(package_node, lic_from_files_predicate, node) for node in licenses_from_files_nodes] - for triple in lic_from_files_triples: - self.graph.add(triple) - # Copyright Text - cr_text_node = self.to_special_value(package.cr_text) - cr_text_triple = (package_node, self.spdx_namespace.copyrightText, cr_text_node) - self.graph.add(cr_text_triple) - # Handle files - self.handle_package_has_file(package, package_node) - return package_node - - def packages(self): - """ - Return a node that represents the package in the graph. - Call this function to write package info. - """ - # TODO: In the future this may be a list to support SPDX 2.0 - return self.create_package_node(self.document.package) - - def handle_package_has_file_helper(self, pkg_file): - """ - Return node representing pkg_file - pkg_file should be instance of spdx.file. - """ - nodes = list(self.graph.triples((None, self.spdx_namespace.fileName, Literal(pkg_file.name)))) - if len(nodes) == 1: - return nodes[0][0] - else: - raise InvalidDocumentError('handle_package_has_file_helper could not' + - ' find file node for file: {0}'.format(pkg_file.name)) - - def handle_package_has_file(self, package, package_node): - """ - Add hasFile triples to graph. - Must be called after files have been added. - """ - file_nodes = map(self.handle_package_has_file_helper, package.files) - triples = [(package_node, self.spdx_namespace.hasFile, node) for node in file_nodes] - for triple in triples: - self.graph.add(triple) - - -class PackageExternalRefWriter(BaseWriter): - """ - Write class spdx.package.ExternalPackageRef - """ - - def __init__(self, document, out): - super(PackageExternalRefWriter, self).__init__(document, out) - - def create_package_external_ref_node(self, pkg_ext_refs): - """ - Add and return an external package reference node to graph. - """ - pkg_ext_ref_node = BNode() - pkg_ext_ref_triple = (pkg_ext_ref_node, RDF.type, self.spdx_namespace.ExternalRef) - self.graph.add(pkg_ext_ref_triple) - - pkg_ext_ref_category = Literal(pkg_ext_refs.category) - pkg_ext_ref_category_triple = ( - pkg_ext_ref_node, self.spdx_namespace.referenceCategory, pkg_ext_ref_category) - self.graph.add(pkg_ext_ref_category_triple) - - pkg_ext_ref_type = Literal(pkg_ext_refs.pkg_ext_ref_type) - pkg_ext_ref_type_triple = ( - pkg_ext_ref_node, self.spdx_namespace.referenceType, pkg_ext_ref_type) - self.graph.add(pkg_ext_ref_type_triple) - - pkg_ext_ref_locator = Literal(pkg_ext_refs.locator) - pkg_ext_ref_locator_triple = ( - pkg_ext_ref_node, self.spdx_namespace.referenceLocator, pkg_ext_ref_locator) - self.graph.add(pkg_ext_ref_locator_triple) - - pkg_ext_ref_comment = Literal(pkg_ext_refs.comment) - pkg_ext_ref_comment_triple = ( - pkg_ext_ref_node, RDFS.comment, pkg_ext_ref_comment) - self.graph.add(pkg_ext_ref_comment_triple) - - return pkg_ext_ref_node - - def pkg_ext_refs(self): - """ - Return a list of package external references. - """ - return map(self.create_package_external_ref_node, - self.document.package.pkg_ext_refs) - - -class Writer(CreationInfoWriter, ReviewInfoWriter, FileWriter, PackageWriter, - PackageExternalRefWriter, ExternalDocumentRefWriter, AnnotationInfoWriter, - SnippetWriter): - """ - Warpper for other writers to write all fields of spdx.document.Document - Call `write()` to start writing. - """ - - def __init__(self, document, out): - """ - - document is spdx.document instance that will be written. - - out is a file-like object that will be written to. - """ - super(Writer, self).__init__(document, out) - - def create_doc(self): - """ - Add and return the root document node to graph. - """ - doc_node = URIRef('http://www.spdx.org/tools#SPDXRef-DOCUMENT') - # Doc type - self.graph.add((doc_node, RDF.type, self.spdx_namespace.SpdxDocument)) - # Version - vers_literal = Literal(str(self.document.version)) - self.graph.add((doc_node, self.spdx_namespace.specVersion, vers_literal)) - # Data license - data_lics = URIRef(self.document.data_license.url) - self.graph.add((doc_node, self.spdx_namespace.dataLicense, data_lics)) - if self.document.name: - doc_name = URIRef(self.document.name) - self.graph.add((doc_node, self.spdx_namespace.name, doc_name)) - return doc_node - - def write(self): - doc_node = self.create_doc() - # Add creation info - creation_info_node = self.create_creation_info() - ci_triple = (doc_node, self.spdx_namespace.creationInfo, creation_info_node) - self.graph.add(ci_triple) - # Add review info - review_nodes = self.reviews() - for review in review_nodes: - self.graph.add((doc_node, self.spdx_namespace.reviewed, review)) - # Add external document references info - ext_doc_ref_nodes = self.ext_doc_refs() - for ext_doc_ref in ext_doc_ref_nodes: - ext_doc_ref_triple = (doc_node, - self.spdx_namespace.externalDocumentRef, - ext_doc_ref) - self.graph.add(ext_doc_ref_triple) - # Add extracted licenses - licenses = map( - self.create_extracted_license, self.document.extracted_licenses) - for lic in licenses: - self.graph.add((doc_node, self.spdx_namespace.hasExtractedLicensingInfo, lic)) - # Add files - files = self.files() - for file_node in files: - self.graph.add((doc_node, self.spdx_namespace.referencesFile, file_node)) - self.add_file_dependencies() - # Add package - package_node = self.packages() - package_triple = (doc_node, self.spdx_namespace.describesPackage, package_node) - self.graph.add(package_triple) - # Add snippet - snippet_nodes = self.snippets() - for snippet in snippet_nodes: - self.graph.add((doc_node, self.spdx_namespace.Snippet, snippet)) - - # normalize the graph to ensure that the sort order is stable - self.graph = to_isomorphic(self.graph) - - # Write file - self.graph.serialize(self.out, 'pretty-xml', encoding='utf-8') - - -def write_document(document, out, validate=True): - """ - Write an SPDX RDF document. - - document - spdx.document instance. - - out - file like object that will be written to. - Optionally `validate` the document before writing and raise - InvalidDocumentError if document.validate returns False. - """ - - if validate: - messages = [] - messages = document.validate(messages) - if messages: - raise InvalidDocumentError(messages) - - writer = Writer(document, out) - writer.write() diff --git a/spdx/writers/tagvalue.py b/spdx/writers/tagvalue.py deleted file mode 100644 index 939fec9d2..000000000 --- a/spdx/writers/tagvalue.py +++ /dev/null @@ -1,339 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import six -from six.moves import zip_longest - -from spdx import document -from spdx import file as spdx_file - - -class InvalidDocumentError(Exception): - """ - Raised when attempting to write an invalid document. - """ - pass - - -def write_separators(out): - out.write(u'\n' * 2) - - -def format_verif_code(package): - if len(package.verif_exc_files) == 0: - return package.verif_code - else: - return "{0} ({1})".format(package.verif_code, ','.join(package.verif_exc_files)) - - -def write_value(tag, value, out): - out.write(u'{0}: {1}\n'.format(tag, value)) - - -def write_text_value(tag, value, out): - value = u'{0}: {1}\n'.format(tag, value) - out.write(value) - - -def write_creation_info(creation_info, out): - """ - Write the creation info to out. - """ - out.write('# Creation Info\n\n') - # Write sorted creators - for creator in sorted(creation_info.creators): - write_value('Creator', creator, out) - - # write created - write_value('Created', creation_info.created_iso_format, out) - # possible comment - if creation_info.has_comment: - write_text_value('CreatorComment', creation_info.comment, out) - - -def write_review(review, out): - """ - Write the fields of a single review to out. - """ - out.write('# Review\n\n') - write_value('Reviewer', review.reviewer, out) - write_value('ReviewDate', review.review_date_iso_format, out) - if review.has_comment: - write_text_value('ReviewComment', review.comment, out) - - -def write_annotation(annotation, out): - """ - Write the fields of a single annotation to out. - """ - out.write('# Annotation\n\n') - write_value('Annotator', annotation.annotator, out) - write_value('AnnotationDate', annotation.annotation_date_iso_format, out) - if annotation.has_comment: - write_text_value('AnnotationComment', annotation.comment, out) - write_value('AnnotationType', annotation.annotation_type, out) - if annotation.spdx_id: - write_value('SPDXREF', annotation.spdx_id, out) - - -def write_file_type(ftype, out): - VALUES = { - spdx_file.FileType.SOURCE: 'SOURCE', - spdx_file.FileType.OTHER: 'OTHER', - spdx_file.FileType.BINARY: 'BINARY', - spdx_file.FileType.ARCHIVE: 'ARCHIVE' - } - write_value('FileType', VALUES[ftype], out) - - -def write_file(spdx_file, out): - """ - Write a file fields to out. - """ - out.write('# File\n\n') - write_value('FileName', spdx_file.name, out) - if spdx_file.spdx_id: - write_value('SPDXID', spdx_file.spdx_id, out) - if spdx_file.has_optional_field('type'): - write_file_type(spdx_file.type, out) - write_value('FileChecksum', spdx_file.chk_sum.to_tv(), out) - if isinstance(spdx_file.conc_lics, (document.LicenseConjunction, document.LicenseDisjunction)): - write_value('LicenseConcluded', u'({0})'.format(spdx_file.conc_lics), out) - else: - write_value('LicenseConcluded', spdx_file.conc_lics, out) - - # write sorted list - for lics in sorted(spdx_file.licenses_in_file): - write_value('LicenseInfoInFile', lics, out) - - if isinstance(spdx_file.copyright, six.string_types): - write_text_value('FileCopyrightText', spdx_file.copyright, out) - else: - write_value('FileCopyrightText', spdx_file.copyright, out) - - if spdx_file.has_optional_field('license_comment'): - write_text_value('LicenseComments', spdx_file.license_comment, out) - - if spdx_file.has_optional_field('comment'): - write_text_value('FileComment', spdx_file.comment, out) - - if spdx_file.has_optional_field('notice'): - write_text_value('FileNotice', spdx_file.notice, out) - - for contributor in sorted(spdx_file.contributors): - write_value('FileContributor', contributor, out) - - for dependency in sorted(spdx_file.dependencies): - write_value('FileDependency', dependency, out) - - names = spdx_file.artifact_of_project_name - homepages = spdx_file.artifact_of_project_home - uris = spdx_file.artifact_of_project_uri - - for name, homepage, uri in sorted(zip_longest(names, homepages, uris)): - write_value('ArtifactOfProjectName', name, out) - if homepage is not None: - write_value('ArtifactOfProjectHomePage', homepage, out) - if uri is not None: - write_value('ArtifactOfProjectURI', uri, out) - - -def write_snippet(snippet, out): - """ - Write snippet fields to out. - """ - out.write('# Snippet\n\n') - write_value('SnippetSPDXID', snippet.spdx_id, out) - write_value('SnippetFromFileSPDXID', snippet.snip_from_file_spdxid, out) - write_text_value('SnippetCopyrightText', snippet.copyright, out) - if snippet.has_optional_field('name'): - write_value('SnippetName', snippet.name, out) - if snippet.has_optional_field('comment'): - write_text_value('SnippetComment', snippet.comment, out) - if snippet.has_optional_field('license_comment'): - write_text_value('SnippetLicenseComments', snippet.license_comment, out) - if isinstance(snippet.conc_lics, - (document.LicenseConjunction, document.LicenseDisjunction)): - write_value('SnippetLicenseConcluded', u'({0})'.format( - snippet.conc_lics), out) - else: - write_value('SnippetLicenseConcluded', snippet.conc_lics, out) - # Write sorted list - for lics in sorted(snippet.licenses_in_snippet): - write_value('LicenseInfoInSnippet', lics, out) - - -def write_package(package, out): - """ - Write a package fields to out. - """ - out.write('# Package\n\n') - if package.name: - write_value('PackageName', package.name, out) - if package.spdx_id: - write_value('SPDXID', package.spdx_id, out) - if package.has_optional_field('version'): - write_value('PackageVersion', package.version, out) - write_value('PackageDownloadLocation', package.download_location, out) - - if package.has_optional_field('files_analyzed'): - write_value('FilesAnalyzed', package.files_analyzed, out) - - if package.has_optional_field('summary'): - write_text_value('PackageSummary', package.summary, out) - - if package.has_optional_field('source_info'): - write_text_value('PackageSourceInfo', package.source_info, out) - - if package.has_optional_field('file_name'): - write_value('PackageFileName', package.file_name, out) - - if package.has_optional_field('supplier'): - write_value('PackageSupplier', package.supplier, out) - - if package.has_optional_field('originator'): - write_value('PackageOriginator', package.originator, out) - - if package.has_optional_field('check_sum'): - write_value('PackageChecksum', package.check_sum.to_tv(), out) - - write_value('PackageVerificationCode', format_verif_code(package), out) - - if package.has_optional_field('description'): - write_text_value('PackageDescription', package.description, out) - - if package.has_optional_field('comment'): - write_text_value('PackageComment', package.comment, out) - - if isinstance(package.license_declared, (document.LicenseConjunction, - document.LicenseDisjunction)): - write_value('PackageLicenseDeclared', u'({0})'.format(package.license_declared), out) - else: - write_value('PackageLicenseDeclared', package.license_declared, out) - - if isinstance(package.conc_lics, (document.LicenseConjunction, - document.LicenseDisjunction)): - write_value('PackageLicenseConcluded', u'({0})'.format(package.conc_lics), out) - else: - write_value('PackageLicenseConcluded', package.conc_lics, out) - - # Write sorted list of licenses. - for lics in sorted(package.licenses_from_files): - write_value('PackageLicenseInfoFromFiles', lics, out) - - if package.has_optional_field('license_comment'): - write_text_value('PackageLicenseComments', package.license_comment, out) - - # cr_text is either free form text or NONE or NOASSERTION. - if package.cr_text: - if isinstance(package.cr_text, six.string_types): - write_text_value('PackageCopyrightText', package.cr_text, out) - else: - write_value('PackageCopyrightText', package.cr_text, out) - - if package.has_optional_field('homepage'): - write_value('PackageHomePage', package.homepage, out) - - for pkg_ref in package.pkg_ext_refs: - pkg_ref_str = ' '.join([pkg_ref.category, - pkg_ref.pkg_ext_ref_type, - pkg_ref.locator]) - write_value('ExternalRef', pkg_ref_str, out) - if pkg_ref.comment: - write_text_value('ExternalRefComment', pkg_ref.comment, out) - - # Write sorted files. - for spdx_file in sorted(package.files): - write_separators(out) - write_file(spdx_file, out) - - -def write_extracted_licenses(lics, out): - """ - Write extracted licenses fields to out. - """ - write_value('LicenseID', lics.identifier, out) - - if lics.full_name is not None: - write_value('LicenseName', lics.full_name, out) - - if lics.comment is not None: - write_text_value('LicenseComment', lics.comment, out) - - for xref in sorted(lics.cross_ref): - write_value('LicenseCrossReference', xref, out) - - write_text_value('ExtractedText', lics.text, out) - - -def write_document(document, out, validate=True): - """ - Write an SPDX tag value document. - - document - spdx.document instance. - - out - file like object that will be written to. - Optionally `validate` the document before writing and raise - InvalidDocumentError if document.validate returns False. - """ - messages = [] - messages = document.validate(messages) - if validate and messages: - raise InvalidDocumentError(messages) - - # Write out document information - out.write('# Document Information\n\n') - write_value('SPDXVersion', str(document.version), out) - write_value('DataLicense', document.data_license.identifier, out) - if document.name: - write_value('DocumentName', document.name, out) - write_value('SPDXID', 'SPDXRef-DOCUMENT', out) - if document.namespace: - write_value('DocumentNamespace', document.namespace, out) - if document.has_comment: - write_text_value('DocumentComment', document.comment, out) - for doc_ref in document.ext_document_references: - doc_ref_str = ' '.join([doc_ref.external_document_id, - doc_ref.spdx_document_uri, - doc_ref.check_sum.identifier + ':' + - doc_ref.check_sum.value]) - write_value('ExternalDocumentRef', doc_ref_str, out) - write_separators(out) - # Write out creation info - write_creation_info(document.creation_info, out) - write_separators(out) - - # Writesorted reviews - for review in sorted(document.reviews): - write_review(review, out) - write_separators(out) - - # Write sorted annotations - for annotation in sorted(document.annotations): - write_annotation(annotation, out) - write_separators(out) - - # Write out package info - write_package(document.package, out) - write_separators(out) - - # Write out snippet info - for snippet in document.snippet: - write_snippet(snippet, out) - write_separators(out) - - out.write('# Extracted Licenses\n\n') - for lic in sorted(document.extracted_licenses): - write_extracted_licenses(lic, out) - write_separators(out) diff --git a/spdx/writers/xml.py b/spdx/writers/xml.py deleted file mode 100644 index 567581c65..000000000 --- a/spdx/writers/xml.py +++ /dev/null @@ -1,34 +0,0 @@ - -# Copyright (c) the SPDX tools authors -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import xmltodict - -from spdx.writers.tagvalue import InvalidDocumentError -from spdx.writers.jsonyamlxml import Writer - - -def write_document(document, out, validate=True): - - if validate: - messages = [] - messages = document.validate(messages) - if messages: - raise InvalidDocumentError(messages) - - writer = Writer(document) - document_object = {'SpdxDocument': writer.create_document()} - - xmltodict.unparse(document_object, out, encoding='utf-8', pretty=True) diff --git a/spdx/writers/yaml.py b/spdx/writers/yaml.py deleted file mode 100644 index 8d166fdc3..000000000 --- a/spdx/writers/yaml.py +++ /dev/null @@ -1,34 +0,0 @@ - -# Copyright (c) Xavier Figueroa -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import yaml - -from spdx.writers.tagvalue import InvalidDocumentError -from spdx.writers.jsonyamlxml import Writer - - -def write_document(document, out, validate=True): - - if validate: - messages = [] - messages = document.validate(messages) - if messages: - raise InvalidDocumentError(messages) - - writer = Writer(document) - document_object = writer.create_document() - - yaml.safe_dump(document_object, out, indent=2, explicit_start=True) diff --git a/spdx/parsers/lexers/__init__.py b/src/spdx_tools/common/__init__.py similarity index 100% rename from spdx/parsers/lexers/__init__.py rename to src/spdx_tools/common/__init__.py diff --git a/src/spdx_tools/common/spdx_licensing.py b/src/spdx_tools/common/spdx_licensing.py new file mode 100644 index 000000000..a9a17e973 --- /dev/null +++ b/src/spdx_tools/common/spdx_licensing.py @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from license_expression import get_spdx_licensing + +# this getter takes quite long so we only call it once in this singleton module +spdx_licensing = get_spdx_licensing() diff --git a/spdx/writers/__init__.py b/src/spdx_tools/common/typing/__init__.py similarity index 100% rename from spdx/writers/__init__.py rename to src/spdx_tools/common/typing/__init__.py diff --git a/src/spdx_tools/common/typing/constructor_type_errors.py b/src/spdx_tools/common/typing/constructor_type_errors.py new file mode 100644 index 000000000..a9b4046aa --- /dev/null +++ b/src/spdx_tools/common/typing/constructor_type_errors.py @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + + +class ConstructorTypeErrors(TypeError): + """ + Helper class that holds a list of error messages. Intended to capture all TypeErrors encountered during a + constructor call, instead of raising only the first one. + """ + + messages: List[str] + + def __init__(self, messages: List[str]): + self.messages = messages + + def get_messages(self): + return list(self.messages) diff --git a/src/spdx_tools/common/typing/dataclass_with_properties.py b/src/spdx_tools/common/typing/dataclass_with_properties.py new file mode 100644 index 000000000..3f13950d5 --- /dev/null +++ b/src/spdx_tools/common/typing/dataclass_with_properties.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import dataclass + +from beartype import beartype +from beartype.roar import BeartypeCallHintException + + +def dataclass_with_properties(cls): + """Decorator to generate a dataclass with properties out of the class' value:type list. + Their getters and setters will be subjected to the @typechecked decorator to ensure type conformity.""" + data_cls = dataclass(cls) + for field_name, field_type in data_cls.__annotations__.items(): + set_field = make_setter(field_name, field_type) + get_field = make_getter(field_name, field_type) + + setattr(data_cls, field_name, property(get_field, set_field)) + + return data_cls + + +def make_setter(field_name, field_type): + """helper method to avoid late binding when generating functions in a for loop""" + + @beartype + def set_field(self, value: field_type): + setattr(self, f"_{field_name}", value) + + def set_field_with_error_conversion(self, value: field_type): + try: + set_field(self, value) + except BeartypeCallHintException as err: + error_message: str = f"SetterError {self.__class__.__name__}: {err}" + + # As setters are created dynamically, their argument name is always "value". We replace it by the + # actual name so the error message is more helpful. + raise TypeError(error_message.replace("value", field_name, 1) + f": {value}") + + return set_field_with_error_conversion + + +def make_getter(field_name, field_type): + """helper method to avoid late binding when generating functions in a for loop""" + + def get_field(self) -> field_type: + return getattr(self, f"_{field_name}") + + return get_field diff --git a/src/spdx_tools/common/typing/type_checks.py b/src/spdx_tools/common/typing/type_checks.py new file mode 100644 index 000000000..d9dc9733a --- /dev/null +++ b/src/spdx_tools/common/typing/type_checks.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import fields + +from beartype.typing import Any, Dict + +from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors + + +def check_types_and_set_values(instance_under_construction: Any, local_variables: Dict) -> None: + """ + Helper method to accumulate all type errors encountered during a constructor call and return them in a + ConstructorTypeErrors instance. + Background: Our setters are enhanced with runtime typechecks using beartype. However, this means that by + default, a TypeError is raised on the first type violation that is encountered. We consider it more helpful to + return all type violations in one go. + As an aside, defining constructors "manually" using this utility method helps avoid a nasty PyCharm bug: + https://youtrack.jetbrains.com/issue/PY-34569 + """ + errors = [] + for field in fields(instance_under_construction): + key = field.name + value = local_variables.get(key) + try: + setattr(instance_under_construction, key, value) + except TypeError as err: + error_message: str = err.args[0] + errors.append(error_message) + if errors: + raise ConstructorTypeErrors(errors) diff --git a/CHANGELOG.rst b/src/spdx_tools/spdx/__init__.py similarity index 100% rename from CHANGELOG.rst rename to src/spdx_tools/spdx/__init__.py diff --git a/src/spdx_tools/spdx/casing_tools.py b/src/spdx_tools/spdx/casing_tools.py new file mode 100644 index 000000000..c143cfd45 --- /dev/null +++ b/src/spdx_tools/spdx/casing_tools.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from re import sub + + +def snake_case_to_camel_case(snake_case_string: str) -> str: + each_word_capitalized = sub(r"[_\-]+", " ", snake_case_string).title().replace(" ", "") + return each_word_capitalized[0].lower() + each_word_capitalized[1:] + + +def camel_case_to_snake_case(camel_case_string: str) -> str: + snake_case_string = sub("(?!^)([A-Z]+)", r"_\1", camel_case_string).lower() + return snake_case_string diff --git a/src/spdx_tools/spdx/clitools/__init__.py b/src/spdx_tools/spdx/clitools/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/clitools/pyspdxtools.py b/src/spdx_tools/spdx/clitools/pyspdxtools.py new file mode 100644 index 000000000..4219c6b81 --- /dev/null +++ b/src/spdx_tools/spdx/clitools/pyspdxtools.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2020 Yash Varshney +# Copyright (c) 2023 spdx contributors +# SPDX-License-Identifier: Apache-2.0 +# 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. +import logging +import sys +from json import JSONDecodeError +from xml.parsers.expat import ExpatError +from xml.sax import SAXParseException + +import click +from beartype.typing import List +from yaml.scanner import ScannerError + +from spdx_tools.spdx.graph_generation import export_graph_from_document +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.parse_anything import parse_file +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.writer.tagvalue import tagvalue_writer +from spdx_tools.spdx.writer.write_anything import write_file + + +@click.command() +@click.option("--infile", "-i", required=True, help="The file containing the document to be validated or converted.") +@click.option( + "--outfile", + "-o", + help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion). " + "If you add the option --graph to the command the generated graph will be written to this file.", +) +@click.option( + "--version", + help='The SPDX version to be used during parsing and validation ("SPDX-2.2" or "SPDX-2.3"). ' + "Will be read from the document if not provided.", + default=None, +) +@click.option("--novalidation", is_flag=True, help="Don't validate the provided document.") +@click.option( + "--graph", + is_flag=True, + default=False, + help="Generate a relationship graph from the input file. " + "The generated graph is saved to the file specified with --outfile. " + "Note: You need to install the optional dependencies 'networkx' and 'pygraphviz' for this feature.", +) +def main(infile: str, outfile: str, version: str, novalidation: bool, graph: bool): + """ + CLI-tool for validating SPDX documents and converting between RDF, TAG-VALUE, JSON, YAML and XML formats. + Formats are determined by the file endings. + To use, run: 'pyspdxtools --infile --outfile ' + """ + try: + document: Document = parse_file(infile) + + if not novalidation: + if not version: + version = document.creation_info.spdx_version + + if version not in ["SPDX-2.2", "SPDX-2.3"]: + logging.error(f"This tool only supports SPDX versions SPDX-2.2 and SPDX-2.3, but got: {version}") + sys.exit(1) + + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document, version) + if validation_messages: + log_string = "\n".join( + ["The document is invalid. The following issues have been found:"] + + [message.validation_message for message in validation_messages] + ) + logging.error(log_string) + sys.exit(1) + else: + logging.info("The document is valid.") + + if outfile == "-": + tagvalue_writer.write_document(document, sys.stdout) + + elif graph: + try: + export_graph_from_document(document, outfile) + except ImportError: + logging.error( + "To be able to draw a relationship graph of the parsed document " + "you need to install 'networkx' and 'pygraphviz'. Run 'pip install \".[graph_generation]\"'." + ) + sys.exit(1) + + elif outfile: + write_file(document, outfile, validate=False) + + except NotImplementedError as err: + logging.error( + err.args[0] + + "\nPlease note that this project is currently undergoing a major refactoring and therefore missing " + "a few features which will be added in time (refer to https://github.com/spdx/tools-python/issues " + "for insights into the current status).\n" + "In the meantime, please use the current PyPI release version." + ) + sys.exit(1) + + except SPDXParsingError as err: + log_string = "\n".join( + ["There have been issues while parsing the provided document:"] + + [message for message in err.get_messages()] + ) + logging.error(log_string) + sys.exit(1) + + except JSONDecodeError as err: + logging.error(f"Invalid JSON provided: {err.args[0]}") + sys.exit(1) + + except ScannerError as err: + logging.error("Invalid YAML provided: " + "\n".join([str(arg) for arg in err.args])) + sys.exit(1) + + except ExpatError as err: + logging.error(f"Invalid XML provided: {err.args[0]}") + sys.exit(1) + + except SAXParseException as err: + logging.error(f"Invalid RDF-XML provided: {str(err)}") + sys.exit(1) + + except FileNotFoundError as err: + logging.error(f"{err.strerror}: {err.filename}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/src/spdx_tools/spdx/constants.py b/src/spdx_tools/spdx/constants.py new file mode 100644 index 000000000..167f98951 --- /dev/null +++ b/src/spdx_tools/spdx/constants.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +DOCUMENT_SPDX_ID = "SPDXRef-DOCUMENT" diff --git a/src/spdx_tools/spdx/datetime_conversions.py b/src/spdx_tools/spdx/datetime_conversions.py new file mode 100644 index 000000000..cce624d57 --- /dev/null +++ b/src/spdx_tools/spdx/datetime_conversions.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime, timezone + + +def datetime_from_str(date_str: str) -> datetime: + if not isinstance(date_str, str): + raise TypeError(f"Could not convert str to datetime, invalid type: {type(date_str).__name__}") + + date = datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%SZ") # raises ValueError if format does not match + return date + + +def datetime_to_iso_string(date: datetime) -> str: + """ + Return an ISO-8601 representation of a datetime object. + """ + if date.tzinfo is not None: + date = date.astimezone(timezone.utc) # Convert aware datetimes to UTC + date = date.replace(tzinfo=None) # Convert to naive datetime + + if date.microsecond != 0: + date = date.replace(microsecond=0) # SPDX does not support microseconds + + return date.isoformat() + "Z" diff --git a/src/spdx_tools/spdx/document_utils.py b/src/spdx_tools/spdx/document_utils.py new file mode 100644 index 000000000..c0c0f5b27 --- /dev/null +++ b/src/spdx_tools/spdx/document_utils.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from copy import deepcopy + +from beartype.typing import Any, Dict, List, Union + +from spdx_tools.spdx.model import Document, File, Package, Snippet + + +def get_contained_spdx_element_ids(document: Document) -> List[str]: + element_ids = [file.spdx_id for file in document.files] + element_ids.extend([package.spdx_id for package in document.packages]) + element_ids.extend([snippet.spdx_id for snippet in document.snippets]) + return element_ids + + +def get_element_from_spdx_id(document: Document, spdx_id: str) -> Union[Package, File, Snippet, None]: + contained_spdx_elements: Dict[str, Union[Package, File, Snippet]] = get_contained_spdx_elements(document) + if spdx_id not in contained_spdx_elements: + return None + return contained_spdx_elements[spdx_id] + + +def get_contained_spdx_elements(document: Document) -> Dict[str, Union[Package, File, Snippet]]: + contained_spdx_elements = {package.spdx_id: package for package in document.packages} + contained_spdx_elements.update({file.spdx_id: file for file in document.files}) + contained_spdx_elements.update({snippet.spdx_id: snippet for snippet in document.snippets}) + + return contained_spdx_elements + + +def create_document_without_duplicates(document: Document) -> Document: + document_without_duplicates = deepcopy(document) + for elements in [ + [document_without_duplicates.creation_info], + document_without_duplicates.files, + document_without_duplicates.packages, + document_without_duplicates.snippets, + document_without_duplicates.extracted_licensing_info, + ]: + for element in elements: + for key, value in element.__dict__.items(): + if isinstance(value, list): + value_without_duplicates = create_list_without_duplicates(value) + setattr(element, key, value_without_duplicates) + + return document_without_duplicates + + +def create_list_without_duplicates(list_with_potential_duplicates: List[Any]) -> List[Any]: + list_without_duplicates = [] + for element in list_with_potential_duplicates: + if element not in list_without_duplicates: + list_without_duplicates.append(element) + + return list_without_duplicates diff --git a/src/spdx_tools/spdx/formats.py b/src/spdx_tools/spdx/formats.py new file mode 100644 index 000000000..56f5b1663 --- /dev/null +++ b/src/spdx_tools/spdx/formats.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto + +from spdx_tools.spdx.parser.error import SPDXParsingError + + +class FileFormat(Enum): + JSON = auto() + YAML = auto() + XML = auto() + TAG_VALUE = auto() + RDF_XML = auto() + + +def file_name_to_format(file_name: str) -> FileFormat: + if file_name.endswith(".rdf") or file_name.endswith(".rdf.xml"): + return FileFormat.RDF_XML + elif file_name.endswith(".tag") or file_name.endswith(".spdx"): + return FileFormat.TAG_VALUE + elif file_name.endswith(".json"): + return FileFormat.JSON + elif file_name.endswith(".xml"): + return FileFormat.XML + elif file_name.endswith(".yaml") or file_name.endswith(".yml"): + return FileFormat.YAML + else: + raise SPDXParsingError(["Unsupported SPDX file type: " + str(file_name)]) diff --git a/src/spdx_tools/spdx/graph_generation.py b/src/spdx_tools/spdx/graph_generation.py new file mode 100644 index 000000000..da4345d50 --- /dev/null +++ b/src/spdx_tools/spdx/graph_generation.py @@ -0,0 +1,73 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict, List, Union + +from spdx_tools.spdx.model import File, Package, Snippet + +try: + from networkx import DiGraph +except ImportError: + DiGraph = None +from spdx_tools.spdx.document_utils import get_contained_spdx_elements +from spdx_tools.spdx.model import Document, Relationship + + +def export_graph_from_document(document: Document, file_name: str) -> None: + from networkx.drawing import nx_agraph + + graph = generate_relationship_graph_from_spdx(document) + _color_nodes(graph) + attributes_graph = nx_agraph.to_agraph(graph) # convert to a pygraphviz graph + attributes_graph.draw(file_name, prog="dot") + + +def generate_relationship_graph_from_spdx(document: Document) -> DiGraph: + from networkx import DiGraph + + graph = DiGraph() + graph.add_node(document.creation_info.spdx_id, element=document.creation_info) + + contained_elements: Dict[str, Union[Package, File, Snippet]] = get_contained_spdx_elements(document) + contained_element_nodes = [(spdx_id, {"element": element}) for spdx_id, element in contained_elements.items()] + graph.add_nodes_from(contained_element_nodes) + + relationships_by_spdx_id: Dict[str, List[Relationship]] = dict() + for relationship in document.relationships: + relationships_by_spdx_id.setdefault(relationship.spdx_element_id, []).append(relationship) + + for spdx_id, relationships in relationships_by_spdx_id.items(): + if spdx_id not in graph.nodes(): + # this will add any external spdx_id to the graph where we have no further information about the element, + # to indicate that this node represents an element we add the attribute "element" + graph.add_node(spdx_id, element=None) + for relationship in relationships: + relationship_node_key = relationship.spdx_element_id + "_" + relationship.relationship_type.name + graph.add_node(relationship_node_key, comment=relationship.comment) + graph.add_edge(relationship.spdx_element_id, relationship_node_key) + # if the related spdx element is SpdxNone or SpdxNoAssertion we need a type conversion + related_spdx_element_id = str(relationship.related_spdx_element_id) + + if related_spdx_element_id not in graph.nodes(): + # this will add any external spdx_id to the graph where we have no further information about + # the element, to indicate that this node represents an element we add the attribute "element" + graph.add_node( + related_spdx_element_id, + element=None, + ) + graph.add_edge(relationship_node_key, related_spdx_element_id) + + return graph + + +def _color_nodes(graph: DiGraph) -> None: + for node in graph.nodes(): + if "_" in node: + # nodes representing a RelationshipType are concatenated with the spdx_element_id, + # to only see the RelationshipType when rendering the graph to a picture we add + # a label to these nodes + graph.add_node(node, color="lightgreen", label=node.split("_", 1)[-1]) + elif node == "SPDXRef-DOCUMENT": + graph.add_node(node, color="indianred2") + else: + graph.add_node(node, color="lightskyblue") diff --git a/src/spdx_tools/spdx/jsonschema/__init__.py b/src/spdx_tools/spdx/jsonschema/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/jsonschema/annotation_converter.py b/src/spdx_tools/spdx/jsonschema/annotation_converter.py new file mode 100644 index 000000000..16645a216 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/annotation_converter.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.annotation_properties import AnnotationProperty +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model import Annotation, Document + + +class AnnotationConverter(TypedConverter[Annotation]): + def _get_property_value( + self, annotation: Annotation, annotation_property: AnnotationProperty, document: Document = None + ) -> Any: + if annotation_property == AnnotationProperty.ANNOTATION_DATE: + return datetime_to_iso_string(annotation.annotation_date) + elif annotation_property == AnnotationProperty.ANNOTATION_TYPE: + return annotation.annotation_type.name + elif annotation_property == AnnotationProperty.ANNOTATOR: + return annotation.annotator.to_serialized_string() + elif annotation_property == AnnotationProperty.COMMENT: + return annotation.annotation_comment + + def get_json_type(self) -> Type[JsonProperty]: + return AnnotationProperty + + def get_data_model_type(self) -> Type[Annotation]: + return Annotation diff --git a/src/spdx_tools/spdx/jsonschema/annotation_properties.py b/src/spdx_tools/spdx/jsonschema/annotation_properties.py new file mode 100644 index 000000000..e8226f945 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/annotation_properties.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class AnnotationProperty(JsonProperty): + ANNOTATION_DATE = auto() + ANNOTATION_TYPE = auto() + ANNOTATOR = auto() + COMMENT = auto() diff --git a/src/spdx_tools/spdx/jsonschema/checksum_converter.py b/src/spdx_tools/spdx/jsonschema/checksum_converter.py new file mode 100644 index 000000000..9ffb39b11 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/checksum_converter.py @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Type + +from spdx_tools.spdx.jsonschema.checksum_properties import ChecksumProperty +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, Document + + +class ChecksumConverter(TypedConverter[Checksum]): + def get_data_model_type(self) -> Type[Checksum]: + return Checksum + + def get_json_type(self) -> Type[JsonProperty]: + return ChecksumProperty + + def _get_property_value( + self, checksum: Checksum, checksum_property: ChecksumProperty, _document: Document = None + ) -> str: + if checksum_property == ChecksumProperty.ALGORITHM: + return algorithm_to_json_string(checksum.algorithm) + elif checksum_property == ChecksumProperty.CHECKSUM_VALUE: + return checksum.value + + +def algorithm_to_json_string(algorithm: ChecksumAlgorithm) -> str: + name_with_dash: str = algorithm.name.replace("_", "-") + if "BLAKE2B" in name_with_dash: + return name_with_dash.replace("BLAKE2B", "BLAKE2b") + return name_with_dash diff --git a/src/spdx_tools/spdx/jsonschema/checksum_properties.py b/src/spdx_tools/spdx/jsonschema/checksum_properties.py new file mode 100644 index 000000000..c9e2f70c6 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/checksum_properties.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class ChecksumProperty(JsonProperty): + ALGORITHM = auto() + CHECKSUM_VALUE = auto() diff --git a/src/spdx_tools/spdx/jsonschema/converter.py b/src/spdx_tools/spdx/jsonschema/converter.py new file mode 100644 index 000000000..55629f2ae --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/converter.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod + +from beartype.typing import Any, Dict, Generic, Type, TypeVar + +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model import Document + +MISSING_IMPLEMENTATION_MESSAGE = "Must be implemented" + +T = TypeVar("T") + + +class TypedConverter(ABC, Generic[T]): + """ + Base class for all converters between an instance of the tools-python data model and the corresponding dictionary + representation, following the json schema. The generic type T is the type according to the data model. + Each converter has several methods: + - get_json_type and get_data_model_type: return the data model type and the corresponding JsonProperty subclass. + These methods are abstract in the base class and need to be implemented in subclasses. + - json_property_name: converts an enum value of a JsonProperty subclass to the corresponding property name in the + json schema. The default implementation simply converts from snake case to camel case. Can be overridden in case + of exceptions like "SPDXID". + - convert: converts an instance of type T (one of the data model types) to a dictionary representation. In some + cases, the full document is required (see below). The logic should be generic for all types. + - requires_full_document: indicates whether the full document is required for conversion. Returns False by + default, can be overridden as needed for specific types. + - _get_property_value: Retrieves the value of a specific json property from the data model instance. In some + cases, the full document is required. + """ + + @abstractmethod + def _get_property_value(self, instance: T, json_property: JsonProperty, document: Document = None) -> Any: + raise NotImplementedError(MISSING_IMPLEMENTATION_MESSAGE) + + @abstractmethod + def get_json_type(self) -> Type[JsonProperty]: + raise NotImplementedError(MISSING_IMPLEMENTATION_MESSAGE) + + @abstractmethod + def get_data_model_type(self) -> Type[T]: + raise NotImplementedError(MISSING_IMPLEMENTATION_MESSAGE) + + def json_property_name(self, json_property: JsonProperty) -> str: + return snake_case_to_camel_case(json_property.name) + + def requires_full_document(self) -> bool: + return False + + def convert(self, instance: T, document: Document = None) -> Dict: + if not isinstance(instance, self.get_data_model_type()): + raise TypeError( + f"Converter of type {self.__class__} can only convert objects of type " + f"{self.get_data_model_type()}. Received {type(instance)} instead." + ) + if self.requires_full_document() and not document: + raise ValueError(f"Converter of type {self.__class__} requires the full document") + + result = {} + for property_name in self.get_json_type(): + property_value = self._get_property_value(instance, property_name, document) + if property_value is None: + continue + result[self.json_property_name(property_name)] = property_value + return result diff --git a/src/spdx_tools/spdx/jsonschema/creation_info_converter.py b/src/spdx_tools/spdx/jsonschema/creation_info_converter.py new file mode 100644 index 000000000..0a2ef875c --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/creation_info_converter.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.creation_info_properties import CreationInfoProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.model import CreationInfo, Document + + +class CreationInfoConverter(TypedConverter[CreationInfo]): + def get_data_model_type(self) -> Type[CreationInfo]: + return CreationInfo + + def get_json_type(self) -> Type[JsonProperty]: + return CreationInfoProperty + + def _get_property_value( + self, creation_info: CreationInfo, creation_info_property: CreationInfoProperty, _document: Document = None + ) -> Any: + if creation_info_property == CreationInfoProperty.CREATED: + return datetime_to_iso_string(creation_info.created) + elif creation_info_property == CreationInfoProperty.CREATORS: + return [creator.to_serialized_string() for creator in creation_info.creators] or None + elif creation_info_property == CreationInfoProperty.LICENSE_LIST_VERSION: + return apply_if_present(str, creation_info.license_list_version) + elif creation_info_property == CreationInfoProperty.COMMENT: + return creation_info.creator_comment diff --git a/src/spdx_tools/spdx/jsonschema/creation_info_properties.py b/src/spdx_tools/spdx/jsonschema/creation_info_properties.py new file mode 100644 index 000000000..8385b646c --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/creation_info_properties.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class CreationInfoProperty(JsonProperty): + CREATED = auto() + CREATORS = auto() + LICENSE_LIST_VERSION = auto() + COMMENT = auto() diff --git a/src/spdx_tools/spdx/jsonschema/document_converter.py b/src/spdx_tools/spdx/jsonschema/document_converter.py new file mode 100644 index 000000000..a3c2e3699 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/document_converter.py @@ -0,0 +1,95 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.document_utils import get_contained_spdx_element_ids +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.creation_info_converter import CreationInfoConverter +from spdx_tools.spdx.jsonschema.document_properties import DocumentProperty +from spdx_tools.spdx.jsonschema.external_document_ref_converter import ExternalDocumentRefConverter +from spdx_tools.spdx.jsonschema.extracted_licensing_info_converter import ExtractedLicensingInfoConverter +from spdx_tools.spdx.jsonschema.file_converter import FileConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.package_converter import PackageConverter +from spdx_tools.spdx.jsonschema.relationship_converter import RelationshipConverter +from spdx_tools.spdx.jsonschema.snippet_converter import SnippetConverter +from spdx_tools.spdx.model import Document + + +class DocumentConverter(TypedConverter[Document]): + creation_info_converter: CreationInfoConverter + external_document_ref_converter: ExternalDocumentRefConverter + package_converter: PackageConverter + file_converter: FileConverter + snippet_converter: SnippetConverter + annotation_converter: AnnotationConverter + relationship_converter: RelationshipConverter + extracted_licensing_info_converter: ExtractedLicensingInfoConverter + + def __init__(self): + self.external_document_ref_converter = ExternalDocumentRefConverter() + self.creation_info_converter = CreationInfoConverter() + self.package_converter = PackageConverter() + self.file_converter = FileConverter() + self.snippet_converter = SnippetConverter() + self.annotation_converter = AnnotationConverter() + self.relationship_converter = RelationshipConverter() + self.extracted_licensing_info_converter = ExtractedLicensingInfoConverter() + + def get_json_type(self) -> Type[JsonProperty]: + return DocumentProperty + + def get_data_model_type(self) -> Type[Document]: + return Document + + def json_property_name(self, document_property: DocumentProperty) -> str: + if document_property == DocumentProperty.SPDX_ID: + return "SPDXID" + return super().json_property_name(document_property) + + def _get_property_value( + self, document: Document, document_property: DocumentProperty, _document: Document = None + ) -> Any: + if document_property == DocumentProperty.SPDX_ID: + return document.creation_info.spdx_id + elif document_property == DocumentProperty.ANNOTATIONS: + # annotations referencing files, packages or snippets will be added to those elements directly + element_ids = get_contained_spdx_element_ids(document) + document_annotations = filter( + lambda annotation: annotation.spdx_id not in element_ids, document.annotations + ) + return [self.annotation_converter.convert(annotation) for annotation in document_annotations] or None + elif document_property == DocumentProperty.COMMENT: + return document.creation_info.document_comment + elif document_property == DocumentProperty.CREATION_INFO: + return self.creation_info_converter.convert(document.creation_info) + elif document_property == DocumentProperty.DATA_LICENSE: + return document.creation_info.data_license + elif document_property == DocumentProperty.EXTERNAL_DOCUMENT_REFS: + return [ + self.external_document_ref_converter.convert(external_document_ref) + for external_document_ref in document.creation_info.external_document_refs + ] or None + elif document_property == DocumentProperty.HAS_EXTRACTED_LICENSING_INFOS: + return [ + self.extracted_licensing_info_converter.convert(licensing_info) + for licensing_info in document.extracted_licensing_info + ] or None + elif document_property == DocumentProperty.NAME: + return document.creation_info.name + elif document_property == DocumentProperty.SPDX_VERSION: + return document.creation_info.spdx_version + elif document_property == DocumentProperty.DOCUMENT_NAMESPACE: + return document.creation_info.document_namespace + elif document_property == DocumentProperty.PACKAGES: + return [self.package_converter.convert(package, document) for package in document.packages] or None + elif document_property == DocumentProperty.FILES: + return [self.file_converter.convert(file, document) for file in document.files] or None + elif document_property == DocumentProperty.SNIPPETS: + return [self.snippet_converter.convert(snippet, document) for snippet in document.snippets] or None + elif document_property == DocumentProperty.RELATIONSHIPS: + return [ + self.relationship_converter.convert(relationship) for relationship in document.relationships + ] or None diff --git a/src/spdx_tools/spdx/jsonschema/document_properties.py b/src/spdx_tools/spdx/jsonschema/document_properties.py new file mode 100644 index 000000000..9b56fa775 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/document_properties.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class DocumentProperty(JsonProperty): + SPDX_ID = auto() + ANNOTATIONS = auto() + COMMENT = auto() + CREATION_INFO = auto() + DATA_LICENSE = auto() + EXTERNAL_DOCUMENT_REFS = auto() + HAS_EXTRACTED_LICENSING_INFOS = auto() + NAME = auto() + SPDX_VERSION = auto() + DOCUMENT_NAMESPACE = auto() + PACKAGES = auto() + FILES = auto() + SNIPPETS = auto() + RELATIONSHIPS = auto() diff --git a/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py b/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py new file mode 100644 index 000000000..f25bf56e3 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.external_document_ref_properties import ExternalDocumentRefProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model import Document, ExternalDocumentRef + + +class ExternalDocumentRefConverter(TypedConverter[ExternalDocumentRef]): + checksum_converter: ChecksumConverter + + def __init__(self): + self.checksum_converter = ChecksumConverter() + + def _get_property_value( + self, + external_document_ref: ExternalDocumentRef, + external_document_ref_property: ExternalDocumentRefProperty, + _document: Document = None, + ) -> Any: + if external_document_ref_property == ExternalDocumentRefProperty.EXTERNAL_DOCUMENT_ID: + return external_document_ref.document_ref_id + elif external_document_ref_property == ExternalDocumentRefProperty.SPDX_DOCUMENT: + return external_document_ref.document_uri + elif external_document_ref_property == ExternalDocumentRefProperty.CHECKSUM: + return self.checksum_converter.convert(external_document_ref.checksum) + + def get_json_type(self) -> Type[JsonProperty]: + return ExternalDocumentRefProperty + + def get_data_model_type(self) -> Type[ExternalDocumentRef]: + return ExternalDocumentRef diff --git a/src/spdx_tools/spdx/jsonschema/external_document_ref_properties.py b/src/spdx_tools/spdx/jsonschema/external_document_ref_properties.py new file mode 100644 index 000000000..822275179 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/external_document_ref_properties.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class ExternalDocumentRefProperty(JsonProperty): + EXTERNAL_DOCUMENT_ID = auto() + SPDX_DOCUMENT = auto() + CHECKSUM = auto() diff --git a/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py b/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py new file mode 100644 index 000000000..732673c36 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model import Document, ExternalPackageRef + + +class ExternalPackageRefConverter(TypedConverter[ExternalPackageRef]): + def _get_property_value( + self, + external_ref: ExternalPackageRef, + external_ref_property: ExternalPackageRefProperty, + document: Document = None, + ) -> Any: + if external_ref_property == ExternalPackageRefProperty.COMMENT: + return external_ref.comment + elif external_ref_property == ExternalPackageRefProperty.REFERENCE_CATEGORY: + return external_ref.category.name + elif external_ref_property == ExternalPackageRefProperty.REFERENCE_LOCATOR: + return external_ref.locator + elif external_ref_property == ExternalPackageRefProperty.REFERENCE_TYPE: + return external_ref.reference_type + + def get_json_type(self) -> Type[JsonProperty]: + return ExternalPackageRefProperty + + def get_data_model_type(self) -> Type[ExternalPackageRef]: + return ExternalPackageRef diff --git a/src/spdx_tools/spdx/jsonschema/external_package_ref_properties.py b/src/spdx_tools/spdx/jsonschema/external_package_ref_properties.py new file mode 100644 index 000000000..a9d249788 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/external_package_ref_properties.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class ExternalPackageRefProperty(JsonProperty): + COMMENT = auto() + REFERENCE_CATEGORY = auto() + REFERENCE_LOCATOR = auto() + REFERENCE_TYPE = auto() diff --git a/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py new file mode 100644 index 000000000..9bf0a8530 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.model import Document, ExtractedLicensingInfo + + +class ExtractedLicensingInfoConverter(TypedConverter[ExtractedLicensingInfo]): + def _get_property_value( + self, + extracted_licensing_info: ExtractedLicensingInfo, + extracted_licensing_info_property: ExtractedLicensingInfoProperty, + document: Document = None, + ) -> Any: + if extracted_licensing_info_property == ExtractedLicensingInfoProperty.COMMENT: + return extracted_licensing_info.comment + elif extracted_licensing_info_property == ExtractedLicensingInfoProperty.EXTRACTED_TEXT: + return extracted_licensing_info.extracted_text + elif extracted_licensing_info_property == ExtractedLicensingInfoProperty.LICENSE_ID: + return extracted_licensing_info.license_id + elif extracted_licensing_info_property == ExtractedLicensingInfoProperty.NAME: + return apply_if_present(str, extracted_licensing_info.license_name) + elif extracted_licensing_info_property == ExtractedLicensingInfoProperty.SEE_ALSOS: + return extracted_licensing_info.cross_references or None + + def get_json_type(self) -> Type[JsonProperty]: + return ExtractedLicensingInfoProperty + + def get_data_model_type(self) -> Type[ExtractedLicensingInfo]: + return ExtractedLicensingInfo diff --git a/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_properties.py b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_properties.py new file mode 100644 index 000000000..b692c6ec3 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_properties.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class ExtractedLicensingInfoProperty(JsonProperty): + COMMENT = auto() + EXTRACTED_TEXT = auto() + LICENSE_ID = auto() + NAME = auto() + SEE_ALSOS = auto() diff --git a/src/spdx_tools/spdx/jsonschema/file_converter.py b/src/spdx_tools/spdx/jsonschema/file_converter.py new file mode 100644 index 000000000..7c8ae4ad1 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/file_converter.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.file_properties import FileProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.model import Document, File + + +class FileConverter(TypedConverter[File]): + annotation_converter: AnnotationConverter + checksum_converter: ChecksumConverter + + def __init__(self): + self.annotation_converter = AnnotationConverter() + self.checksum_converter = ChecksumConverter() + + def json_property_name(self, file_property: FileProperty) -> str: + if file_property == FileProperty.SPDX_ID: + return "SPDXID" + return super().json_property_name(file_property) + + def _get_property_value(self, file: Any, file_property: FileProperty, document: Document = None) -> Any: + if file_property == FileProperty.SPDX_ID: + return file.spdx_id + elif file_property == FileProperty.ANNOTATIONS: + file_annotations = filter(lambda annotation: annotation.spdx_id == file.spdx_id, document.annotations) + return [self.annotation_converter.convert(annotation) for annotation in file_annotations] or None + elif file_property == FileProperty.ARTIFACT_OFS: + # Deprecated property, automatically converted during parsing + pass + elif file_property == FileProperty.ATTRIBUTION_TEXTS: + return file.attribution_texts or None + elif file_property == FileProperty.CHECKSUMS: + return [self.checksum_converter.convert(checksum) for checksum in file.checksums] or None + elif file_property == FileProperty.COMMENT: + return file.comment + elif file_property == FileProperty.COPYRIGHT_TEXT: + return apply_if_present(str, file.copyright_text) + elif file_property == FileProperty.FILE_CONTRIBUTORS: + return file.contributors or None + elif file_property == FileProperty.FILE_DEPENDENCIES: + # Deprecated property, automatically converted during parsing + pass + elif file_property == FileProperty.FILE_NAME: + return file.name + elif file_property == FileProperty.FILE_TYPES: + return [file_type.name for file_type in file.file_types] or None + elif file_property == FileProperty.LICENSE_COMMENTS: + return file.license_comment + elif file_property == FileProperty.LICENSE_CONCLUDED: + return apply_if_present(str, file.license_concluded) + elif file_property == FileProperty.LICENSE_INFO_IN_FILES: + return [str(license_expression) for license_expression in file.license_info_in_file] or None + elif file_property == FileProperty.NOTICE_TEXT: + return file.notice + + def get_json_type(self) -> Type[JsonProperty]: + return FileProperty + + def get_data_model_type(self) -> Type[File]: + return File + + def requires_full_document(self) -> bool: + return True diff --git a/src/spdx_tools/spdx/jsonschema/file_properties.py b/src/spdx_tools/spdx/jsonschema/file_properties.py new file mode 100644 index 000000000..c1d584eb5 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/file_properties.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class FileProperty(JsonProperty): + SPDX_ID = auto() + ANNOTATIONS = auto() + ARTIFACT_OFS = auto() + ATTRIBUTION_TEXTS = auto() + CHECKSUMS = auto() + COMMENT = auto() + COPYRIGHT_TEXT = auto() + FILE_CONTRIBUTORS = auto() + FILE_DEPENDENCIES = auto() + FILE_NAME = auto() + FILE_TYPES = auto() + LICENSE_COMMENTS = auto() + LICENSE_CONCLUDED = auto() + LICENSE_INFO_IN_FILES = auto() + NOTICE_TEXT = auto() diff --git a/src/spdx_tools/spdx/jsonschema/json_property.py b/src/spdx_tools/spdx/jsonschema/json_property.py new file mode 100644 index 000000000..9bdbe1265 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/json_property.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum + + +class JsonProperty(Enum): + """ + Parent class for all json property classes. Not meant to be instantiated directly, only to have a common parent + type that can be used in type hints. + In general, all the child enums list the properties of the corresponding objects from the json schema. + """ + + pass diff --git a/src/spdx_tools/spdx/jsonschema/optional_utils.py b/src/spdx_tools/spdx/jsonschema/optional_utils.py new file mode 100644 index 000000000..3d3f9e223 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/optional_utils.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Callable, Optional, TypeVar + +T = TypeVar("T") +S = TypeVar("S") + + +def apply_if_present(function: Callable[[T], S], optional_value: Optional[T]) -> Optional[S]: + """ + Apply the passed function to the optional value if it is not None. Else returns None. + """ + return function(optional_value) if optional_value is not None else None diff --git a/src/spdx_tools/spdx/jsonschema/package_converter.py b/src/spdx_tools/spdx/jsonschema/package_converter.py new file mode 100644 index 000000000..074fc7a78 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/package_converter.py @@ -0,0 +1,112 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.external_package_ref_converter import ExternalPackageRefConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.jsonschema.package_properties import PackageProperty +from spdx_tools.spdx.jsonschema.package_verification_code_converter import PackageVerificationCodeConverter +from spdx_tools.spdx.model import Actor, Document, Package + + +class PackageConverter(TypedConverter[Package]): + annotation_converter: AnnotationConverter + checksum_converter: ChecksumConverter + external_package_ref_converter: ExternalPackageRefConverter + package_verification_code_converter: PackageVerificationCodeConverter + + def __init__(self): + self.annotation_converter = AnnotationConverter() + self.checksum_converter = ChecksumConverter() + self.external_package_ref_converter = ExternalPackageRefConverter() + self.package_verification_code_converter = PackageVerificationCodeConverter() + + def json_property_name(self, package_property: PackageProperty) -> str: + if package_property == PackageProperty.SPDX_ID: + return "SPDXID" + return super().json_property_name(package_property) + + def _get_property_value( + self, package: Package, package_property: PackageProperty, document: Document = None + ) -> Any: + if package_property == PackageProperty.SPDX_ID: + return package.spdx_id + elif package_property == PackageProperty.ANNOTATIONS: + package_annotations = filter( + lambda annotation: annotation.spdx_id == package.spdx_id, document.annotations + ) + return [ + self.annotation_converter.convert(annotation, document) for annotation in package_annotations + ] or None + elif package_property == PackageProperty.ATTRIBUTION_TEXTS: + return package.attribution_texts or None + elif package_property == PackageProperty.BUILT_DATE: + return apply_if_present(datetime_to_iso_string, package.built_date) + elif package_property == PackageProperty.CHECKSUMS: + return [self.checksum_converter.convert(checksum, document) for checksum in package.checksums] or None + elif package_property == PackageProperty.COMMENT: + return package.comment + elif package_property == PackageProperty.COPYRIGHT_TEXT: + return apply_if_present(str, package.copyright_text) + elif package_property == PackageProperty.DESCRIPTION: + return package.description + elif package_property == PackageProperty.DOWNLOAD_LOCATION: + return str(package.download_location) + elif package_property == PackageProperty.EXTERNAL_REFS: + return [ + self.external_package_ref_converter.convert(external_ref) + for external_ref in package.external_references + ] or None + elif package_property == PackageProperty.FILES_ANALYZED: + return package.files_analyzed + elif package_property == PackageProperty.HOMEPAGE: + return apply_if_present(str, package.homepage) + elif package_property == PackageProperty.LICENSE_COMMENTS: + return package.license_comment + elif package_property == PackageProperty.LICENSE_CONCLUDED: + return apply_if_present(str, package.license_concluded) + elif package_property == PackageProperty.LICENSE_DECLARED: + return apply_if_present(str, package.license_declared) + elif package_property == PackageProperty.LICENSE_INFO_FROM_FILES: + return [str(license_expression) for license_expression in package.license_info_from_files] or None + elif package_property == PackageProperty.NAME: + return package.name + elif package_property == PackageProperty.ORIGINATOR: + if isinstance(package.originator, Actor): + return package.originator.to_serialized_string() + return apply_if_present(str, package.originator) + elif package_property == PackageProperty.PACKAGE_FILE_NAME: + return package.file_name + elif package_property == PackageProperty.PACKAGE_VERIFICATION_CODE: + return apply_if_present(self.package_verification_code_converter.convert, package.verification_code) + elif package_property == PackageProperty.PRIMARY_PACKAGE_PURPOSE: + return package.primary_package_purpose.name if package.primary_package_purpose is not None else None + elif package_property == PackageProperty.RELEASE_DATE: + return apply_if_present(datetime_to_iso_string, package.release_date) + elif package_property == PackageProperty.SOURCE_INFO: + return package.source_info + elif package_property == PackageProperty.SUMMARY: + return package.summary + elif package_property == PackageProperty.SUPPLIER: + if isinstance(package.supplier, Actor): + return package.supplier.to_serialized_string() + return apply_if_present(str, package.supplier) + elif package_property == PackageProperty.VALID_UNTIL_DATE: + return apply_if_present(datetime_to_iso_string, package.valid_until_date) + elif package_property == PackageProperty.VERSION_INFO: + return package.version + + def get_json_type(self) -> Type[JsonProperty]: + return PackageProperty + + def get_data_model_type(self) -> Type[Package]: + return Package + + def requires_full_document(self) -> bool: + return True diff --git a/src/spdx_tools/spdx/jsonschema/package_properties.py b/src/spdx_tools/spdx/jsonschema/package_properties.py new file mode 100644 index 000000000..903fb1968 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/package_properties.py @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class PackageProperty(JsonProperty): + SPDX_ID = auto() + ANNOTATIONS = auto() + ATTRIBUTION_TEXTS = auto() + BUILT_DATE = auto() + CHECKSUMS = auto() + COMMENT = auto() + COPYRIGHT_TEXT = auto() + DESCRIPTION = auto() + DOWNLOAD_LOCATION = auto() + EXTERNAL_REFS = auto() + FILES_ANALYZED = auto() + HOMEPAGE = auto() + LICENSE_COMMENTS = auto() + LICENSE_CONCLUDED = auto() + LICENSE_DECLARED = auto() + LICENSE_INFO_FROM_FILES = auto() + NAME = auto() + ORIGINATOR = auto() + PACKAGE_FILE_NAME = auto() + PACKAGE_VERIFICATION_CODE = auto() + PRIMARY_PACKAGE_PURPOSE = auto() + RELEASE_DATE = auto() + SOURCE_INFO = auto() + SUMMARY = auto() + SUPPLIER = auto() + VALID_UNTIL_DATE = auto() + VERSION_INFO = auto() diff --git a/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py b/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py new file mode 100644 index 000000000..b98396272 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.package_verification_code_properties import PackageVerificationCodeProperty +from spdx_tools.spdx.model import Document, PackageVerificationCode + + +class PackageVerificationCodeConverter(TypedConverter[PackageVerificationCode]): + def _get_property_value( + self, + verification_code: PackageVerificationCode, + verification_code_property: PackageVerificationCodeProperty, + document: Document = None, + ) -> Any: + if verification_code_property == PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES: + return verification_code.excluded_files or None + elif verification_code_property == PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_VALUE: + return verification_code.value + + def get_json_type(self) -> Type[JsonProperty]: + return PackageVerificationCodeProperty + + def get_data_model_type(self) -> Type[PackageVerificationCode]: + return PackageVerificationCode diff --git a/src/spdx_tools/spdx/jsonschema/package_verification_code_properties.py b/src/spdx_tools/spdx/jsonschema/package_verification_code_properties.py new file mode 100644 index 000000000..f73410385 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/package_verification_code_properties.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class PackageVerificationCodeProperty(JsonProperty): + PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES = auto() + PACKAGE_VERIFICATION_CODE_VALUE = auto() diff --git a/src/spdx_tools/spdx/jsonschema/relationship_converter.py b/src/spdx_tools/spdx/jsonschema/relationship_converter.py new file mode 100644 index 000000000..78442d25b --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/relationship_converter.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Type + +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.relationship_properties import RelationshipProperty +from spdx_tools.spdx.model import Document, Relationship + + +class RelationshipConverter(TypedConverter[Relationship]): + def _get_property_value( + self, relationship: Relationship, relationship_property: RelationshipProperty, document: Document = None + ) -> Any: + if relationship_property == RelationshipProperty.SPDX_ELEMENT_ID: + return relationship.spdx_element_id + elif relationship_property == RelationshipProperty.COMMENT: + return relationship.comment + elif relationship_property == RelationshipProperty.RELATED_SPDX_ELEMENT: + return str(relationship.related_spdx_element_id) + elif relationship_property == RelationshipProperty.RELATIONSHIP_TYPE: + return relationship.relationship_type.name + + def get_json_type(self) -> Type[JsonProperty]: + return RelationshipProperty + + def get_data_model_type(self) -> Type[Relationship]: + return Relationship diff --git a/src/spdx_tools/spdx/jsonschema/relationship_properties.py b/src/spdx_tools/spdx/jsonschema/relationship_properties.py new file mode 100644 index 000000000..73c1259e9 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/relationship_properties.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class RelationshipProperty(JsonProperty): + SPDX_ELEMENT_ID = auto() + COMMENT = auto() + RELATED_SPDX_ELEMENT = auto() + RELATIONSHIP_TYPE = auto() diff --git a/src/spdx_tools/spdx/jsonschema/snippet_converter.py b/src/spdx_tools/spdx/jsonschema/snippet_converter.py new file mode 100644 index 000000000..a4e75c4fa --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/snippet_converter.py @@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Dict, Tuple, Type + +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.jsonschema.snippet_properties import SnippetProperty +from spdx_tools.spdx.model import Document, Snippet + + +class SnippetConverter(TypedConverter[Snippet]): + annotation_converter: AnnotationConverter + + def __init__(self): + self.annotation_converter = AnnotationConverter() + + def json_property_name(self, snippet_property: SnippetProperty) -> str: + if snippet_property == SnippetProperty.SPDX_ID: + return "SPDXID" + return super().json_property_name(snippet_property) + + def _get_property_value( + self, snippet: Snippet, snippet_property: SnippetProperty, document: Document = None + ) -> Any: + if snippet_property == SnippetProperty.SPDX_ID: + return snippet.spdx_id + elif snippet_property == SnippetProperty.ANNOTATIONS: + snippet_annotations = filter( + lambda annotation: annotation.spdx_id == snippet.spdx_id, document.annotations + ) + return [self.annotation_converter.convert(annotation) for annotation in snippet_annotations] or None + elif snippet_property == SnippetProperty.ATTRIBUTION_TEXTS: + return snippet.attribution_texts or None + elif snippet_property == SnippetProperty.COMMENT: + return snippet.comment + elif snippet_property == SnippetProperty.COPYRIGHT_TEXT: + return apply_if_present(str, snippet.copyright_text) + elif snippet_property == SnippetProperty.LICENSE_COMMENTS: + return snippet.license_comment + elif snippet_property == SnippetProperty.LICENSE_CONCLUDED: + return apply_if_present(str, snippet.license_concluded) + elif snippet_property == SnippetProperty.LICENSE_INFO_IN_SNIPPETS: + return [str(license_expression) for license_expression in snippet.license_info_in_snippet] or None + elif snippet_property == SnippetProperty.NAME: + return snippet.name + elif snippet_property == SnippetProperty.RANGES: + ranges = [convert_byte_range_to_dict(snippet.byte_range, snippet.file_spdx_id)] + if snippet.line_range: + ranges.append(convert_line_range_to_dict(snippet.line_range, snippet.file_spdx_id)) + return ranges + elif snippet_property == SnippetProperty.SNIPPET_FROM_FILE: + return snippet.file_spdx_id + + def get_json_type(self) -> Type[JsonProperty]: + return SnippetProperty + + def get_data_model_type(self) -> Type[Snippet]: + return Snippet + + def requires_full_document(self) -> bool: + return True + + +def convert_line_range_to_dict(line_range: Tuple[int, int], file_id: str) -> Dict: + return _convert_range_to_dict(line_range, file_id, "lineNumber") + + +def convert_byte_range_to_dict(byte_range: Tuple[int, int], file_id: str) -> Dict: + return _convert_range_to_dict(byte_range, file_id, "offset") + + +def _convert_range_to_dict(int_range: Tuple[int, int], file_id: str, pointer_property: str) -> Dict: + return { + "startPointer": _pointer(file_id, int_range[0], pointer_property), + "endPointer": _pointer(file_id, int_range[1], pointer_property), + } + + +def _pointer(reference: str, target: int, pointer_property: str) -> Dict: + return {"reference": reference, pointer_property: target} diff --git a/src/spdx_tools/spdx/jsonschema/snippet_properties.py b/src/spdx_tools/spdx/jsonschema/snippet_properties.py new file mode 100644 index 000000000..772a58401 --- /dev/null +++ b/src/spdx_tools/spdx/jsonschema/snippet_properties.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto + +from spdx_tools.spdx.jsonschema.json_property import JsonProperty + + +class SnippetProperty(JsonProperty): + SPDX_ID = auto() + ANNOTATIONS = auto() + ATTRIBUTION_TEXTS = auto() + COMMENT = auto() + COPYRIGHT_TEXT = auto() + LICENSE_COMMENTS = auto() + LICENSE_CONCLUDED = auto() + LICENSE_INFO_IN_SNIPPETS = auto() + NAME = auto() + RANGES = auto() + SNIPPET_FROM_FILE = auto() diff --git a/src/spdx_tools/spdx/model/__init__.py b/src/spdx_tools/spdx/model/__init__.py new file mode 100644 index 000000000..e27a116d0 --- /dev/null +++ b/src/spdx_tools/spdx/model/__init__.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.model.package import ( + ExternalPackageRef, + ExternalPackageRefCategory, + Package, + PackagePurpose, + PackageVerificationCode, +) +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model.document import CreationInfo, Document diff --git a/src/spdx_tools/spdx/model/actor.py b/src/spdx_tools/spdx/model/actor.py new file mode 100644 index 000000000..9aeb9e059 --- /dev/null +++ b/src/spdx_tools/spdx/model/actor.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto + +from beartype.typing import Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values + + +class ActorType(Enum): + PERSON = auto() + ORGANIZATION = auto() + TOOL = auto() + + +@dataclass_with_properties +class Actor: + actor_type: ActorType + name: str + email: Optional[str] = None + + def __init__(self, actor_type: ActorType, name: str, email: Optional[str] = None): + check_types_and_set_values(self, locals()) + + def to_serialized_string(self) -> str: + """ + All serialization formats use the same representation of an actor, so this method is included in the data model + """ + optional_email = f" ({self.email})" if self.email else "" + return "".join([f"{self.actor_type.name.title()}:", f" {self.name}", optional_email]) + + def __str__(self): + return self.to_serialized_string() diff --git a/src/spdx_tools/spdx/model/annotation.py b/src/spdx_tools/spdx/model/annotation.py new file mode 100644 index 000000000..6ada0607b --- /dev/null +++ b/src/spdx_tools/spdx/model/annotation.py @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import Enum, auto + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model import Actor + + +class AnnotationType(Enum): + REVIEW = auto() + OTHER = auto() + + +@dataclass_with_properties +class Annotation: + spdx_id: str + annotation_type: AnnotationType + annotator: Actor + annotation_date: datetime + annotation_comment: str + + def __init__( + self, + spdx_id: str, + annotation_type: AnnotationType, + annotator: Actor, + annotation_date: datetime, + annotation_comment: str, + ): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx/model/checksum.py b/src/spdx_tools/spdx/model/checksum.py new file mode 100644 index 000000000..7889e1163 --- /dev/null +++ b/src/spdx_tools/spdx/model/checksum.py @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values + + +class ChecksumAlgorithm(Enum): + SHA1 = auto() + SHA224 = auto() + SHA256 = auto() + SHA384 = auto() + SHA512 = auto() + SHA3_256 = auto() + SHA3_384 = auto() + SHA3_512 = auto() + BLAKE2B_256 = auto() + BLAKE2B_384 = auto() + BLAKE2B_512 = auto() + BLAKE3 = auto() + MD2 = auto() + MD4 = auto() + MD5 = auto() + MD6 = auto() + ADLER32 = auto() + + +@dataclass_with_properties +class Checksum: + algorithm: ChecksumAlgorithm + value: str + + def __init__(self, algorithm: ChecksumAlgorithm, value: str): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx/model/document.py b/src/spdx_tools/spdx/model/document.py new file mode 100644 index 000000000..980c59ca5 --- /dev/null +++ b/src/spdx_tools/spdx/model/document.py @@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model import ( + Actor, + Annotation, + ExternalDocumentRef, + ExtractedLicensingInfo, + File, + Package, + Relationship, + Snippet, + Version, +) + + +@dataclass_with_properties +class CreationInfo: + spdx_version: str + spdx_id: str + name: str + document_namespace: str + creators: List[Actor] + created: datetime + creator_comment: Optional[str] = None + data_license: str = "CC0-1.0" + external_document_refs: List[ExternalDocumentRef] = field(default_factory=list) + license_list_version: Optional[Version] = None + document_comment: Optional[str] = None + + def __init__( + self, + spdx_version: str, + spdx_id: str, + name: str, + document_namespace: str, + creators: List[Actor], + created: datetime, + creator_comment: Optional[str] = None, + data_license: str = "CC0-1.0", + external_document_refs: List[ExternalDocumentRef] = None, + license_list_version: Optional[Version] = None, + document_comment: Optional[str] = None, + ): + external_document_refs = [] if external_document_refs is None else external_document_refs + check_types_and_set_values(self, locals()) + + +@dataclass_with_properties +class Document: + creation_info: CreationInfo + + packages: List[Package] = field(default_factory=list) + files: List[File] = field(default_factory=list) + snippets: List[Snippet] = field(default_factory=list) + annotations: List[Annotation] = field(default_factory=list) + relationships: List[Relationship] = field(default_factory=list) + extracted_licensing_info: List[ExtractedLicensingInfo] = field(default_factory=list) + + def __init__( + self, + creation_info: CreationInfo, + packages: List[Package] = None, + files: List[File] = None, + snippets: List[Snippet] = None, + annotations: List[Annotation] = None, + relationships: List[Relationship] = None, + extracted_licensing_info: List[ExtractedLicensingInfo] = None, + ): + packages = [] if packages is None else packages + files = [] if files is None else files + snippets = [] if snippets is None else snippets + annotations = [] if annotations is None else annotations + relationships = [] if relationships is None else relationships + extracted_licensing_info = [] if extracted_licensing_info is None else extracted_licensing_info + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx/model/external_document_ref.py b/src/spdx_tools/spdx/model/external_document_ref.py new file mode 100644 index 000000000..fbbaf4847 --- /dev/null +++ b/src/spdx_tools/spdx/model/external_document_ref.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model import Checksum + + +@dataclass_with_properties +class ExternalDocumentRef: + document_ref_id: str # of the form "DocumentRef-[idstring]" + document_uri: str + checksum: Checksum + + def __init__(self, document_ref_id: str, document_uri: str, checksum: Checksum): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx/model/extracted_licensing_info.py b/src/spdx_tools/spdx/model/extracted_licensing_info.py new file mode 100644 index 000000000..e401dd7b6 --- /dev/null +++ b/src/spdx_tools/spdx/model/extracted_licensing_info.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field + +from beartype.typing import List, Optional, Union + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model import SpdxNoAssertion + + +@dataclass_with_properties +class ExtractedLicensingInfo: + license_id: Optional[str] = None + extracted_text: Optional[str] = None + license_name: Optional[Union[str, SpdxNoAssertion]] = None + cross_references: List[str] = field(default_factory=list) + comment: Optional[str] = None + + def __init__( + self, + license_id: Optional[str] = None, + extracted_text: Optional[str] = None, + license_name: Optional[Union[str, SpdxNoAssertion]] = None, + cross_references: List[str] = None, + comment: Optional[str] = None, + ): + cross_references = [] if cross_references is None else cross_references + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx/model/file.py b/src/spdx_tools/spdx/model/file.py new file mode 100644 index 000000000..27aae4ca3 --- /dev/null +++ b/src/spdx_tools/spdx/model/file.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from enum import Enum, auto + +from beartype.typing import List, Optional, Union +from license_expression import LicenseExpression + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model import Checksum, SpdxNoAssertion, SpdxNone + + +class FileType(Enum): + SOURCE = auto() + BINARY = auto() + ARCHIVE = auto() + APPLICATION = auto() + AUDIO = auto() + IMAGE = auto() + TEXT = auto() + VIDEO = auto() + DOCUMENTATION = auto() + SPDX = auto() + OTHER = auto() + + +@dataclass_with_properties +class File: + name: str + spdx_id: str + checksums: List[Checksum] + file_types: List[FileType] = field(default_factory=list) + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None + license_info_in_file: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = field(default_factory=list) + license_comment: Optional[str] = None + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None + comment: Optional[str] = None + notice: Optional[str] = None + contributors: List[str] = field(default_factory=list) + attribution_texts: List[str] = field(default_factory=list) + + # Deprecated properties that should be replaced during parsing: + # - file dependencies: replace by a DEPENDENCY_OF relationship (or one of the more precise versions) + # - artifact of (3 properties): replace by an external package reference and a GENERATED_FROM relationship + # between the file and this package + + def __init__( + self, + name: str, + spdx_id: str, + checksums: List[Checksum], + file_types: List[FileType] = None, + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_info_in_file: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_comment: Optional[str] = None, + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, + comment: str = None, + notice: Optional[str] = None, + contributors: List[str] = None, + attribution_texts: List[str] = None, + ): + file_types = [] if file_types is None else file_types + license_info_in_file = [] if license_info_in_file is None else license_info_in_file + contributors = [] if contributors is None else contributors + attribution_texts = [] if attribution_texts is None else attribution_texts + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx/model/package.py b/src/spdx_tools/spdx/model/package.py new file mode 100644 index 000000000..1cf89e607 --- /dev/null +++ b/src/spdx_tools/spdx/model/package.py @@ -0,0 +1,134 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime +from enum import Enum, auto + +from beartype.typing import Dict, List, Optional, Union +from license_expression import LicenseExpression + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model import Actor, Checksum, SpdxNoAssertion, SpdxNone + + +class PackagePurpose(Enum): + APPLICATION = auto() + FRAMEWORK = auto() + LIBRARY = auto() + CONTAINER = auto() + OPERATING_SYSTEM = auto() + DEVICE = auto() + FIRMWARE = auto() + SOURCE = auto() + ARCHIVE = auto() + FILE = auto() + INSTALL = auto() + OTHER = auto() + + +@dataclass_with_properties +class PackageVerificationCode: + value: str + excluded_files: List[str] = field(default_factory=list) + + def __init__(self, value: str, excluded_files: List[str] = None): + excluded_files = [] if excluded_files is None else excluded_files + check_types_and_set_values(self, locals()) + + +class ExternalPackageRefCategory(Enum): + SECURITY = auto() + PACKAGE_MANAGER = auto() + PERSISTENT_ID = auto() + OTHER = auto() + + +CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES: Dict[ExternalPackageRefCategory, List[str]] = { + ExternalPackageRefCategory.SECURITY: ["cpe22Type", "cpe23Type", "advisory", "fix", "url", "swid"], + ExternalPackageRefCategory.PACKAGE_MANAGER: ["maven-central", "npm", "nuget", "bower", "purl"], + ExternalPackageRefCategory.PERSISTENT_ID: ["swh", "gitoid"], + ExternalPackageRefCategory.OTHER: [], +} + + +@dataclass_with_properties +class ExternalPackageRef: + category: ExternalPackageRefCategory + # In theory, once could refine the typing, + # see https://spdx.github.io/spdx-spec/v2.3/external-repository-identifiers/. But it's probably not worth the + # effort. + reference_type: str + locator: str + comment: Optional[str] = None + + def __init__( + self, category: ExternalPackageRefCategory, reference_type: str, locator: str, comment: Optional[str] = None + ): + check_types_and_set_values(self, locals()) + + +@dataclass_with_properties +class Package: + spdx_id: str + name: str + download_location: Union[str, SpdxNoAssertion, SpdxNone] + version: Optional[str] = None + file_name: Optional[str] = None + supplier: Optional[Union[Actor, SpdxNoAssertion]] = None + originator: Optional[Union[Actor, SpdxNoAssertion]] = None + files_analyzed: bool = True + verification_code: Optional[PackageVerificationCode] = None + checksums: List[Checksum] = field(default_factory=list) + homepage: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None + source_info: Optional[str] = None + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None + license_info_from_files: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = field(default_factory=list) + license_declared: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None + license_comment: Optional[str] = None + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None + summary: Optional[str] = None + description: Optional[str] = None + comment: Optional[str] = None + external_references: List[ExternalPackageRef] = field(default_factory=list) + attribution_texts: List[str] = field(default_factory=list) + primary_package_purpose: Optional[PackagePurpose] = None + release_date: Optional[datetime] = None + built_date: Optional[datetime] = None + valid_until_date: Optional[datetime] = None + + def __init__( + self, + spdx_id: str, + name: str, + download_location: Union[str, SpdxNoAssertion, SpdxNone], + version: Optional[str] = None, + file_name: Optional[str] = None, + supplier: Optional[Union[Actor, SpdxNoAssertion]] = None, + originator: Optional[Union[Actor, SpdxNoAssertion]] = None, + files_analyzed: bool = True, + verification_code: Optional[PackageVerificationCode] = None, + checksums: List[Checksum] = None, + homepage: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, + source_info: Optional[str] = None, + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_info_from_files: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_declared: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_comment: Optional[str] = None, + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + external_references: List[ExternalPackageRef] = None, + attribution_texts: List[str] = None, + primary_package_purpose: Optional[PackagePurpose] = None, + release_date: Optional[datetime] = None, + built_date: Optional[datetime] = None, + valid_until_date: Optional[datetime] = None, + ): + checksums = [] if checksums is None else checksums + license_info_from_files = [] if license_info_from_files is None else license_info_from_files + external_references = [] if external_references is None else external_references + attribution_texts = [] if attribution_texts is None else attribution_texts + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx/model/relationship.py b/src/spdx_tools/spdx/model/relationship.py new file mode 100644 index 000000000..02b1326a9 --- /dev/null +++ b/src/spdx_tools/spdx/model/relationship.py @@ -0,0 +1,75 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto + +from beartype.typing import Optional, Union + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone + + +class RelationshipType(Enum): + AMENDS = auto() + ANCESTOR_OF = auto() + BUILD_DEPENDENCY_OF = auto() + BUILD_TOOL_OF = auto() + CONTAINED_BY = auto() + CONTAINS = auto() + COPY_OF = auto() + DATA_FILE_OF = auto() + DEPENDENCY_MANIFEST_OF = auto() + DEPENDENCY_OF = auto() + DEPENDS_ON = auto() + DESCENDANT_OF = auto() + DESCRIBED_BY = auto() + DESCRIBES = auto() + DEV_DEPENDENCY_OF = auto() + DEV_TOOL_OF = auto() + DISTRIBUTION_ARTIFACT = auto() + DOCUMENTATION_OF = auto() + DYNAMIC_LINK = auto() + EXAMPLE_OF = auto() + EXPANDED_FROM_ARCHIVE = auto() + FILE_ADDED = auto() + FILE_DELETED = auto() + FILE_MODIFIED = auto() + GENERATED_FROM = auto() + GENERATES = auto() + HAS_PREREQUISITE = auto() + METAFILE_OF = auto() + OPTIONAL_COMPONENT_OF = auto() + OPTIONAL_DEPENDENCY_OF = auto() + OTHER = auto() + PACKAGE_OF = auto() + PATCH_APPLIED = auto() + PATCH_FOR = auto() + PREREQUISITE_FOR = auto() + PROVIDED_DEPENDENCY_OF = auto() + REQUIREMENT_DESCRIPTION_FOR = auto() + RUNTIME_DEPENDENCY_OF = auto() + SPECIFICATION_FOR = auto() + STATIC_LINK = auto() + TEST_CASE_OF = auto() + TEST_DEPENDENCY_OF = auto() + TEST_OF = auto() + TEST_TOOL_OF = auto() + VARIANT_OF = auto() + + +@dataclass_with_properties +class Relationship: + spdx_element_id: str + relationship_type: RelationshipType + related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion] + comment: Optional[str] = None + + def __init__( + self, + spdx_element_id: str, + relationship_type: RelationshipType, + related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion], + comment: Optional[str] = None, + ): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx/model/relationship_filters.py b/src/spdx_tools/spdx/model/relationship_filters.py new file mode 100644 index 000000000..8858fb038 --- /dev/null +++ b/src/spdx_tools/spdx/model/relationship_filters.py @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + +from spdx_tools.spdx.model import Document, Package, Relationship, RelationshipType + + +def find_package_contains_file_relationships(document: Document, package: Package) -> List[Relationship]: + file_ids_in_document = [file.spdx_id for file in document.files] + package_contains_relationships = filter_by_type_and_origin( + document.relationships, RelationshipType.CONTAINS, package.spdx_id + ) + return [ + relationship + for relationship in package_contains_relationships + if relationship.related_spdx_element_id in file_ids_in_document + ] + + +def find_file_contained_by_package_relationships(document: Document, package: Package) -> List[Relationship]: + file_ids_in_document = [file.spdx_id for file in document.files] + contained_by_package_relationships = filter_by_type_and_target( + document.relationships, RelationshipType.CONTAINED_BY, package.spdx_id + ) + return [ + relationship + for relationship in contained_by_package_relationships + if relationship.spdx_element_id in file_ids_in_document + ] + + +def filter_by_type_and_target( + relationships: List[Relationship], relationship_type: RelationshipType, target_id: str +) -> List[Relationship]: + return [ + relationship + for relationship in relationships + if relationship.relationship_type == relationship_type and relationship.related_spdx_element_id == target_id + ] + + +def filter_by_type_and_origin( + relationships: List[Relationship], relationship_type: RelationshipType, origin_id: str +) -> List[Relationship]: + return [ + relationship + for relationship in relationships + if relationship.relationship_type == relationship_type and relationship.spdx_element_id == origin_id + ] diff --git a/src/spdx_tools/spdx/model/snippet.py b/src/spdx_tools/spdx/model/snippet.py new file mode 100644 index 000000000..5a1669f4a --- /dev/null +++ b/src/spdx_tools/spdx/model/snippet.py @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field + +from beartype.typing import List, Optional, Tuple, Union +from license_expression import LicenseExpression + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone + + +@dataclass_with_properties +class Snippet: + spdx_id: str + file_spdx_id: str + byte_range: Tuple[int, int] + line_range: Optional[Tuple[int, int]] = None + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None + license_info_in_snippet: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None + license_comment: Optional[str] = None + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None + comment: Optional[str] = None + name: Optional[str] = None + attribution_texts: List[str] = field(default_factory=list) + + def __init__( + self, + spdx_id: str, + file_spdx_id: str, + byte_range: Tuple[int, int], + line_range: Optional[Tuple[int, int]] = None, + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_info_in_snippet: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_comment: Optional[str] = None, + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, + comment: Optional[str] = None, + name: Optional[str] = None, + attribution_texts: List[str] = None, + ): + attribution_texts = [] if attribution_texts is None else attribution_texts + license_info_in_snippet = [] if license_info_in_snippet is None else license_info_in_snippet + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx/model/spdx_no_assertion.py b/src/spdx_tools/spdx/model/spdx_no_assertion.py new file mode 100644 index 000000000..1255dba35 --- /dev/null +++ b/src/spdx_tools/spdx/model/spdx_no_assertion.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +SPDX_NO_ASSERTION_STRING = "NOASSERTION" + + +class SpdxNoAssertion: + """ + Represents the SPDX NOASSERTION value. + """ + + def __str__(self): + return SPDX_NO_ASSERTION_STRING + + def __repr__(self): + return SPDX_NO_ASSERTION_STRING + + def __eq__(self, other): + return isinstance(other, SpdxNoAssertion) diff --git a/src/spdx_tools/spdx/model/spdx_none.py b/src/spdx_tools/spdx/model/spdx_none.py new file mode 100644 index 000000000..25f63099f --- /dev/null +++ b/src/spdx_tools/spdx/model/spdx_none.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +SPDX_NONE_STRING = "NONE" + + +class SpdxNone: + """ + Represents the SPDX NONE value. + """ + + def __str__(self): + return SPDX_NONE_STRING + + def __repr__(self): + return SPDX_NONE_STRING + + def __eq__(self, other): + return isinstance(other, SpdxNone) diff --git a/src/spdx_tools/spdx/model/version.py b/src/spdx_tools/spdx/model/version.py new file mode 100644 index 000000000..c3874246b --- /dev/null +++ b/src/spdx_tools/spdx/model/version.py @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + + +import re +from re import Pattern + + +class Version: + VERSION_REGEX: Pattern = re.compile(r"^(\d+)\.(\d+)$") + + major: int + minor: int + + @classmethod + def is_valid_version_string(cls, value: str) -> bool: + return cls.VERSION_REGEX.match(value) is not None + + # No type hint for Python reasons. + # See https://stackoverflow.com/questions/33533148/how-do-i-type-hint-a-method-with-the-type-of-the-enclosing-class + @classmethod + def from_string(cls, value: str): + if not Version.is_valid_version_string(value): + raise ValueError(f"{value} is not a valid version string") + + match = cls.VERSION_REGEX.match(value) + return cls(int(match.group(1)), int(match.group(2))) + + def __init__(self, major: int, minor: int): + self.major = major + self.minor = minor + + def __str__(self): + return f"{self.major}.{self.minor}" + + def __eq__(self, other): + if not isinstance(other, Version): + return False + return self.major == other.major and self.minor == other.minor diff --git a/src/spdx_tools/spdx/parser/__init__.py b/src/spdx_tools/spdx/parser/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/parser/actor_parser.py b/src/spdx_tools/spdx/parser/actor_parser.py new file mode 100644 index 000000000..14cc4ffb0 --- /dev/null +++ b/src/spdx_tools/spdx/parser/actor_parser.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import re + +from beartype.typing import Match, Pattern + +from spdx_tools.spdx.model import Actor, ActorType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.parsing_functions import construct_or_raise_parsing_error + + +class ActorParser: + @staticmethod + def parse_actor(actor: str) -> Actor: + tool_re: Pattern = re.compile(r"^Tool:\s*(.+)", re.UNICODE) + person_re: Pattern = re.compile(r"^Person:\s*(?:(.*)\((.*)\)|(.*))$", re.UNICODE) + org_re: Pattern = re.compile(r"^Organization:\s*(?:(.*)\((.*)\)|(.*))$", re.UNICODE) + tool_match: Match = tool_re.match(actor) + person_match: Match = person_re.match(actor) + org_match: Match = org_re.match(actor) + + if tool_match: + name: str = tool_match.group(1).strip() + if not name: + raise SPDXParsingError([f"No name for Tool provided: {actor}."]) + return construct_or_raise_parsing_error(Actor, dict(actor_type=ActorType.TOOL, name=name)) + + if person_match: + actor_type = ActorType.PERSON + match = person_match + elif org_match: + actor_type = ActorType.ORGANIZATION + match = org_match + else: + raise SPDXParsingError([f"Actor {actor} doesn't match any of person, organization or tool."]) + + if match.group(3): + return construct_or_raise_parsing_error( + Actor, dict(actor_type=actor_type, name=match.group(3).strip(), email=None) + ) + else: + name = match.group(1) + if not name: + raise SPDXParsingError([f"No name for Actor provided: {actor}."]) + else: + name = name.strip() + + email = match.group(2).strip() + + return construct_or_raise_parsing_error( + Actor, dict(actor_type=actor_type, name=name, email=email if email else None) + ) diff --git a/src/spdx_tools/spdx/parser/error.py b/src/spdx_tools/spdx/parser/error.py new file mode 100644 index 000000000..1e58c1122 --- /dev/null +++ b/src/spdx_tools/spdx/parser/error.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + + +class SPDXParsingError(Exception): + messages: List[str] + + def __init__(self, messages: List[str]): + self.messages = messages + + def get_messages(self): + return list(self.messages) diff --git a/src/spdx_tools/spdx/parser/json/__init__.py b/src/spdx_tools/spdx/parser/json/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/parser/json/json_parser.py b/src/spdx_tools/spdx/parser/json/json_parser.py new file mode 100644 index 000000000..219ccfed2 --- /dev/null +++ b/src/spdx_tools/spdx/parser/json/json_parser.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import json + +from beartype.typing import Dict + +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser + + +def parse_from_file(file_name: str, encoding: str = "utf-8") -> Document: + with open(file_name, encoding=encoding) as file: + input_doc_as_dict: Dict = json.load(file) + + return JsonLikeDictParser().parse(input_doc_as_dict) diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/__init__.py b/src/spdx_tools/spdx/parser/jsonlikedict/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py new file mode 100644 index 000000000..38ccac3ff --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py @@ -0,0 +1,125 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import Dict, List, Optional + +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model import Actor, Annotation, AnnotationType +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( + append_parsed_field_or_log_error, + parse_field_or_log_error, +) +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) + + +class AnnotationParser: + logger: Logger + actor_parser: ActorParser + + def __init__(self): + self.logger = Logger() + self.actor_parser = ActorParser() + + def parse_all_annotations(self, input_doc_dict: Dict) -> List[Annotation]: + annotations = [] + self.parse_annotations_from_object(annotations, [input_doc_dict]) + reviews: List[Dict] = input_doc_dict.get("revieweds", []) + for review in reviews: + annotations = append_parsed_field_or_log_error( + self.logger, annotations, review, lambda x: self.parse_review(x, spdx_id=input_doc_dict.get("SPDXID")) + ) + packages: List[Dict] = input_doc_dict.get("packages", []) + self.parse_annotations_from_object(annotations, packages) + files: List[Dict] = input_doc_dict.get("files", []) + self.parse_annotations_from_object(annotations, files) + snippets: List[Dict] = input_doc_dict.get("snippets", []) + self.parse_annotations_from_object(annotations, snippets) + + raise_parsing_error_if_logger_has_messages(self.logger, "annotations") + return annotations + + def parse_annotations_from_object(self, annotations: List[Annotation], element_list: List[Dict]): + for element in element_list: + element_spdx_id: Optional[str] = element.get("SPDXID") + element_annotations: List[Dict] = element.get("annotations", []) + annotations.extend( + parse_field_or_log_error( + self.logger, + element_annotations, + lambda y: self.parse_annotation(y, spdx_id=element_spdx_id), + [], + True, + ) + ) + + def parse_annotation(self, annotation_dict: Dict, spdx_id: Optional[str] = None) -> Annotation: + logger = Logger() + spdx_id: Optional[str] = annotation_dict.get("SPDXID") or spdx_id + + annotation_type: Optional[AnnotationType] = parse_field_or_log_error( + logger, annotation_dict.get("annotationType"), self.parse_annotation_type + ) + + annotator: Optional[Actor] = parse_field_or_log_error( + logger, annotation_dict.get("annotator"), self.actor_parser.parse_actor + ) + + annotation_date: Optional[datetime] = parse_field_or_log_error( + logger, annotation_dict.get("annotationDate"), datetime_from_str + ) + + annotation_comment: Optional[str] = annotation_dict.get("comment") + raise_parsing_error_if_logger_has_messages(logger, "Annotation") + annotation_dict = construct_or_raise_parsing_error( + Annotation, + dict( + spdx_id=spdx_id, + annotation_type=annotation_type, + annotator=annotator, + annotation_date=annotation_date, + annotation_comment=annotation_comment, + ), + ) + + return annotation_dict + + @staticmethod + def parse_annotation_type(annotation_type: str) -> AnnotationType: + try: + return AnnotationType[annotation_type] + except KeyError: + raise SPDXParsingError([f"Invalid AnnotationType: {annotation_type}"]) + + def parse_review(self, review_dict: Dict, spdx_id: str) -> Annotation: + logger = Logger() + annotator: Optional[Actor] = parse_field_or_log_error( + logger, review_dict.get("reviewer"), self.actor_parser.parse_actor + ) + + annotation_date: Optional[datetime] = parse_field_or_log_error( + logger, review_dict.get("reviewDate"), datetime_from_str + ) + + annotation_type = AnnotationType.REVIEW + comment: Optional[str] = review_dict.get("comment") + raise_parsing_error_if_logger_has_messages(logger, "Annotation from revieweds") + + annotation = construct_or_raise_parsing_error( + Annotation, + dict( + spdx_id=spdx_id, + annotation_type=annotation_type, + annotator=annotator, + annotation_date=annotation_date, + annotation_comment=comment, + ), + ) + return annotation diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py new file mode 100644 index 000000000..5da8ff544 --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict, Optional + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import json_str_to_enum_name +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) + + +class ChecksumParser: + logger: Logger + + def __init__(self): + self.logger = Logger() + + @staticmethod + def parse_checksum(checksum_dict: Dict) -> Checksum: + logger = Logger() + algorithm: str = json_str_to_enum_name(checksum_dict.get("algorithm", "")) + try: + checksum_algorithm = ChecksumAlgorithm[algorithm] + except KeyError: + logger.append(f"Invalid ChecksumAlgorithm: {algorithm}") + checksum_algorithm = None + checksum_value: Optional[str] = checksum_dict.get("checksumValue") + raise_parsing_error_if_logger_has_messages(logger, "Checksum") + checksum = construct_or_raise_parsing_error(Checksum, dict(algorithm=checksum_algorithm, value=checksum_value)) + return checksum diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py new file mode 100644 index 000000000..c530999f1 --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py @@ -0,0 +1,117 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import Dict, List, Optional + +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model import Actor, Checksum, CreationInfo, ExternalDocumentRef, Version +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_log_error +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) + + +class CreationInfoParser: + logger: Logger + actor_parser: ActorParser + checksum_parser: ChecksumParser + + def __init__(self): + self.logger = Logger() + self.actor_parser = ActorParser() + self.checksum_parser = ChecksumParser() + + def parse_creation_info(self, doc_dict: Dict) -> CreationInfo: + logger = Logger() + spdx_version: Optional[str] = doc_dict.get("spdxVersion") + spdx_id: Optional[str] = doc_dict.get("SPDXID") + name: Optional[str] = doc_dict.get("name") + document_namespace: Optional[str] = doc_dict.get("documentNamespace") + creation_info_dict: Optional[Dict] = doc_dict.get("creationInfo") + + # There are nested required properties. If creationInfo is not set, we cannot continue parsing. + if creation_info_dict is None: + logger.append("CreationInfo does not exist.") + raise SPDXParsingError([f"Error while parsing document {name}: {logger.get_messages()}"]) + + creators: List[Actor] = parse_field_or_log_error( + logger, creation_info_dict.get("creators"), self.actor_parser.parse_actor, field_is_list=True + ) + + created: Optional[datetime] = parse_field_or_log_error( + logger, creation_info_dict.get("created"), datetime_from_str + ) + + creator_comment: Optional[str] = creation_info_dict.get("comment") + data_license: Optional[str] = doc_dict.get("dataLicense") + + external_document_refs: List[ExternalDocumentRef] = parse_field_or_log_error( + logger, doc_dict.get("externalDocumentRefs"), self.parse_external_document_refs + ) + license_list_version: Optional[Version] = parse_field_or_log_error( + logger, creation_info_dict.get("licenseListVersion"), self.parse_version + ) + document_comment: Optional[str] = doc_dict.get("comment") + raise_parsing_error_if_logger_has_messages(logger, "Document") + + creation_info = construct_or_raise_parsing_error( + CreationInfo, + dict( + spdx_version=spdx_version, + spdx_id=spdx_id, + name=name, + document_namespace=document_namespace, + creators=creators, + created=created, + license_list_version=license_list_version, + document_comment=document_comment, + creator_comment=creator_comment, + data_license=data_license, + external_document_refs=external_document_refs, + ), + ) + + return creation_info + + @staticmethod + def parse_version(version_str: str) -> Version: + try: + return Version.from_string(version_str) + except ValueError as err: + raise SPDXParsingError([f"Error while parsing version {version_str}: {err.args[0]}"]) + + def parse_external_document_refs(self, external_document_ref_dicts: List[Dict]) -> List[ExternalDocumentRef]: + logger = Logger() + external_document_refs = [] + for external_document_ref_dict in external_document_ref_dicts: + external_document_ref: ExternalDocumentRef = parse_field_or_log_error( + logger, external_document_ref_dict, self.parse_external_document_ref + ) + + external_document_refs.append(external_document_ref) + + raise_parsing_error_if_logger_has_messages(logger) + return external_document_refs + + def parse_external_document_ref(self, external_document_ref_dict: Dict) -> ExternalDocumentRef: + logger = Logger() + checksum: Optional[Checksum] = parse_field_or_log_error( + logger, external_document_ref_dict.get("checksum"), self.checksum_parser.parse_checksum + ) + + external_document_id: Optional[str] = external_document_ref_dict.get("externalDocumentId") + document_uri: Optional[str] = external_document_ref_dict.get("spdxDocument") + raise_parsing_error_if_logger_has_messages(logger, "ExternalDocumentRef") + external_document_ref: ExternalDocumentRef = construct_or_raise_parsing_error( + ExternalDocumentRef, + dict(document_ref_id=external_document_id, checksum=checksum, document_uri=document_uri), + ) + + return external_document_ref diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py new file mode 100644 index 000000000..0733317d1 --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py @@ -0,0 +1,82 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Callable, Dict, List, Optional + +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages + + +def json_str_to_enum_name(json_str: str) -> str: + if not isinstance(json_str, str): + raise SPDXParsingError([f"Type for enum must be str not {type(json_str).__name__}"]) + return json_str.replace("-", "_").upper() + + +def parse_field_or_log_error( + logger: Logger, + field: Any, + parsing_method: Callable = lambda x: x, + default: Any = None, + field_is_list: bool = False, +) -> Any: + if not field: + return default + try: + if field_is_list: + return parse_list_of_elements(field, parsing_method) + else: + return parsing_method(field) + except SPDXParsingError as err: + logger.extend(err.get_messages()) + except (TypeError, ValueError) as err: + logger.append(err.args[0]) + return default + + +def append_parsed_field_or_log_error( + logger: Logger, list_to_append_to: List[Any], field: Any, method_to_parse: Callable +) -> List[Any]: + try: + parsed_element = method_to_parse(field) + list_to_append_to.append(parsed_element) + except SPDXParsingError as err: + logger.extend(err.get_messages()) + except (TypeError, ValueError) as err: + logger.append(err.args[0]) + return list_to_append_to + + +def parse_field_or_no_assertion_or_none(field: Optional[str], method_for_field: Callable = lambda x: x) -> Any: + if field == SpdxNoAssertion().__str__(): + return SpdxNoAssertion() + elif field == SpdxNone().__str__(): + return SpdxNone() + else: + return method_for_field(field) + + +def parse_field_or_no_assertion(field: Optional[str], method_for_field: Callable = lambda x: x) -> Any: + if field == SpdxNoAssertion().__str__(): + return SpdxNoAssertion() + else: + return method_for_field(field) + + +def parse_list_of_elements(list_of_elements: List[Dict], method_to_parse_element: Callable, logger=None) -> List[Any]: + if not logger: + logger = Logger() + parsed_elements = [] + for element_dict in list_of_elements: + parsed_elements = append_parsed_field_or_log_error( + logger, parsed_elements, element_dict, method_to_parse_element + ) + raise_parsing_error_if_logger_has_messages(logger) + return parsed_elements + + +def delete_duplicates_from_list(list_with_potential_duplicates: List[Any]) -> List[Any]: + list_without_duplicates = list(dict.fromkeys(list_with_potential_duplicates)) + return list_without_duplicates diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py new file mode 100644 index 000000000..c0646084f --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict, List, Optional, Union + +from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_no_assertion +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import construct_or_raise_parsing_error + + +class ExtractedLicensingInfoParser: + logger: Logger + + def __init__(self): + self.logger = Logger() + + @staticmethod + def parse_extracted_licensing_info(extracted_licensing_info_dict: Dict) -> ExtractedLicensingInfo: + license_id: Optional[str] = extracted_licensing_info_dict.get("licenseId") + extracted_text: Optional[str] = extracted_licensing_info_dict.get("extractedText") + license_name: Optional[Union[str, SpdxNoAssertion]] = parse_field_or_no_assertion( + extracted_licensing_info_dict.get("name") + ) + cross_references: List[str] = extracted_licensing_info_dict.get("seeAlsos", []) + comment: Optional[str] = extracted_licensing_info_dict.get("comment") + extracted_licensing_info = construct_or_raise_parsing_error( + ExtractedLicensingInfo, + dict( + license_id=license_id, + extracted_text=extracted_text, + comment=comment, + license_name=license_name, + cross_references=cross_references, + ), + ) + return extracted_licensing_info diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py new file mode 100644 index 000000000..77138ab40 --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py @@ -0,0 +1,96 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict, List, Optional, Union +from license_expression import LicenseExpression + +from spdx_tools.spdx.model import Checksum, File, FileType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( + parse_field_or_log_error, + parse_field_or_no_assertion_or_none, +) +from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) + + +class FileParser: + logger: Logger + checksum_parser: ChecksumParser + license_expression_parser: LicenseExpressionParser + + def __init__(self): + self.logger = Logger() + self.checksum_parser = ChecksumParser() + self.license_expression_parser = LicenseExpressionParser() + + def parse_file(self, file_dict: Dict) -> Optional[File]: + logger = Logger() + name: Optional[str] = file_dict.get("fileName") + spdx_id: Optional[str] = file_dict.get("SPDXID") + checksums_list: List[Dict] = file_dict.get("checksums") + checksums: List[Checksum] = parse_field_or_log_error( + logger, checksums_list, self.checksum_parser.parse_checksum, field_is_list=True + ) + + attribution_texts: List[str] = file_dict.get("attributionTexts", []) + comment: Optional[str] = file_dict.get("comment") + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( + file_dict.get("copyrightText") + ) + file_contributors: List[str] = file_dict.get("fileContributors", []) + file_types: List[FileType] = parse_field_or_log_error( + logger, file_dict.get("fileTypes"), self.parse_file_types + ) + + license_comments: Optional[str] = file_dict.get("licenseComments") + + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( + logger, file_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression + ) + + license_info_in_files: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( + logger, + file_dict.get("licenseInfoInFiles"), + self.license_expression_parser.parse_license_expression, + field_is_list=True, + ) + notice_text: Optional[str] = file_dict.get("noticeText") + raise_parsing_error_if_logger_has_messages(logger, "File") + + file = construct_or_raise_parsing_error( + File, + dict( + name=name, + spdx_id=spdx_id, + checksums=checksums, + attribution_texts=attribution_texts, + comment=comment, + copyright_text=copyright_text, + file_types=file_types, + contributors=file_contributors, + license_comment=license_comments, + license_concluded=license_concluded, + license_info_in_file=license_info_in_files, + notice=notice_text, + ), + ) + return file + + @staticmethod + def parse_file_types(file_types_list: List[str]) -> List[FileType]: + logger = Logger() + file_types = [] + for file_type in file_types_list: + try: + file_type = FileType[file_type] + except KeyError: + logger.append(f"Invalid FileType: {file_type}") + continue + file_types.append(file_type) + raise_parsing_error_if_logger_has_messages(logger, "FileType") + return file_types diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py new file mode 100644 index 000000000..31a41559a --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py @@ -0,0 +1,92 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict + +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.annotation_parser import AnnotationParser +from spdx_tools.spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements +from spdx_tools.spdx.parser.jsonlikedict.extracted_licensing_info_parser import ExtractedLicensingInfoParser +from spdx_tools.spdx.parser.jsonlikedict.file_parser import FileParser +from spdx_tools.spdx.parser.jsonlikedict.package_parser import PackageParser +from spdx_tools.spdx.parser.jsonlikedict.relationship_parser import RelationshipParser +from spdx_tools.spdx.parser.jsonlikedict.snippet_parser import SnippetParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) + + +class JsonLikeDictParser: + logger: Logger + creation_info_parser: CreationInfoParser + package_parser: PackageParser + file_parser: FileParser + snippet_parser: SnippetParser + extracted_licensing_info_parser: ExtractedLicensingInfoParser + relationship_parser: RelationshipParser + annotation_parser: AnnotationParser + + def __init__(self): + self.logger = Logger() + self.creation_info_parser = CreationInfoParser() + self.package_parser = PackageParser() + self.file_parser = FileParser() + self.snippet_parser = SnippetParser() + self.extracted_licensing_info_parser = ExtractedLicensingInfoParser() + self.relationship_parser = RelationshipParser() + self.annotation_parser = AnnotationParser() + + def parse(self, json_like_dict: Dict) -> Document: + fields_to_parse = [ + ("creation_info", json_like_dict, self.creation_info_parser.parse_creation_info, False), + ( + "packages", + json_like_dict.get("packages"), + lambda x: parse_list_of_elements(x, self.package_parser.parse_package, self.package_parser.logger), + True, + ), + ( + "files", + json_like_dict.get("files"), + lambda x: parse_list_of_elements(x, self.file_parser.parse_file, self.file_parser.logger), + True, + ), + ("annotations", json_like_dict, self.annotation_parser.parse_all_annotations, True), + ( + "snippets", + json_like_dict.get("snippets"), + lambda x: parse_list_of_elements(x, self.snippet_parser.parse_snippet, self.snippet_parser.logger), + True, + ), + ("relationships", json_like_dict, self.relationship_parser.parse_all_relationships, True), + ( + "extracted_licensing_info", + json_like_dict.get("hasExtractedLicensingInfos"), + lambda x: parse_list_of_elements( + x, + self.extracted_licensing_info_parser.parse_extracted_licensing_info, + self.extracted_licensing_info_parser.logger, + ), + True, + ), + ] + + parsed_fields = {} + + for argument_name, field, parsing_method, optional in fields_to_parse: + if optional and not field: + continue + try: + parsed_fields[argument_name] = parsing_method(field) + except SPDXParsingError as err: + self.logger.extend(err.get_messages()) + + raise_parsing_error_if_logger_has_messages(self.logger) + + document = construct_or_raise_parsing_error(Document, parsed_fields) + + return document diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py new file mode 100644 index 000000000..5a3b545f6 --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Union +from license_expression import ExpressionError, LicenseExpression + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError + + +class LicenseExpressionParser: + @staticmethod + def parse_license_expression(license_expression_str: str) -> Union[LicenseExpression, SpdxNone, SpdxNoAssertion]: + if isinstance(license_expression_str, str): + if license_expression_str.upper() == "NOASSERTION": + return SpdxNoAssertion() + if license_expression_str.upper() == "NONE": + return SpdxNone() + + try: + license_expression = spdx_licensing.parse(license_expression_str) + except ExpressionError as err: + err_msg = f'Error parsing LicenseExpression: "{license_expression_str}"' + if err.args: + err_msg += f": {err.args[0]}" + raise SPDXParsingError([err_msg]) + + return license_expression diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py new file mode 100644 index 000000000..b395abd39 --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py @@ -0,0 +1,218 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import Dict, List, Optional, Union +from license_expression import LicenseExpression + +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model import ( + Actor, + ExternalPackageRef, + ExternalPackageRefCategory, + Package, + PackagePurpose, + PackageVerificationCode, + SpdxNoAssertion, + SpdxNone, +) +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( + append_parsed_field_or_log_error, + json_str_to_enum_name, + parse_field_or_log_error, + parse_field_or_no_assertion, + parse_field_or_no_assertion_or_none, +) +from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) + + +class PackageParser: + logger: Logger + actor_parser: ActorParser + checksum_parser: ChecksumParser + license_expression_parser: LicenseExpressionParser + + def __init__(self): + self.actor_parser = ActorParser() + self.checksum_parser = ChecksumParser() + self.license_expression_parser = LicenseExpressionParser() + self.logger = Logger() + + def parse_package(self, package_dict: Dict) -> Package: + logger = Logger() + name: Optional[str] = package_dict.get("name") + spdx_id: Optional[str] = package_dict.get("SPDXID") + attribution_texts: List[str] = package_dict.get("attributionTexts", []) + + built_date: Optional[datetime] = parse_field_or_log_error( + logger, package_dict.get("builtDate"), datetime_from_str + ) + + checksums = parse_field_or_log_error( + logger, package_dict.get("checksums"), self.checksum_parser.parse_checksum, field_is_list=True + ) + comment: Optional[str] = package_dict.get("comment") + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( + package_dict.get("copyrightText") + ) + description: Optional[str] = package_dict.get("description") + download_location: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( + package_dict.get("downloadLocation") + ) + + external_refs: List[ExternalPackageRef] = parse_field_or_log_error( + logger, package_dict.get("externalRefs"), self.parse_external_refs + ) + + files_analyzed: Optional[Union[bool, str]] = package_dict.get("filesAnalyzed") + + if files_analyzed is None: # default value is True + files_analyzed = True + elif isinstance(files_analyzed, str): # XML does not support boolean typed values + if files_analyzed.lower() == "true": + files_analyzed = True + elif files_analyzed.lower() == "false": + files_analyzed = False + + homepage: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( + package_dict.get("homepage") + ) + license_comments: Optional[str] = package_dict.get("licenseComments") + license_concluded = parse_field_or_log_error( + logger, package_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression + ) + + license_declared: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( + logger, package_dict.get("licenseDeclared"), self.license_expression_parser.parse_license_expression + ) + + license_info_from_file: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( + logger, + package_dict.get("licenseInfoFromFiles"), + self.license_expression_parser.parse_license_expression, + field_is_list=True, + ) + originator: Optional[Union[Actor, SpdxNoAssertion]] = parse_field_or_log_error( + logger, + package_dict.get("originator"), + lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor), + ) + package_file_name: Optional[str] = package_dict.get("packageFileName") + + package_verification_code: Optional[PackageVerificationCode] = parse_field_or_log_error( + logger, package_dict.get("packageVerificationCode"), self.parse_package_verification_code + ) + primary_package_purpose: Optional[PackagePurpose] = parse_field_or_log_error( + logger, package_dict.get("primaryPackagePurpose"), self.parse_primary_package_purpose + ) + + release_date: Optional[datetime] = parse_field_or_log_error( + logger, package_dict.get("releaseDate"), datetime_from_str + ) + source_info: Optional[str] = package_dict.get("sourceInfo") + summary: Optional[str] = package_dict.get("summary") + supplier: Optional[Union[Actor, SpdxNoAssertion]] = parse_field_or_log_error( + logger, + package_dict.get("supplier"), + lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor), + ) + valid_until_date: Optional[datetime] = parse_field_or_log_error( + logger, package_dict.get("validUntilDate"), datetime_from_str + ) + + version_info: Optional[str] = package_dict.get("versionInfo") + raise_parsing_error_if_logger_has_messages(logger, "Package") + + package = construct_or_raise_parsing_error( + Package, + dict( + spdx_id=spdx_id, + name=name, + download_location=download_location, + version=version_info, + file_name=package_file_name, + supplier=supplier, + originator=originator, + files_analyzed=files_analyzed, + verification_code=package_verification_code, + checksums=checksums, + homepage=homepage, + source_info=source_info, + license_concluded=license_concluded, + license_info_from_files=license_info_from_file, + license_declared=license_declared, + license_comment=license_comments, + copyright_text=copyright_text, + summary=summary, + description=description, + comment=comment, + external_references=external_refs, + attribution_texts=attribution_texts, + primary_package_purpose=primary_package_purpose, + release_date=release_date, + built_date=built_date, + valid_until_date=valid_until_date, + ), + ) + + return package + + def parse_external_refs(self, external_ref_dicts: List[Dict]) -> List[ExternalPackageRef]: + external_refs = [] + for external_ref_dict in external_ref_dicts: + external_refs = append_parsed_field_or_log_error( + self.logger, external_refs, external_ref_dict, self.parse_external_ref + ) + return external_refs + + def parse_external_ref(self, external_ref_dict: Dict) -> ExternalPackageRef: + logger = Logger() + ref_category = parse_field_or_log_error( + logger, external_ref_dict.get("referenceCategory"), self.parse_external_ref_category + ) + ref_locator: Optional[str] = external_ref_dict.get("referenceLocator") + ref_type: Optional[str] = external_ref_dict.get("referenceType") + comment: Optional[str] = external_ref_dict.get("comment") + raise_parsing_error_if_logger_has_messages(logger, "ExternalPackageRef") + external_ref = construct_or_raise_parsing_error( + ExternalPackageRef, + dict(category=ref_category, reference_type=ref_type, locator=ref_locator, comment=comment), + ) + + return external_ref + + @staticmethod + def parse_external_ref_category(external_ref_category_str: str) -> ExternalPackageRefCategory: + try: + external_ref_category = ExternalPackageRefCategory[json_str_to_enum_name(external_ref_category_str)] + except KeyError: + raise SPDXParsingError([f"Invalid ExternalPackageRefCategory: {external_ref_category_str}"]) + + return external_ref_category + + @staticmethod + def parse_package_verification_code(verification_code_dict: Dict) -> PackageVerificationCode: + excluded_files: List[str] = verification_code_dict.get("packageVerificationCodeExcludedFiles", []) + verification_code_value: Optional[str] = verification_code_dict.get("packageVerificationCodeValue") + + package_verification_code = construct_or_raise_parsing_error( + PackageVerificationCode, dict(value=verification_code_value, excluded_files=excluded_files) + ) + + return package_verification_code + + @staticmethod + def parse_primary_package_purpose(primary_package_purpose: str) -> PackagePurpose: + try: + return PackagePurpose[json_str_to_enum_name(primary_package_purpose)] + except KeyError: + raise SPDXParsingError([f"Invalid PrimaryPackagePurpose: {primary_package_purpose}"]) diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py new file mode 100644 index 000000000..17374bef5 --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py @@ -0,0 +1,213 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict, List, Optional + +from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors +from spdx_tools.spdx.model import Relationship, RelationshipType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( + delete_duplicates_from_list, + json_str_to_enum_name, + parse_field_or_log_error, + parse_field_or_no_assertion_or_none, +) +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) + + +class RelationshipParser: + logger: Logger + + def __init__(self): + self.logger = Logger() + + def parse_all_relationships(self, input_doc_dict: Dict) -> List[Relationship]: + relationships = [] + relationship_dicts: List[Dict] = input_doc_dict.get("relationships", []) + relationships.extend( + parse_field_or_log_error(self.logger, relationship_dicts, self.parse_relationship, [], True) + ) + + document_describes: List[str] = delete_duplicates_from_list(input_doc_dict.get("documentDescribes", [])) + doc_spdx_id: Optional[str] = input_doc_dict.get("SPDXID") + + existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments( + relationships + ) + relationships.extend( + parse_field_or_log_error( + self.logger, + document_describes, + lambda x: self.parse_document_describes( + doc_spdx_id=doc_spdx_id, + described_spdx_ids=x, + existing_relationships=existing_relationships_without_comments, + ), + [], + ) + ) + + package_dicts: List[Dict] = input_doc_dict.get("packages", []) + existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments( + relationships + ) + + relationships.extend( + parse_field_or_log_error( + self.logger, + package_dicts, + lambda x: self.parse_has_files( + package_dicts=x, existing_relationships=existing_relationships_without_comments + ), + [], + ) + ) + + file_dicts: List[Dict] = input_doc_dict.get("files", []) + + # not implemented yet: deal with deprecated fields in file: + # https://github.com/spdx/tools-python/issues/294 & https://github.com/spdx/tools-python/issues/387 + _ = self.parse_artifact_of(file_dicts=file_dicts) + _ = self.parse_file_dependencies(file_dicts=file_dicts) + + raise_parsing_error_if_logger_has_messages(self.logger) + + return relationships + + def parse_relationship(self, relationship_dict: Dict) -> Relationship: + logger = Logger() + spdx_element_id: Optional[str] = relationship_dict.get("spdxElementId") + related_spdx_element: Optional[str] = parse_field_or_no_assertion_or_none( + relationship_dict.get("relatedSpdxElement") + ) + relationship_type: Optional[RelationshipType] = parse_field_or_log_error( + logger, relationship_dict.get("relationshipType"), self.parse_relationship_type + ) + relationship_comment: Optional[str] = relationship_dict.get("comment") + raise_parsing_error_if_logger_has_messages(logger, "Relationship") + + relationship = construct_or_raise_parsing_error( + Relationship, + dict( + spdx_element_id=spdx_element_id, + relationship_type=relationship_type, + related_spdx_element_id=related_spdx_element, + comment=relationship_comment, + ), + ) + return relationship + + @staticmethod + def parse_relationship_type(relationship_type_str: str) -> RelationshipType: + try: + relationship_type = RelationshipType[json_str_to_enum_name(relationship_type_str)] + except KeyError: + raise SPDXParsingError([f"Invalid RelationshipType: {relationship_type_str}"]) + return relationship_type + + def parse_document_describes( + self, doc_spdx_id: str, described_spdx_ids: List[str], existing_relationships: List[Relationship] + ) -> List[Relationship]: + logger = Logger() + describes_relationships = [] + for spdx_id in described_spdx_ids: + try: + describes_relationship = Relationship( + spdx_element_id=doc_spdx_id, + relationship_type=RelationshipType.DESCRIBES, + related_spdx_element_id=spdx_id, + ) + except ConstructorTypeErrors as err: + logger.append(err.get_messages()) + continue + if not self.check_if_relationship_exists(describes_relationship, existing_relationships): + describes_relationships.append(describes_relationship) + raise_parsing_error_if_logger_has_messages(logger, "document describes relationships") + + return describes_relationships + + def parse_has_files( + self, package_dicts: List[Dict], existing_relationships: List[Relationship] + ) -> List[Relationship]: + # assume existing relationships are stripped of comments + logger = Logger() + contains_relationships = [] + for package in package_dicts: + package_spdx_id: Optional[str] = package.get("SPDXID") + contained_files: List[str] = delete_duplicates_from_list(package.get("hasFiles", [])) + if not contained_files: + continue + for file_spdx_id in contained_files: + try: + contains_relationship = Relationship( + spdx_element_id=package_spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=file_spdx_id, + ) + except ConstructorTypeErrors as err: + logger.append(err.get_messages()) + continue + if not self.check_if_relationship_exists( + relationship=contains_relationship, existing_relationships=existing_relationships + ): + contains_relationships.append(contains_relationship) + raise_parsing_error_if_logger_has_messages(logger, "package contains relationships") + + return contains_relationships + + def check_if_relationship_exists( + self, relationship: Relationship, existing_relationships: List[Relationship] + ) -> bool: + # assume existing relationships are stripped of comments + if relationship in existing_relationships: + return True + relationship_inverted: Relationship = self.invert_relationship(relationship) + if relationship_inverted in existing_relationships: + return True + + return False + + @staticmethod + def get_all_relationships_without_comments(existing_relationships: List[Relationship]) -> List[Relationship]: + relationships_without_comments = [ + Relationship( + relationship_type=relationship.relationship_type, + related_spdx_element_id=relationship.related_spdx_element_id, + spdx_element_id=relationship.spdx_element_id, + ) + for relationship in existing_relationships + ] + return relationships_without_comments + + def invert_relationship(self, relationship: Relationship) -> Relationship: + return Relationship( + related_spdx_element_id=relationship.spdx_element_id, + spdx_element_id=relationship.related_spdx_element_id, + relationship_type=self.invert_relationship_types[relationship.relationship_type], + comment=relationship.comment, + ) + + invert_relationship_types = { + RelationshipType.DESCRIBES: RelationshipType.DESCRIBED_BY, + RelationshipType.DESCRIBED_BY: RelationshipType.DESCRIBES, + RelationshipType.CONTAINS: RelationshipType.CONTAINED_BY, + RelationshipType.CONTAINED_BY: RelationshipType.CONTAINS, + } + + @staticmethod + def parse_file_dependencies(file_dicts: List[Dict]) -> List[Relationship]: + dependency_relationships = [] + # the field fileDependencies is deprecated and should be converted to a relationship + # https://github.com/spdx/tools-python/issues/387 + return dependency_relationships + + @staticmethod + def parse_artifact_of(file_dicts: List[Dict]) -> List[Relationship]: + generated_relationships = [] + # artifactOfs is deprecated and should be converted to an external package and a generated from relationship + # https://github.com/spdx/tools-python/issues/294 + return generated_relationships diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py new file mode 100644 index 000000000..f00779407 --- /dev/null +++ b/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py @@ -0,0 +1,140 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto + +from beartype.typing import Dict, List, Optional, Tuple, Union +from license_expression import LicenseExpression + +from spdx_tools.spdx.model import Snippet, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( + parse_field_or_log_error, + parse_field_or_no_assertion_or_none, +) +from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import construct_or_raise_parsing_error + + +class RangeType(Enum): + BYTE = auto() + LINE = auto() + + +class SnippetParser: + logger: Logger + license_expression_parser = LicenseExpressionParser + + def __init__(self): + self.logger = Logger() + self.license_expression_parser = LicenseExpressionParser() + + def parse_snippet(self, snippet_dict: Dict) -> Snippet: + logger = Logger() + spdx_id: Optional[str] = snippet_dict.get("SPDXID") + file_spdx_id: Optional[str] = snippet_dict.get("snippetFromFile") + name: Optional[str] = snippet_dict.get("name") + + ranges: Dict = parse_field_or_log_error(logger, snippet_dict.get("ranges", []), self.parse_ranges, default={}) + byte_range: Optional[Tuple[Union[int, str], Union[int, str]]] = ranges.get(RangeType.BYTE) + line_range: Optional[Tuple[Union[int, str], Union[int, str]]] = ranges.get(RangeType.LINE) + byte_range = self.convert_range_from_str(byte_range) + line_range = self.convert_range_from_str(line_range) + + attribution_texts: List[str] = snippet_dict.get("attributionTexts", []) + comment: Optional[str] = snippet_dict.get("comment") + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( + snippet_dict.get("copyrightText") + ) + license_comment: Optional[str] = snippet_dict.get("licenseComments") + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( + logger, snippet_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression + ) + + license_info: List[Union[LicenseExpression], SpdxNoAssertion, SpdxNone] = parse_field_or_log_error( + logger, + snippet_dict.get("licenseInfoInSnippets"), + self.license_expression_parser.parse_license_expression, + field_is_list=True, + ) + if logger.has_messages(): + raise SPDXParsingError([f"Error while parsing snippet: {logger.get_messages()}"]) + + snippet = construct_or_raise_parsing_error( + Snippet, + dict( + spdx_id=spdx_id, + name=name, + byte_range=byte_range, + file_spdx_id=file_spdx_id, + line_range=line_range, + attribution_texts=attribution_texts, + comment=comment, + copyright_text=copyright_text, + license_comment=license_comment, + license_concluded=license_concluded, + license_info_in_snippet=license_info, + ), + ) + + return snippet + + def parse_ranges(self, ranges_from_snippet: List[Dict]) -> Dict: + logger = Logger() + ranges = {} + for range_dict in ranges_from_snippet: + try: + range_type: RangeType = self.validate_range_and_get_type(range_dict) + start_end_tuple: Tuple[int, int] = SnippetParser.get_start_end_tuple(range_dict, range_type) + ranges[range_type] = start_end_tuple + except ValueError as error: + logger.append(error.args[0]) + if logger.has_messages(): + raise SPDXParsingError([f"Error while parsing snippet ranges: {logger.get_messages()}"]) + return ranges + + @staticmethod + def get_start_end_tuple(range_dict: Dict, range_type: RangeType) -> Tuple[int, int]: + end_pointer: Dict = range_dict["endPointer"] + start_pointer: Dict = range_dict["startPointer"] + if range_type == RangeType.BYTE: + start: int = start_pointer["offset"] + end: int = end_pointer["offset"] + else: + start: int = start_pointer["lineNumber"] + end: int = end_pointer["lineNumber"] + return start, end + + def validate_range_and_get_type(self, range_dict: Dict) -> RangeType: + if "startPointer" not in range_dict: + raise ValueError("Startpointer missing in snippet ranges.") + if "endPointer" not in range_dict: + raise ValueError("Endpointer missing in snippet ranges.") + start_pointer_type: RangeType = self.validate_pointer_and_get_type(range_dict["startPointer"]) + end_pointer_type: RangeType = self.validate_pointer_and_get_type(range_dict["endPointer"]) + if start_pointer_type != end_pointer_type: + raise ValueError("Type of startpointer is not the same as type of endpointer.") + return start_pointer_type + + @staticmethod + def validate_pointer_and_get_type(pointer: Dict) -> RangeType: + if "offset" in pointer and "lineNumber" in pointer: + raise ValueError('Couldn\'t determine type of pointer: "offset" and "lineNumber" provided as key.') + if "offset" not in pointer and "lineNumber" not in pointer: + raise ValueError('Couldn\'t determine type of pointer: neither "offset" nor "lineNumber" provided as key.') + return RangeType.BYTE if "offset" in pointer else RangeType.LINE + + @staticmethod + def convert_range_from_str( + _range: Tuple[Union[int, str], Union[int, str]] + ) -> Tuple[Union[int, str], Union[int, str]]: + # XML does not support integers, so we have to convert from string (if possible) + if not _range: + return _range + + if isinstance(_range[0], str) and _range[0].isdigit(): + _range = int(_range[0]), _range[1] + if isinstance(_range[1], str) and _range[1].isdigit(): + _range = _range[0], int(_range[1]) + return _range diff --git a/src/spdx_tools/spdx/parser/logger.py b/src/spdx_tools/spdx/parser/logger.py new file mode 100644 index 000000000..343de7398 --- /dev/null +++ b/src/spdx_tools/spdx/parser/logger.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + + +class Logger: + messages: List[str] + + def __init__(self): + self.messages = [] + + def append(self, message: str): + self.messages.append(message) + + def extend(self, messages_to_append: List[str]): + self.messages.extend(messages_to_append) + + def has_messages(self): + return bool(self.messages) + + def get_messages(self): + return list(self.messages) diff --git a/src/spdx_tools/spdx/parser/parse_anything.py b/src/spdx_tools/spdx/parser/parse_anything.py new file mode 100644 index 000000000..ff41e2b77 --- /dev/null +++ b/src/spdx_tools/spdx/parser/parse_anything.py @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) spdx contributors +# 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. +import logging + +from spdx_tools.spdx.formats import FileFormat, file_name_to_format +from spdx_tools.spdx.parser.json import json_parser +from spdx_tools.spdx.parser.rdf import rdf_parser +from spdx_tools.spdx.parser.tagvalue import tagvalue_parser +from spdx_tools.spdx.parser.xml import xml_parser +from spdx_tools.spdx.parser.yaml import yaml_parser + + +def parse_file(file_name: str, encoding: str = "utf-8"): + if encoding != "utf-8": + logging.warning( + "It's recommended to use the UTF-8 encoding for any SPDX file. Consider changing the encoding of the file." + ) + + input_format = file_name_to_format(file_name) + if input_format == FileFormat.RDF_XML: + return rdf_parser.parse_from_file(file_name, encoding) + elif input_format == FileFormat.TAG_VALUE: + return tagvalue_parser.parse_from_file(file_name, encoding) + elif input_format == FileFormat.JSON: + return json_parser.parse_from_file(file_name, encoding) + elif input_format == FileFormat.XML: + return xml_parser.parse_from_file(file_name, encoding) + elif input_format == FileFormat.YAML: + return yaml_parser.parse_from_file(file_name, encoding) diff --git a/src/spdx_tools/spdx/parser/parsing_functions.py b/src/spdx_tools/spdx/parser/parsing_functions.py new file mode 100644 index 000000000..47f73951d --- /dev/null +++ b/src/spdx_tools/spdx/parser/parsing_functions.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Dict + +from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger + + +def construct_or_raise_parsing_error(object_to_construct: Any, args_for_construction: Dict) -> Any: + try: + constructed_object = object_to_construct(**args_for_construction) + except ConstructorTypeErrors as err: + raise SPDXParsingError([f"Error while constructing {object_to_construct.__name__}: {err.get_messages()}"]) + except TypeError as err: + raise SPDXParsingError([f"Error while constructing {object_to_construct.__name__}: {err.args[0]}"]) + return constructed_object + + +def raise_parsing_error_if_logger_has_messages(logger: Logger, parsed_object_name: str = None): + if logger.has_messages(): + if parsed_object_name: + raise SPDXParsingError([f"Error while parsing {parsed_object_name}: {logger.get_messages()}"]) + else: + raise SPDXParsingError(logger.get_messages()) diff --git a/src/spdx_tools/spdx/parser/rdf/__init__.py b/src/spdx_tools/spdx/parser/rdf/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/parser/rdf/annotation_parser.py b/src/spdx_tools/spdx/parser/rdf/annotation_parser.py new file mode 100644 index 000000000..880637bf1 --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/annotation_parser.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDFS, BNode, Graph, URIRef + +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model import Annotation, AnnotationType +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import parse_enum_value, parse_literal, parse_spdx_id +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def parse_annotation(annotation_node: BNode, graph: Graph, parent_node: URIRef, doc_namespace: str) -> Annotation: + logger = Logger() + spdx_id = parse_spdx_id(parent_node, doc_namespace, graph) + annotator = parse_literal( + logger, graph, annotation_node, SPDX_NAMESPACE.annotator, parsing_method=ActorParser.parse_actor + ) + annotation_type = parse_literal( + logger, + graph, + annotation_node, + SPDX_NAMESPACE.annotationType, + parsing_method=lambda x: parse_enum_value(x, AnnotationType, SPDX_NAMESPACE.annotationType_), + ) + annotation_date = parse_literal( + logger, graph, annotation_node, SPDX_NAMESPACE.annotationDate, parsing_method=datetime_from_str + ) + annotation_comment = parse_literal(logger, graph, annotation_node, RDFS.comment) + + raise_parsing_error_if_logger_has_messages(logger, "Annotation") + annotation = construct_or_raise_parsing_error( + Annotation, + dict( + spdx_id=spdx_id, + annotation_type=annotation_type, + annotator=annotator, + annotation_date=annotation_date, + annotation_comment=annotation_comment, + ), + ) + + return annotation diff --git a/src/spdx_tools/spdx/parser/rdf/checksum_parser.py b/src/spdx_tools/spdx/parser/rdf/checksum_parser.py new file mode 100644 index 000000000..722f20340 --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/checksum_parser.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import BNode, Graph + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import parse_literal, remove_prefix +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def parse_checksum(parent_node: BNode, graph: Graph) -> Checksum: + logger = Logger() + algorithm = parse_literal( + logger, graph, parent_node, SPDX_NAMESPACE.algorithm, parsing_method=convert_rdf_to_algorithm + ) + value = parse_literal(logger, graph, parent_node, SPDX_NAMESPACE.checksumValue) + + raise_parsing_error_if_logger_has_messages(logger, "Checksum") + checksum = construct_or_raise_parsing_error(Checksum, dict(algorithm=algorithm, value=value)) + return checksum + + +def convert_rdf_to_algorithm(algorithm: str) -> ChecksumAlgorithm: + algorithm = remove_prefix(algorithm, SPDX_NAMESPACE.checksumAlgorithm_).upper() + if "BLAKE2B" in algorithm: + algorithm = algorithm.replace("BLAKE2B", "BLAKE2B_") + try: + checksum = ChecksumAlgorithm[algorithm] + except KeyError: + raise SPDXParsingError([f"Invalid value for ChecksumAlgorithm: {algorithm}"]) + return checksum diff --git a/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py new file mode 100644 index 000000000..7c70e0242 --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py @@ -0,0 +1,145 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import logging +import sys +from urllib.parse import urldefrag + +from beartype.typing import Tuple +from rdflib import RDF, RDFS, Graph, Namespace +from rdflib.exceptions import UniquenessError +from rdflib.term import URIRef + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model import CreationInfo, ExternalDocumentRef, Version +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.checksum_parser import parse_checksum +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( + get_correctly_typed_triples, + parse_literal, + parse_spdx_id, + remove_prefix, +) +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE + + +def parse_creation_info(graph: Graph) -> Tuple[CreationInfo, URIRef]: + logger = Logger() + namespace, spdx_id, doc_node = parse_namespace_and_spdx_id(graph) + spec_version = parse_literal(logger, graph, doc_node, SPDX_NAMESPACE.specVersion) + data_license = parse_literal( + logger, + graph, + doc_node, + SPDX_NAMESPACE.dataLicense, + parsing_method=lambda x: remove_prefix(x, LICENSE_NAMESPACE), + ) + comment = parse_literal(logger, graph, doc_node, RDFS.comment) + name = parse_literal(logger, graph, doc_node, SPDX_NAMESPACE.name) + + creation_info_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.CreationInfo) + if not creation_info_node: + logger.append("CreationInfo does not exist.") + raise SPDXParsingError([f"Error while parsing document {name}: {logger.get_messages()}"]) + + created = parse_literal( + logger, graph, creation_info_node, SPDX_NAMESPACE.created, parsing_method=datetime_from_str + ) + license_list_version = parse_literal( + logger, graph, creation_info_node, SPDX_NAMESPACE.licenseListVersion, parsing_method=Version.from_string + ) + creator_comment = parse_literal(logger, graph, creation_info_node, RDFS.comment) + creators = [] + for _, _, creator_literal in get_correctly_typed_triples( + logger, graph, creation_info_node, SPDX_NAMESPACE.creator + ): + creators.append(ActorParser.parse_actor(creator_literal.toPython())) + if not creators: + logger.append("No creators provided.") + external_document_refs = [] + for _, _, external_document_node in get_correctly_typed_triples( + logger, graph, doc_node, SPDX_NAMESPACE.externalDocumentRef + ): + external_document_refs.append(parse_external_document_refs(external_document_node, graph, namespace)) + + raise_parsing_error_if_logger_has_messages(logger, "CreationInfo") + creation_info = construct_or_raise_parsing_error( + CreationInfo, + dict( + spdx_id=spdx_id, + document_namespace=namespace, + spdx_version=spec_version, + name=name, + data_license=data_license, + document_comment=comment, + created=created, + license_list_version=license_list_version, + creator_comment=creator_comment, + creators=creators, + external_document_refs=external_document_refs, + ), + ) + return creation_info, doc_node + + +def parse_namespace_and_spdx_id(graph: Graph) -> (str, str): + try: + subject = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.SpdxDocument, any=False) + except UniquenessError: + logging.error("Multiple SpdxDocuments found, can't parse rdf file.") + sys.exit(1) + + if not subject: + logging.error("No SpdxDocument found, can't parse rdf file.") + sys.exit(1) + if "#" not in subject: + logging.error( + "No '#' found in the URI of SpdxDocument, " + f"the URI for the SpdxDocument should be the namespace appended by '#{DOCUMENT_SPDX_ID}." + ) + sys.exit(1) + + namespace, spdx_id = urldefrag(str(subject)) + + if not namespace: + logging.error( + f"No namespace found, the URI for the SpdxDocument should be the namespace appended by " + f"'#{DOCUMENT_SPDX_ID}." + ) + sys.exit(1) + + if not spdx_id: + spdx_id = None + + return namespace, spdx_id, subject + + +def parse_external_document_refs( + external_document_node: URIRef, graph: Graph, doc_namespace: str +) -> ExternalDocumentRef: + logger = Logger() + document_ref_id = parse_spdx_id(external_document_node, doc_namespace, graph) + document_uri = parse_literal(logger, graph, external_document_node, SPDX_NAMESPACE.spdxDocument) + checksum = parse_literal( + logger, + graph, + external_document_node, + SPDX_NAMESPACE.checksum, + parsing_method=lambda x: parse_checksum(x, graph), + ) + external_document_ref = construct_or_raise_parsing_error( + ExternalDocumentRef, dict(document_ref_id=document_ref_id, document_uri=document_uri, checksum=checksum) + ) + + # To replace the external doc namespaces by the ref id in spdx ids later (e.g. in a relationship), we need to bind + # the namespace to the graph. + graph.bind(external_document_ref.document_ref_id, Namespace(external_document_ref.document_uri + "#")) + + return external_document_ref diff --git a/src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py b/src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py new file mode 100644 index 000000000..e77e8e8ad --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDFS, Graph, URIRef + +from spdx_tools.spdx.model import ExtractedLicensingInfo +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( + get_correctly_typed_triples, + parse_literal, + parse_literal_or_no_assertion_or_none, +) +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def parse_extracted_licensing_info( + extracted_licensing_info_node: URIRef, graph: Graph, doc_namespace: str +) -> ExtractedLicensingInfo: + logger = Logger() + license_id = parse_literal(logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.licenseId) + if not license_id: + license_id = ( + extracted_licensing_info_node.fragment + if extracted_licensing_info_node.startswith(f"{doc_namespace}#") + else extracted_licensing_info_node.toPython() + ) + + extracted_text = parse_literal(logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.extractedText) + comment = parse_literal(logger, graph, extracted_licensing_info_node, RDFS.comment) + license_name = parse_literal_or_no_assertion_or_none( + logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.name + ) + cross_references = [] + for _, _, cross_reference_node in get_correctly_typed_triples( + logger, graph, extracted_licensing_info_node, RDFS.seeAlso + ): + cross_references.append(cross_reference_node.toPython()) + raise_parsing_error_if_logger_has_messages(logger, "ExtractedLicensingInfo") + extracted_licensing_info = construct_or_raise_parsing_error( + ExtractedLicensingInfo, + dict( + license_id=license_id, + extracted_text=extracted_text, + comment=comment, + license_name=license_name, + cross_references=cross_references, + ), + ) + + return extracted_licensing_info diff --git a/src/spdx_tools/spdx/parser/rdf/file_parser.py b/src/spdx_tools/spdx/parser/rdf/file_parser.py new file mode 100644 index 000000000..22323d09c --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/file_parser.py @@ -0,0 +1,91 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Union +from rdflib import RDFS, BNode, Graph, URIRef + +from spdx_tools.spdx.model import File, FileType +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.checksum_parser import parse_checksum +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( + apply_parsing_method_or_log_error, + get_correctly_typed_triples, + get_correctly_typed_value, + parse_enum_value, + parse_literal, + parse_literal_or_no_assertion_or_none, + parse_spdx_id, +) +from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def parse_file(file_node: Union[URIRef, BNode], graph: Graph, doc_namespace: str) -> File: + logger = Logger() + spdx_id = parse_spdx_id(file_node, doc_namespace, graph) + name = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.fileName) + checksums = [] + for _, _, checksum_node in get_correctly_typed_triples(logger, graph, file_node, SPDX_NAMESPACE.checksum): + checksums.append(parse_checksum(checksum_node, graph)) + + file_types = [] + for _, _, file_type_ref in graph.triples((file_node, SPDX_NAMESPACE.fileType, None)): + file_types.append( + apply_parsing_method_or_log_error( + logger, file_type_ref, parsing_method=lambda x: parse_enum_value(x, FileType, SPDX_NAMESPACE.fileType_) + ) + ) + license_concluded = parse_literal_or_no_assertion_or_none( + logger, + graph, + file_node, + SPDX_NAMESPACE.licenseConcluded, + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace, logger), + ) + license_info_in_file = [] + for _, _, license_info_from_files_node in graph.triples((file_node, SPDX_NAMESPACE.licenseInfoInFile, None)): + license_info_in_file.append( + get_correctly_typed_value( + logger, + license_info_from_files_node, + lambda x: parse_license_expression(x, graph, doc_namespace, logger), + ) + ) + license_comment = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.licenseComments) + copyright_text = parse_literal_or_no_assertion_or_none(logger, graph, file_node, SPDX_NAMESPACE.copyrightText) + file_contributors = [] + for _, _, file_contributor in get_correctly_typed_triples( + logger, graph, file_node, SPDX_NAMESPACE.fileContributor, None + ): + file_contributors.append(file_contributor.toPython()) + + notice_text = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.noticeText) + comment = parse_literal(logger, graph, file_node, RDFS.comment) + attribution_texts = [] + for _, _, attribution_text_literal in get_correctly_typed_triples( + logger, graph, file_node, SPDX_NAMESPACE.attributionText, None + ): + attribution_texts.append(attribution_text_literal.toPython()) + raise_parsing_error_if_logger_has_messages(logger, "File") + file = construct_or_raise_parsing_error( + File, + dict( + name=name, + spdx_id=spdx_id, + checksums=checksums, + attribution_texts=attribution_texts, + comment=comment, + copyright_text=copyright_text, + file_types=file_types, + contributors=file_contributors, + license_comment=license_comment, + license_concluded=license_concluded, + license_info_in_file=license_info_in_file, + notice=notice_text, + ), + ) + return file diff --git a/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py new file mode 100644 index 000000000..5e2b8e099 --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py @@ -0,0 +1,148 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum + +from beartype.typing import Any, Callable, Optional, Tuple, Type, Union +from rdflib import RDF, Graph, URIRef +from rdflib.exceptions import UniquenessError +from rdflib.namespace import NamespaceManager +from rdflib.term import BNode, Literal, Node + +from spdx_tools.spdx.casing_tools import camel_case_to_snake_case +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def parse_literal( + logger: Logger, + graph: Graph, + subject: Node, + predicate: Node, + parsing_method: Callable = lambda x: x.strip(), + default: Any = None, +): + value = get_unique_value(logger, graph, subject, predicate, default) + if not value: + return default + return apply_parsing_method_or_log_error(logger, value, parsing_method, default) + + +def apply_parsing_method_or_log_error( + logger: Logger, value: Any, parsing_method: Callable = lambda x: x.strip(), default: Any = None +): + try: + return parsing_method(value) + except SPDXParsingError as err: + logger.extend(err.get_messages()) + except (TypeError, ValueError) as err: + logger.append(err.args[0]) + return default + + +def parse_literal_or_no_assertion_or_none( + logger: Logger, + graph: Graph, + subject: Node, + predicate: Node, + parsing_method: Callable = lambda x: x.strip(), + default: Any = None, +): + value = get_unique_value(logger, graph, subject, predicate, default) + return get_correctly_typed_value(logger, value, parsing_method, default) + + +def get_correctly_typed_value( + logger: Logger, value: Any, parsing_method: Callable = lambda x: x.strip(), default: Any = None +): + if not value: + return default + if value == SPDX_NAMESPACE.noassertion or value.toPython() == SPDX_NO_ASSERTION_STRING: + return SpdxNoAssertion() + if value == SPDX_NAMESPACE.none or value.toPython() == SPDX_NONE_STRING: + return SpdxNone() + return apply_parsing_method_or_log_error(logger, value, parsing_method, default) + + +def get_unique_value(logger: Logger, graph: Graph, subject: Node, predicate: Node, default: Any) -> Any: + try: + value = graph.value(subject=subject, predicate=predicate, default=default, any=False) + return value + except UniquenessError: + logger.append(f"Multiple values for unique value {predicate} found.") + return default + + +def parse_enum_value(enum_str: str, enum_class: Type[Enum], prefix: str) -> Enum: + try: + enum_without_rdf_prefix = remove_prefix(enum_str, prefix) + value = camel_case_to_snake_case(enum_without_rdf_prefix).upper() + return enum_class[value] + except KeyError: + raise SPDXParsingError([f"Invalid value for {enum_class}: {enum_str}"]) + + +def parse_spdx_id(resource: Union[URIRef, BNode], doc_namespace: str, graph: Graph) -> Optional[str]: + if not resource or isinstance(resource, BNode): + return None + if resource.startswith(f"{doc_namespace}#"): + return resource.fragment + if "#" in resource: + namespace_manager = NamespaceManager(graph) + return namespace_manager.normalizeUri(resource) + return resource.toPython() or None + + +# Python 3.9 introduced the method removeprefix() for strings, but as we are also supporting Python 3.7 and 3.8 we need +# to write our own helper method to delete prefixes. +def remove_prefix(string: str, prefix: str) -> str: + if string.startswith(prefix): + return string[len(prefix) :] + return string + + +def get_correctly_typed_triples( + logger: Logger, + graph: Graph, + subject: Optional[Node] = None, + predicate: Optional[Node] = None, + _object: Optional[Node] = None, +) -> Tuple[Union[BNode, URIRef], Node, Union[BNode, Literal, URIRef]]: + # this is a helper method to cast some rdf types from graph.triples() to be compatible with the + # code that follows + for s, p, o in graph.triples((subject, predicate, _object)): + if not isinstance(s, (BNode, URIRef)): + logger.append( + f"Warning: Subject {s} should be of type BNode or URIRef, but is {type(s).__name__}. " + f"This might lead to a failure." + ) + if not isinstance(o, (BNode, Literal, URIRef)): + logger.append( + f"Warning: Object {o} should be of type BNode, Literal or URIRef, but is {type(o).__name__}. " + f"This might lead to a failure." + ) + yield s, p, o + + +def get_value_from_graph( + logger: Logger, + graph: Graph, + subject: Optional[Node] = None, + predicate: Optional[Node] = RDF.value, + _object: Optional[Node] = None, + default: Optional[Any] = None, + _any: Optional[bool] = True, +) -> Optional[Union[URIRef, Literal, BNode]]: + # this is a helper method to cast some rdf types from graph.value() to be compatible with the + # code that follows + value = graph.value(subject=subject, predicate=predicate, object=_object, default=default, any=_any) + if value != default and value is not None and not isinstance(value, (URIRef, Literal, BNode)): + logger.append( + f"Warning: Node {value} should be of type BNode, Literal or URIRef, but is {type(value).__name__}. " + f"This might lead to a failure." + ) + return value diff --git a/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py b/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py new file mode 100644 index 000000000..2ae547232 --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py @@ -0,0 +1,62 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Optional, Union +from license_expression import LicenseExpression +from rdflib import RDF, Graph +from rdflib.term import BNode, Identifier, Node, URIRef + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import get_value_from_graph, remove_prefix +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE + + +def parse_license_expression( + license_expression_node: Union[URIRef, BNode, Node], + graph: Graph, + doc_namespace: str, + logger: Optional[Logger] = None, +) -> LicenseExpression: + if not logger: + logger = Logger() + + expression = "" + if license_expression_node.startswith(LICENSE_NAMESPACE): + expression = remove_prefix(license_expression_node, LICENSE_NAMESPACE) + return spdx_licensing.parse(expression) + if license_expression_node.startswith(doc_namespace): + expression = license_expression_node.fragment + return spdx_licensing.parse(expression) + + node_type = graph.value(license_expression_node, RDF.type) + if node_type == SPDX_NAMESPACE.ConjunctiveLicenseSet: + members = [] + for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)): + members.append(parse_license_expression(member_node, graph, doc_namespace, logger)) + expression = " AND ".join([str(member) for member in members]) + if node_type == SPDX_NAMESPACE.DisjunctiveLicenseSet: + members = [] + for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)): + members.append(parse_license_expression(member_node, graph, doc_namespace, logger)) + expression = " OR ".join([str(member) for member in members]) + if node_type == SPDX_NAMESPACE.WithExceptionOperator: + license_expression = parse_license_expression( + graph.value(license_expression_node, SPDX_NAMESPACE.member), graph, doc_namespace, logger + ) + exception = parse_license_exception( + get_value_from_graph(logger, graph, license_expression_node, SPDX_NAMESPACE.licenseException), + graph, + logger, + ) + expression = f"{license_expression} WITH {exception}" + + return spdx_licensing.parse(expression) + + +def parse_license_exception(exception_node: Identifier, graph: Graph, logger) -> str: + if exception_node.startswith(LICENSE_NAMESPACE): + exception = remove_prefix(exception_node, LICENSE_NAMESPACE) + else: + exception = get_value_from_graph(logger, graph, exception_node, SPDX_NAMESPACE.licenseExceptionId).toPython() + return exception diff --git a/src/spdx_tools/spdx/parser/rdf/package_parser.py b/src/spdx_tools/spdx/parser/rdf/package_parser.py new file mode 100644 index 000000000..668377162 --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/package_parser.py @@ -0,0 +1,207 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Optional, Union +from rdflib import DOAP, RDFS, Graph, URIRef +from rdflib.term import BNode + +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model import ( + ExternalPackageRef, + ExternalPackageRefCategory, + Package, + PackagePurpose, + PackageVerificationCode, +) +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.checksum_parser import parse_checksum +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( + get_correctly_typed_triples, + get_correctly_typed_value, + get_value_from_graph, + parse_enum_value, + parse_literal, + parse_literal_or_no_assertion_or_none, + parse_spdx_id, +) +from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression +from spdx_tools.spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE + + +def parse_package(package_node: Union[URIRef, BNode], graph: Graph, doc_namespace: str) -> Package: + logger = Logger() + spdx_id = parse_spdx_id(package_node, doc_namespace, graph) + name = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.name) + download_location = parse_literal_or_no_assertion_or_none( + logger, graph, package_node, SPDX_NAMESPACE.downloadLocation + ) + checksums = [] + for _, _, checksum_node in get_correctly_typed_triples(logger, graph, package_node, SPDX_NAMESPACE.checksum): + checksums.append(parse_checksum(checksum_node, graph)) + + version_info = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.versionInfo) + package_file_name = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.packageFileName) + + supplier = parse_literal_or_no_assertion_or_none( + logger, graph, package_node, SPDX_NAMESPACE.supplier, parsing_method=ActorParser.parse_actor + ) + originator = parse_literal_or_no_assertion_or_none( + logger, graph, package_node, SPDX_NAMESPACE.originator, parsing_method=ActorParser.parse_actor + ) + verification_code = parse_literal( + logger, + graph, + package_node, + SPDX_NAMESPACE.packageVerificationCode, + parsing_method=lambda x: parse_package_verification_code(x, graph), + ) + + external_package_refs = [] + for _, _, external_package_ref_node in get_correctly_typed_triples( + logger, graph, package_node, SPDX_NAMESPACE.externalRef + ): + external_package_refs.append(parse_external_package_ref(external_package_ref_node, graph, doc_namespace)) + files_analyzed = bool( + get_value_from_graph(logger, graph, package_node, SPDX_NAMESPACE.filesAnalyzed, default=True) + ) + license_concluded = parse_literal_or_no_assertion_or_none( + logger, + graph, + package_node, + SPDX_NAMESPACE.licenseConcluded, + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace, logger), + ) + license_declared = parse_literal_or_no_assertion_or_none( + logger, + graph, + package_node, + SPDX_NAMESPACE.licenseDeclared, + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace, logger), + ) + license_info_from_files = [] + for _, _, license_info_from_files_node in graph.triples((package_node, SPDX_NAMESPACE.licenseInfoFromFiles, None)): + license_info_from_files.append( + get_correctly_typed_value( + logger, + license_info_from_files_node, + lambda x: parse_license_expression(x, graph, doc_namespace, logger), + ) + ) + license_comment = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.licenseComments) + comment = parse_literal(logger, graph, package_node, RDFS.comment) + summary = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.summary) + description = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.description) + copyright_text = parse_literal_or_no_assertion_or_none(logger, graph, package_node, SPDX_NAMESPACE.copyrightText) + source_info = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.sourceInfo) + primary_package_purpose = parse_literal( + logger, + graph, + package_node, + SPDX_NAMESPACE.primaryPackagePurpose, + parsing_method=lambda x: parse_enum_value(x, PackagePurpose, SPDX_NAMESPACE.purpose_), + ) + homepage = parse_literal(logger, graph, package_node, DOAP.homepage) + attribution_texts = [] + for _, _, attribution_text_literal in get_correctly_typed_triples( + logger, graph, package_node, SPDX_NAMESPACE.attributionText, None + ): + attribution_texts.append(attribution_text_literal.toPython()) + + release_date = parse_literal( + logger, graph, package_node, SPDX_NAMESPACE.releaseDate, parsing_method=datetime_from_str + ) + built_date = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.builtDate, parsing_method=datetime_from_str) + valid_until_date = parse_literal( + logger, graph, package_node, SPDX_NAMESPACE.validUntilDate, parsing_method=datetime_from_str + ) + raise_parsing_error_if_logger_has_messages(logger, "Package") + package = construct_or_raise_parsing_error( + Package, + dict( + name=name, + spdx_id=spdx_id, + download_location=download_location, + version=version_info, + file_name=package_file_name, + supplier=supplier, + originator=originator, + files_analyzed=files_analyzed, + verification_code=verification_code, + checksums=checksums, + homepage=homepage, + source_info=source_info, + license_concluded=license_concluded, + license_info_from_files=license_info_from_files, + license_declared=license_declared, + license_comment=license_comment, + copyright_text=copyright_text, + summary=summary, + description=description, + comment=comment, + external_references=external_package_refs, + attribution_texts=attribution_texts, + primary_package_purpose=primary_package_purpose, + release_date=release_date, + built_date=built_date, + valid_until_date=valid_until_date, + ), + ) + + return package + + +def parse_package_verification_code( + package_verification_code_node: URIRef, graph: Graph +) -> Optional[PackageVerificationCode]: + logger = Logger() + value = parse_literal(logger, graph, package_verification_code_node, SPDX_NAMESPACE.packageVerificationCodeValue) + excluded_files = [] + for _, _, excluded_file_literal in graph.triples( + (package_verification_code_node, SPDX_NAMESPACE.packageVerificationCodeExcludedFile, None) + ): + excluded_files.append(excluded_file_literal.toPython()) + + raise_parsing_error_if_logger_has_messages(logger, "PackageVerificationCode") + package_verification_code = construct_or_raise_parsing_error( + PackageVerificationCode, dict(value=value, excluded_files=excluded_files) + ) + return package_verification_code + + +def parse_external_package_ref(external_package_ref_node: BNode, graph: Graph, doc_namespace) -> ExternalPackageRef: + logger = Logger() + ref_locator = parse_literal(logger, graph, external_package_ref_node, SPDX_NAMESPACE.referenceLocator) + ref_category = parse_literal( + logger, + graph, + external_package_ref_node, + SPDX_NAMESPACE.referenceCategory, + parsing_method=lambda x: parse_enum_value(x, ExternalPackageRefCategory, SPDX_NAMESPACE.referenceCategory_), + ) + ref_type = parse_literal( + logger, + graph, + external_package_ref_node, + SPDX_NAMESPACE.referenceType, + parsing_method=lambda x: parse_external_package_ref_type(x, doc_namespace), + ) + comment = parse_literal(logger, graph, external_package_ref_node, RDFS.comment) + + raise_parsing_error_if_logger_has_messages(logger, "ExternalPackageRef") + external_package_ref = construct_or_raise_parsing_error( + ExternalPackageRef, dict(category=ref_category, reference_type=ref_type, locator=ref_locator, comment=comment) + ) + return external_package_ref + + +def parse_external_package_ref_type(external_package_ref_type_resource: URIRef, doc_namespace: str) -> str: + if external_package_ref_type_resource.startswith(doc_namespace): + return external_package_ref_type_resource.fragment + if external_package_ref_type_resource.startswith(REFERENCE_NAMESPACE): + return external_package_ref_type_resource.replace(REFERENCE_NAMESPACE, "") + return external_package_ref_type_resource.toPython() diff --git a/src/spdx_tools/spdx/parser/rdf/rdf_parser.py b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py new file mode 100644 index 000000000..5dc0b8f19 --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py @@ -0,0 +1,96 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Any, Dict +from rdflib import RDF, Graph + +from spdx_tools.spdx.model import Document, RelationshipType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.annotation_parser import parse_annotation +from spdx_tools.spdx.parser.rdf.creation_info_parser import parse_creation_info +from spdx_tools.spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info +from spdx_tools.spdx.parser.rdf.file_parser import parse_file +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import get_correctly_typed_triples +from spdx_tools.spdx.parser.rdf.package_parser import parse_package +from spdx_tools.spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship +from spdx_tools.spdx.parser.rdf.snippet_parser import parse_snippet +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def parse_from_file(file_name: str, encoding: str = "utf-8") -> Document: + graph = Graph() + with open(file_name, encoding=encoding) as file: + graph.parse(file, format="xml") + + document: Document = translate_graph_to_document(graph) + return document + + +def translate_graph_to_document(graph: Graph) -> Document: + parsed_fields: Dict[str, Any] = dict() + logger = Logger() + creation_info, doc_node = parse_creation_info(graph) + + parsed_fields["creation_info"] = creation_info + + for element, triple, parsing_method in [ + ("packages", (None, RDF.type, SPDX_NAMESPACE.Package), parse_package), + ("files", (None, RDF.type, SPDX_NAMESPACE.File), parse_file), + ("snippets", (None, RDF.type, SPDX_NAMESPACE.Snippet), parse_snippet), + ]: + elements = [] + for element_node, _, _ in get_correctly_typed_triples(logger, graph, *triple): + try: + elements.append(parsing_method(element_node, graph, creation_info.document_namespace)) + except SPDXParsingError as err: + logger.extend(err.get_messages()) + parsed_fields[element] = elements + + for element, triple, parsing_method in [ + ("annotations", (None, SPDX_NAMESPACE.annotation, None), parse_annotation), + ("relationships", (None, SPDX_NAMESPACE.relationship, None), parse_relationship), + ]: + elements = [] + for parent_node, _, element_node in graph.triples(triple): + try: + elements.append(parsing_method(element_node, graph, parent_node, creation_info.document_namespace)) + except SPDXParsingError as err: + logger.extend(err.get_messages()) + parsed_fields[element] = elements + + for triple, relationship_type in [ + ((None, SPDX_NAMESPACE.hasFile, None), RelationshipType.CONTAINS), + ((None, SPDX_NAMESPACE.describesPackage, None), RelationshipType.DESCRIBES), + ]: + for parent_node, _, element_node in get_correctly_typed_triples(logger, graph, *triple): + try: + relationship = parse_implicit_relationship( + parent_node, relationship_type, element_node, graph, creation_info.document_namespace + ) + if relationship not in parsed_fields["relationships"]: + parsed_fields["relationships"].append(relationship) + + except SPDXParsingError as err: + logger.extend(err.get_messages()) + + extracted_licensing_infos = [] + for _, _, extracted_licensing_info_node in get_correctly_typed_triples( + logger, graph, None, SPDX_NAMESPACE.hasExtractedLicensingInfo + ): + try: + extracted_licensing_infos.append( + parse_extracted_licensing_info(extracted_licensing_info_node, graph, creation_info.document_namespace) + ) + except SPDXParsingError as err: + logger.extend(err.get_messages()) + parsed_fields["extracted_licensing_info"] = extracted_licensing_infos + + raise_parsing_error_if_logger_has_messages(logger) + document = construct_or_raise_parsing_error(Document, parsed_fields) + + return document diff --git a/src/spdx_tools/spdx/parser/rdf/relationship_parser.py b/src/spdx_tools/spdx/parser/rdf/relationship_parser.py new file mode 100644 index 000000000..562e0ab92 --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/relationship_parser.py @@ -0,0 +1,73 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDFS, Graph, URIRef +from rdflib.term import Node + +from spdx_tools.spdx.model import Relationship, RelationshipType +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( + parse_enum_value, + parse_literal, + parse_literal_or_no_assertion_or_none, + parse_spdx_id, +) +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def parse_relationship(relationship_node: Node, graph: Graph, parent_node: URIRef, doc_namespace: str) -> Relationship: + logger = Logger() + spdx_element_id = parse_spdx_id(parent_node, doc_namespace, graph) + + relationship_type = parse_literal( + logger, + graph, + relationship_node, + SPDX_NAMESPACE.relationshipType, + parsing_method=lambda x: parse_enum_value(x, RelationshipType, SPDX_NAMESPACE.relationshipType_), + ) + related_spdx_element = parse_literal_or_no_assertion_or_none( + logger, + graph, + relationship_node, + SPDX_NAMESPACE.relatedSpdxElement, + parsing_method=lambda x: parse_spdx_id(x, doc_namespace, graph), + ) + + comment = parse_literal(logger, graph, relationship_node, RDFS.comment) + raise_parsing_error_if_logger_has_messages(logger, "Relationship") + relationship = construct_or_raise_parsing_error( + Relationship, + dict( + spdx_element_id=spdx_element_id, + relationship_type=relationship_type, + related_spdx_element_id=related_spdx_element, + comment=comment, + ), + ) + + return relationship + + +def parse_implicit_relationship( + spdx_element_node: URIRef, + relationship_type: RelationshipType, + related_spdx_element_node: URIRef, + graph: Graph, + doc_namespace: str, +) -> Relationship: + spdx_element_id = parse_spdx_id(spdx_element_node, doc_namespace, graph) + related_spdx_element_id = parse_spdx_id(related_spdx_element_node, doc_namespace, graph) + relationship = construct_or_raise_parsing_error( + Relationship, + dict( + spdx_element_id=spdx_element_id, + relationship_type=relationship_type, + related_spdx_element_id=related_spdx_element_id, + ), + ) + return relationship diff --git a/src/spdx_tools/spdx/parser/rdf/snippet_parser.py b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py new file mode 100644 index 000000000..d09671f60 --- /dev/null +++ b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py @@ -0,0 +1,147 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict, Optional, Tuple, Union +from rdflib import RDF, RDFS, Graph +from rdflib.exceptions import UniquenessError +from rdflib.term import BNode, Node, URIRef + +from spdx_tools.spdx.model import Snippet +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( + apply_parsing_method_or_log_error, + get_correctly_typed_triples, + get_correctly_typed_value, + get_value_from_graph, + parse_literal, + parse_literal_or_no_assertion_or_none, + parse_spdx_id, +) +from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression +from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE + + +def parse_snippet(snippet_node: Union[URIRef, BNode], graph: Graph, doc_namespace: str) -> Snippet: + logger = Logger() + spdx_id = parse_spdx_id(snippet_node, doc_namespace, graph) + file_spdx_id_uri = get_value_from_graph( + logger, graph, subject=snippet_node, predicate=SPDX_NAMESPACE.snippetFromFile + ) + file_spdx_id = parse_spdx_id(file_spdx_id_uri, doc_namespace, graph) + byte_range = None + line_range = None + for _, _, start_end_pointer in graph.triples((snippet_node, SPDX_NAMESPACE.range, None)): + parsed_range = apply_parsing_method_or_log_error( + logger, start_end_pointer, parsing_method=lambda x: parse_ranges(x, graph) + ) + byte_range, line_range = set_range_or_log_error(byte_range, line_range, logger, parsed_range) + + license_concluded = parse_literal_or_no_assertion_or_none( + logger, + graph, + snippet_node, + SPDX_NAMESPACE.licenseConcluded, + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace, logger), + ) + license_info_in_snippet = [] + for _, _, license_info_in_snippet_node in graph.triples((snippet_node, SPDX_NAMESPACE.licenseInfoInSnippet, None)): + license_info_in_snippet.append( + get_correctly_typed_value( + logger, + license_info_in_snippet_node, + lambda x: parse_license_expression(x, graph, doc_namespace, logger), + ) + ) + license_comment = parse_literal(logger, graph, snippet_node, SPDX_NAMESPACE.licenseComments) + copyright_text = parse_literal_or_no_assertion_or_none(logger, graph, snippet_node, SPDX_NAMESPACE.copyrightText) + comment = parse_literal(logger, graph, snippet_node, RDFS.comment) + name = parse_literal(logger, graph, snippet_node, SPDX_NAMESPACE.name) + attribution_texts = [] + for _, _, attribution_text_literal in get_correctly_typed_triples( + logger, graph, snippet_node, SPDX_NAMESPACE.attributionText, None + ): + attribution_texts.append(attribution_text_literal.toPython()) + + raise_parsing_error_if_logger_has_messages(logger, "Snippet") + snippet = construct_or_raise_parsing_error( + Snippet, + dict( + spdx_id=spdx_id, + file_spdx_id=file_spdx_id, + byte_range=byte_range, + line_range=line_range, + license_concluded=license_concluded, + license_info_in_snippet=license_info_in_snippet, + license_comment=license_comment, + copyright_text=copyright_text, + comment=comment, + name=name, + attribution_texts=attribution_texts, + ), + ) + return snippet + + +def set_range_or_log_error( + byte_range: Optional[Tuple[int, int]], + line_range: Optional[Tuple[int, int]], + logger: Logger, + parsed_range: Dict[str, Tuple[int, int]], +) -> Tuple[Optional[Tuple[int, int]], Optional[Tuple[int, int]]]: + if not parsed_range: + return byte_range, line_range + if "ByteOffsetPointer" in parsed_range.keys() and not byte_range: + byte_range = parsed_range["ByteOffsetPointer"] + elif "ByteOffsetPointer" in parsed_range.keys() and byte_range: + logger.append("Multiple ByteOffsetPointer found.") + elif "LineCharPointer" in parsed_range.keys() and not line_range: + line_range = parsed_range["LineCharPointer"] + elif "LineCharPointer" in parsed_range.keys() and line_range: + logger.append("Multiple LineCharPointer found.") + return byte_range, line_range + + +def parse_ranges(start_end_pointer: BNode, graph: Graph) -> Dict[str, Tuple[int, int]]: + range_values = dict() + start_pointer_type, start_pointer_node = get_pointer_type(graph, POINTER_NAMESPACE.startPointer, start_end_pointer) + end_pointer_type, end_pointer_node = get_pointer_type(graph, POINTER_NAMESPACE.endPointer, start_end_pointer) + + if start_pointer_type != end_pointer_type: + raise SPDXParsingError(["Types of startPointer and endPointer don't match"]) + + range_values["startPointer"] = parse_range_value(graph, start_pointer_node, POINTER_MATCHING[start_pointer_type]) + range_values["endPointer"] = parse_range_value(graph, end_pointer_node, POINTER_MATCHING[end_pointer_type]) + + return {str(start_pointer_type.fragment): (range_values["startPointer"], range_values["endPointer"])} + + +def get_pointer_type(graph: Graph, pointer: URIRef, start_end_pointer: BNode) -> Tuple[URIRef, Node]: + try: + pointer_node = graph.value(start_end_pointer, pointer, any=False) + except UniquenessError: + raise SPDXParsingError([f"Multiple values for {pointer.fragment}"]) + if not pointer_node: + raise SPDXParsingError([f"Couldn't find pointer of type {pointer.fragment}."]) + pointer_type = get_value_from_graph(Logger(), graph, pointer_node, RDF.type) + return pointer_type, pointer_node + + +POINTER_MATCHING = { + POINTER_NAMESPACE.ByteOffsetPointer: POINTER_NAMESPACE.offset, + POINTER_NAMESPACE.LineCharPointer: POINTER_NAMESPACE.lineNumber, +} + + +def parse_range_value(graph: Graph, pointer_node: Node, predicate: URIRef) -> Optional[int]: + try: + value = get_value_from_graph(Logger(), graph, pointer_node, predicate, _any=False) + except UniquenessError: + raise SPDXParsingError([f"Multiple values for {predicate.fragment} found."]) + if value: + value = int(value.toPython()) + return value diff --git a/src/spdx_tools/spdx/parser/tagvalue/__init__.py b/src/spdx_tools/spdx/parser/tagvalue/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py b/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py new file mode 100644 index 000000000..ea528a434 --- /dev/null +++ b/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py @@ -0,0 +1,134 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import re + +from beartype.typing import Any, Callable, Dict, Optional +from ply.yacc import YaccProduction + +from spdx_tools.spdx.casing_tools import camel_case_to_snake_case +from spdx_tools.spdx.model import ( + Annotation, + Checksum, + ChecksumAlgorithm, + CreationInfo, + ExtractedLicensingInfo, + File, + Package, + Snippet, +) +from spdx_tools.spdx.parser.error import SPDXParsingError + + +def grammar_rule(doc): + # this is a helper method to use decorators for the parsing methods instead of docstrings + def decorate(func): + func.__doc__ = doc + return func + + return decorate + + +def str_from_text(text: Optional[str]) -> Optional[str]: + regex = re.compile("((.|\n)+)", re.UNICODE) + match = regex.match(text) + if match: + return match.group(1) + elif isinstance(text, str): + return text + else: + return None + + +def parse_checksum(checksum_str: str) -> Checksum: + # The lexer and the corresponding regex for the token CHECKSUM and EXT_DOC_REF_CHECKSUM ensure that the passed + # checksum_str is formatted in the way that the following lines of code can't cause an error. + algorithm, value = checksum_str.split(":") + algorithm = ChecksumAlgorithm[algorithm.upper().replace("-", "_")] + value = value.strip() + checksum = Checksum(algorithm, value) + return checksum + + +def set_value( + parsed_value: YaccProduction, + dict_to_fill: Dict[str, Any], + argument_name: Optional[str] = None, + method_to_apply: Callable = lambda x: x, +): + if not argument_name: + argument_name = get_property_name(parsed_value[1]) + if argument_name in dict_to_fill: + dict_to_fill["logger"].append(f"Multiple values for {parsed_value[1]} found. Line: {parsed_value.lineno(1)}") + return + try: + dict_to_fill[argument_name] = method_to_apply(parsed_value[2]) + except SPDXParsingError as err: + dict_to_fill["logger"].append(err.get_messages()) + except ValueError as err: + dict_to_fill["logger"].append(err.args[0]) + except KeyError: + dict_to_fill["logger"].append(f"Invalid {parsed_value[1]}: {parsed_value[2]}. Line: {parsed_value.lineno(1)}") + + +def get_property_name(tag: str): + if tag not in TAG_DATA_MODEL_FIELD.keys(): + return camel_case_to_snake_case(tag) + return TAG_DATA_MODEL_FIELD[tag][1] + + +# This dictionary serves as a mapping from a tag to the corresponding class and field in the internal data model. +# This mapping is not complete as we only list the values which can be parsed by a generic method and don't need any +# individual logic. +TAG_DATA_MODEL_FIELD = { + "SPDXVersion": (CreationInfo, "spdx_version"), + "DataLicense": (CreationInfo, "data_license"), + "DocumentName": (CreationInfo, "name"), + "DocumentComment": (CreationInfo, "document_comment"), + "DocumentNamespace": (CreationInfo, "document_namespace"), + "Creator": (CreationInfo, "creator"), + "Created": (CreationInfo, "created"), + "CreatorComment": (CreationInfo, "creator_comment"), + "LicenseListVersion": (CreationInfo, "license_list_version"), + "ExternalDocumentRef": (CreationInfo, "external_document_refs"), + "FileName": (File, "name"), + "FileType": (File, "file_type"), + "FileChecksum": (File, "checksums"), + "FileNotice": (File, "notice"), + "FileCopyrightText": (File, "copyright_text"), + "LicenseComments": (File, "license_comment"), + "FileComment": (File, "comment"), + "LicenseConcluded": (File, "license_concluded"), + "LicenseDeclared": (File, "license_declared"), + "PackageName": (Package, "name"), + "PackageComment": (Package, "comment"), + "PackageCopyrightText": (Package, "copyright_text"), + "PackageLicenseComments": (Package, "license_comment"), + "PackageLicenseDeclared": (Package, "license_declared"), + "PackageLicenseConcluded": (Package, "license_concluded"), + "PackageFileName": (Package, "file_name"), + "PackageVersion": (Package, "version"), + "PackageDownloadLocation": (Package, "download_location"), + "PackageSummary": (Package, "summary"), + "PackageSourceInfo": (Package, "source_info"), + "PackageSupplier": (Package, "supplier"), + "PackageOriginator": (Package, "originator"), + "PackageDescription": (Package, "description"), + "PackageHomePage": (Package, "homepage"), + "SnippetSPDXID": (Snippet, "spdx_id"), + "SnippetFromFileSPDXID": (Snippet, "file_spdx_id"), + "SnippetName": (Snippet, "name"), + "SnippetComment": (Snippet, "comment"), + "SnippetCopyrightText": (Snippet, "copyright_text"), + "SnippetLicenseComments": (Snippet, "license_comment"), + "SnippetLicenseConcluded": (Snippet, "license_concluded"), + "SnippetByteRange": (Snippet, "byte_range"), + "SnippetLineRange": (Snippet, "line_range"), + "Annotator": (Annotation, "annotator"), + "SPDXREF": (Annotation, "spdx_id"), + "AnnotationComment": (Annotation, "annotation_comment"), + "LicenseID": (ExtractedLicensingInfo, "license_id"), + "ExtractedText": (ExtractedLicensingInfo, "extracted_text"), + "LicenseComment": (ExtractedLicensingInfo, "comment"), + "LicenseName": (ExtractedLicensingInfo, "license_name"), +} diff --git a/src/spdx_tools/spdx/parser/tagvalue/lexer.py b/src/spdx_tools/spdx/parser/tagvalue/lexer.py new file mode 100644 index 000000000..9a857827b --- /dev/null +++ b/src/spdx_tools/spdx/parser/tagvalue/lexer.py @@ -0,0 +1,207 @@ +# Copyright (c) 2014 Ahmed H. Ismail +# Copyright (c) 2023 spdx contributors +# SPDX-License-Identifier: Apache-2.0 +# 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. + +from ply import lex +from ply.lex import TOKEN + + +class SPDXLexer: + reserved = { + # Top level fields + "SPDXVersion": "DOC_VERSION", + "DataLicense": "DOC_LICENSE", + "DocumentName": "DOC_NAME", + "SPDXID": "SPDX_ID", + "DocumentComment": "DOC_COMMENT", + "DocumentNamespace": "DOC_NAMESPACE", + "ExternalDocumentRef": "EXT_DOC_REF", + # Creation info fields + "Creator": "CREATOR", + "Created": "CREATED", + "CreatorComment": "CREATOR_COMMENT", + "LicenseListVersion": "LICENSE_LIST_VERSION", + # Annotation fields + "Annotator": "ANNOTATOR", + "AnnotationDate": "ANNOTATION_DATE", + "AnnotationComment": "ANNOTATION_COMMENT", + "AnnotationType": "ANNOTATION_TYPE", + "SPDXREF": "ANNOTATION_SPDX_ID", + # Relationship fields + "Relationship": "RELATIONSHIP", + "RelationshipComment": "RELATIONSHIP_COMMENT", + # Package fields + "PackageName": "PKG_NAME", + "PackageVersion": "PKG_VERSION", + "PackageDownloadLocation": "PKG_DOWNLOAD_LOCATION", + "FilesAnalyzed": "PKG_FILES_ANALYZED", + "PackageSummary": "PKG_SUMMARY", + "PackageSourceInfo": "PKG_SOURCE_INFO", + "PackageFileName": "PKG_FILE_NAME", + "PackageSupplier": "PKG_SUPPLIER", + "PackageOriginator": "PKG_ORIGINATOR", + "PackageChecksum": "PKG_CHECKSUM", + "PackageVerificationCode": "PKG_VERIFICATION_CODE", + "PackageDescription": "PKG_DESCRIPTION", + "PackageComment": "PKG_COMMENT", + "PackageLicenseDeclared": "PKG_LICENSE_DECLARED", + "PackageLicenseConcluded": "PKG_LICENSE_CONCLUDED", + "PackageLicenseInfoFromFiles": "PKG_LICENSE_INFO", + "PackageLicenseComments": "PKG_LICENSE_COMMENT", + "PackageCopyrightText": "PKG_COPYRIGHT_TEXT", + "PackageHomePage": "PKG_HOMEPAGE", + "ExternalRef": "PKG_EXTERNAL_REF", + "ExternalRefComment": "PKG_EXTERNAL_REF_COMMENT", + "PackageAttributionText": "PKG_ATTRIBUTION_TEXT", + "PrimaryPackagePurpose": "PRIMARY_PACKAGE_PURPOSE", + "BuiltDate": "BUILT_DATE", + "ReleaseDate": "RELEASE_DATE", + "ValidUntilDate": "VALID_UNTIL_DATE", + # File fields + "FileName": "FILE_NAME", + "FileType": "FILE_TYPE", + "FileChecksum": "FILE_CHECKSUM", + "LicenseConcluded": "FILE_LICENSE_CONCLUDED", + "LicenseInfoInFile": "FILE_LICENSE_INFO", + "FileCopyrightText": "FILE_COPYRIGHT_TEXT", + "LicenseComments": "FILE_LICENSE_COMMENT", + "FileComment": "FILE_COMMENT", + "FileNotice": "FILE_NOTICE", + "FileContributor": "FILE_CONTRIBUTOR", + "FileAttributionText": "FILE_ATTRIBUTION_TEXT", + # ExtractedLicensingInfo fields + "LicenseID": "LICENSE_ID", + "ExtractedText": "LICENSE_TEXT", + "LicenseName": "LICENSE_NAME", + "LicenseCrossReference": "LICENSE_CROSS_REF", + "LicenseComment": "LICENSE_COMMENT", + # Snippet fields + "SnippetSPDXID": "SNIPPET_SPDX_ID", + "SnippetName": "SNIPPET_NAME", + "SnippetComment": "SNIPPET_COMMENT", + "SnippetCopyrightText": "SNIPPET_COPYRIGHT_TEXT", + "SnippetLicenseComments": "SNIPPET_LICENSE_COMMENT", + "SnippetFromFileSPDXID": "SNIPPET_FILE_SPDXID", + "SnippetLicenseConcluded": "SNIPPET_LICENSE_CONCLUDED", + "LicenseInfoInSnippet": "SNIPPET_LICENSE_INFO", + "SnippetAttributionText": "SNIPPET_ATTRIBUTION_TEXT", + "SnippetByteRange": "SNIPPET_BYTE_RANGE", + "SnippetLineRange": "SNIPPET_LINE_RANGE", + # Common fields + "NOASSERTION": "NO_ASSERTION", + "NONE": "NONE", + } + states = (("text", "exclusive"),) + + tokens = [ + "TEXT", + "TOOL_VALUE", + "UNKNOWN_TAG", + "ORGANIZATION_VALUE", + "PERSON_VALUE", + "ISO8601_DATE", + "LINE", + "CHECKSUM", + ] + list(reserved.values()) + + def __init__(self): + self.lexer = None + + @TOKEN(r":\s*") + def t_text(self, t): + t.lexer.text_start = t.lexer.lexpos - len("") + t.lexer.begin("text") + + @TOKEN(r"\s*") + def t_text_end(self, t): + t.type = "TEXT" + t.value = t.lexer.lexdata[t.lexer.text_start : t.lexer.lexpos] + t.lexer.lineno += t.value.count("\n") + t.value = t.value.strip() + t.lexer.begin("INITIAL") + return t + + @TOKEN(r".|\n") + def t_text_any(self, t): + pass + + def t_text_error(self, t): + print("Lexer error in text state") + + @TOKEN( + r":\s*(ADLER32|BLAKE2b-256|BLAKE2b-384|BLAKE2b-512|BLAKE3|MD2|MD4|MD5|MD6|SHA1|SHA224|SHA256|SHA384|SHA512|" + r"SHA3-256|SHA3-384|SHA3-512):\s*([a-f0-9]*)" + ) + def t_CHECKSUM(self, t): + t.value = t.value[1:].strip() + return t + + @TOKEN(r":\s*Tool:.+") + def t_TOOL_VALUE(self, t): + t.value = t.value[1:].strip() + return t + + @TOKEN(r":\s*Organization:.+") + def t_ORGANIZATION_VALUE(self, t): + t.value = t.value[1:].strip() + return t + + @TOKEN(r":\s*Person:.+") + def t_PERSON_VALUE(self, t): + t.value = t.value[1:].strip() + return t + + @TOKEN(r":\s*\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ") + def t_ISO8601_DATE(self, t): + t.value = t.value[1:].strip() + return t + + @TOKEN(r"[a-zA-Z]+") + def t_KEYWORD_AS_TAG(self, t): + t.type = self.reserved.get(t.value, "UNKNOWN_TAG") + t.value = t.value.strip() + return t + + @TOKEN(r":.+") + def t_LINE_OR_KEYWORD_VALUE(self, t): + t.value = t.value[1:].strip() + if t.value in self.reserved.keys(): + t.type = self.reserved[t.value] + else: + t.type = "LINE" + return t + + @TOKEN(r"\#.*") + def t_comment(self, t): + pass + + @TOKEN(r"\n+") + def t_newline(self, t): + t.lexer.lineno += len(t.value) + + @TOKEN(r"[ \t]+") + def t_whitespace(self, t): + pass + + def build(self, **kwargs): + self.lexer = lex.lex(module=self, **kwargs) + + def token(self): + return self.lexer.token() + + def input(self, data): + self.lexer.input(data) + + def t_error(self, t): + t.lexer.skip(1) + t.value = "Lexer error" + return t diff --git a/src/spdx_tools/spdx/parser/tagvalue/parser.py b/src/spdx_tools/spdx/parser/tagvalue/parser.py new file mode 100644 index 000000000..50096bda2 --- /dev/null +++ b/src/spdx_tools/spdx/parser/tagvalue/parser.py @@ -0,0 +1,608 @@ +# Copyright (c) 2014 Ahmed H. Ismail +# Copyright (c) 2023 spdx contributors +# SPDX-License-Identifier: Apache-2.0 +# 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. + +import re + +from beartype.typing import Any, Dict, List +from license_expression import ExpressionError, get_spdx_licensing +from ply import yacc +from ply.yacc import LRParser + +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model import ( + Annotation, + AnnotationType, + CreationInfo, + Document, + ExternalDocumentRef, + ExternalPackageRef, + ExternalPackageRefCategory, + ExtractedLicensingInfo, + File, + FileType, + Package, + PackagePurpose, + PackageVerificationCode, + Relationship, + RelationshipType, + Snippet, + SpdxNoAssertion, + SpdxNone, + Version, +) +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.tagvalue.helper_methods import ( + TAG_DATA_MODEL_FIELD, + grammar_rule, + parse_checksum, + set_value, + str_from_text, +) +from spdx_tools.spdx.parser.tagvalue.lexer import SPDXLexer + +CLASS_MAPPING = dict( + File="files", + Annotation="annotations", + Relationship="relationships", + Snippet="snippets", + Package="packages", + ExtractedLicensingInfo="extracted_licensing_info", +) +ELEMENT_EXPECTED_START_TAG = dict( + File="FileName", + Annotation="Annotator", + Relationship="Relationship", + Snippet="SnippetSPDXID", + Package="PackageName", + ExtractedLicensingInfo="LicenseID", +) + + +class Parser: + tokens: List[str] + logger: Logger + current_element: Dict[str, Any] + creation_info: Dict[str, Any] + elements_built: Dict[str, Any] + lex: SPDXLexer + yacc: LRParser + + def __init__(self, **kwargs): + self.tokens = SPDXLexer.tokens + self.logger = Logger() + self.current_element = {"logger": Logger()} + self.creation_info = {"logger": Logger()} + self.elements_built = dict() + self.lex = SPDXLexer() + self.lex.build(reflags=re.UNICODE) + self.yacc = yacc.yacc(module=self, **kwargs) + + @grammar_rule("start : start attrib ") + def p_start_start_attrib(self, p): + pass + + @grammar_rule("start : attrib ") + def p_start_attrib(self, p): + pass + + @grammar_rule( + "attrib : spdx_version\n| spdx_id\n| data_license\n| doc_name\n| document_comment\n| document_namespace\n| " + "creator\n| created\n| creator_comment\n| license_list_version\n| ext_doc_ref\n" + # attributes for file + "| file_name\n| file_type\n| file_checksum\n| file_license_concluded\n| file_license_info\n" + "| file_copyright_text\n| file_license_comment\n| file_attribution_text\n| file_notice\n| file_comment\n" + "| file_contributor\n" + # attributes for annotation + "| annotator\n| annotation_date\n| annotation_comment\n| annotation_type\n| annotation_spdx_id\n" + # attributes for relationship + "| relationship\n" + # attributes for snippet + "| snippet_spdx_id\n| snippet_name\n| snippet_comment\n| snippet_attribution_text\n| snippet_copyright_text\n" + "| snippet_license_comment\n| file_spdx_id\n| snippet_license_concluded\n| snippet_license_info\n" + "| snippet_byte_range\n| snippet_line_range\n" + # attributes for package + "| package_name\n| package_version\n| download_location\n| files_analyzed\n| homepage\n" + "| summary\n| source_info\n| pkg_file_name\n| supplier\n| originator\n| pkg_checksum\n" + "| verification_code\n| description\n| pkg_comment\n| pkg_attribution_text\n| pkg_license_declared\n" + "| pkg_license_concluded\n| pkg_license_info\n| pkg_license_comment\n| pkg_copyright_text\n" + "| pkg_external_ref\n| primary_package_purpose\n| built_date\n| release_date\n| valid_until_date\n" + # attributes for extracted licensing info + "| license_id\n| extracted_text\n| license_name\n| license_cross_ref\n| lic_comment\n" + "| unknown_tag " + ) + def p_attrib(self, p): + pass + + # general parsing methods + @grammar_rule( + "license_id : LICENSE_ID error\n license_cross_ref : LICENSE_CROSS_REF error\n " + "lic_comment : LICENSE_COMMENT error\n license_name : LICENSE_NAME error\n " + "extracted_text : LICENSE_TEXT error\n " + "file_name : FILE_NAME error\n file_contributor : FILE_CONTRIBUTOR error\n " + "file_notice : FILE_NOTICE error\n file_copyright_text : FILE_COPYRIGHT_TEXT error\n " + "file_license_comment : FILE_LICENSE_COMMENT error\n " + "file_license_info : FILE_LICENSE_INFO error\n file_comment : FILE_COMMENT error\n " + "file_checksum : FILE_CHECKSUM error\n file_license_concluded : FILE_LICENSE_CONCLUDED error\n " + "file_type : FILE_TYPE error\n file_attribution_text : FILE_ATTRIBUTION_TEXT error\n " + "package_name : PKG_NAME error\n pkg_attribution_text : PKG_ATTRIBUTION_TEXT error\n " + "description : PKG_DESCRIPTION error\n pkg_comment : PKG_COMMENT error\n " + "summary : PKG_SUMMARY error\n pkg_copyright_text : PKG_COPYRIGHT_TEXT error\n " + "pkg_external_ref : PKG_EXTERNAL_REF error\n pkg_license_comment : PKG_LICENSE_COMMENT error\n " + "pkg_license_declared : PKG_LICENSE_DECLARED error\n pkg_license_info : PKG_LICENSE_INFO error \n " + "pkg_license_concluded : PKG_LICENSE_CONCLUDED error\n source_info : PKG_SOURCE_INFO error\n " + "homepage : PKG_HOMEPAGE error\n pkg_checksum : PKG_CHECKSUM error\n " + "verification_code : PKG_VERIFICATION_CODE error\n originator : PKG_ORIGINATOR error\n " + "download_location : PKG_DOWNLOAD_LOCATION error\n files_analyzed : PKG_FILES_ANALYZED error\n " + "supplier : PKG_SUPPLIER error\n pkg_file_name : PKG_FILE_NAME error\n " + "package_version : PKG_VERSION error\n primary_package_purpose : PRIMARY_PACKAGE_PURPOSE error\n " + "built_date : BUILT_DATE error\n release_date : RELEASE_DATE error\n " + "valid_until_date : VALID_UNTIL_DATE error\n snippet_spdx_id : SNIPPET_SPDX_ID error\n " + "snippet_name : SNIPPET_NAME error\n snippet_comment : SNIPPET_COMMENT error\n " + "snippet_attribution_text : SNIPPET_ATTRIBUTION_TEXT error\n " + "snippet_copyright_text : SNIPPET_COPYRIGHT_TEXT error\n " + "snippet_license_comment : SNIPPET_LICENSE_COMMENT error\n file_spdx_id : SNIPPET_FILE_SPDXID error\n " + "snippet_license_concluded : SNIPPET_LICENSE_CONCLUDED error\n " + "snippet_license_info : SNIPPET_LICENSE_INFO error\n " + "snippet_byte_range : SNIPPET_BYTE_RANGE error\n snippet_line_range : SNIPPET_LINE_RANGE error\n " + "annotator : ANNOTATOR error\n annotation_date : ANNOTATION_DATE error\n " + "annotation_comment : ANNOTATION_COMMENT error\n annotation_type : ANNOTATION_TYPE error\n " + "annotation_spdx_id : ANNOTATION_SPDX_ID error\n relationship : RELATIONSHIP error" + ) + def p_current_element_error(self, p): + if p[1] in ELEMENT_EXPECTED_START_TAG.values(): + self.initialize_new_current_element(TAG_DATA_MODEL_FIELD[p[1]][0]) + self.current_element["logger"].append( + f"Error while parsing {p[1]}: Token did not match specified grammar rule. Line: {p.lineno(1)}" + ) + + @grammar_rule( + "license_name : LICENSE_NAME line_or_no_assertion\n extracted_text : LICENSE_TEXT text_or_line\n " + "lic_comment : LICENSE_COMMENT text_or_line\n license_id : LICENSE_ID LINE\n " + "file_name : FILE_NAME LINE \n file_notice : FILE_NOTICE text_or_line\n " + "file_copyright_text : FILE_COPYRIGHT_TEXT line_or_no_assertion_or_none\n " + "file_license_comment : FILE_LICENSE_COMMENT text_or_line\n " + "file_comment : FILE_COMMENT text_or_line\n " + "file_license_concluded : FILE_LICENSE_CONCLUDED license_or_no_assertion_or_none\n " + "package_name : PKG_NAME LINE\n description : PKG_DESCRIPTION text_or_line\n " + "summary : PKG_SUMMARY text_or_line\n source_info : PKG_SOURCE_INFO text_or_line\n " + "homepage : PKG_HOMEPAGE line_or_no_assertion_or_none\n " + "download_location : PKG_DOWNLOAD_LOCATION line_or_no_assertion_or_none\n " + "originator : PKG_ORIGINATOR actor_or_no_assertion\n supplier : PKG_SUPPLIER actor_or_no_assertion\n " + "pkg_comment : PKG_COMMENT text_or_line\n " + "pkg_copyright_text : PKG_COPYRIGHT_TEXT line_or_no_assertion_or_none\n " + "pkg_license_declared : PKG_LICENSE_DECLARED license_or_no_assertion_or_none\n " + "pkg_file_name : PKG_FILE_NAME LINE\n " + "pkg_license_concluded : PKG_LICENSE_CONCLUDED license_or_no_assertion_or_none\n " + "package_version : PKG_VERSION LINE\n pkg_license_comment : PKG_LICENSE_COMMENT text_or_line\n " + "snippet_spdx_id : SNIPPET_SPDX_ID LINE\n snippet_name : SNIPPET_NAME LINE\n " + "snippet_comment : SNIPPET_COMMENT text_or_line\n " + "snippet_copyright_text : SNIPPET_COPYRIGHT_TEXT line_or_no_assertion_or_none\n " + "snippet_license_comment : SNIPPET_LICENSE_COMMENT text_or_line\n " + "file_spdx_id : SNIPPET_FILE_SPDXID LINE\n " + "snippet_license_concluded : SNIPPET_LICENSE_CONCLUDED license_or_no_assertion_or_none\n " + "annotation_spdx_id : ANNOTATION_SPDX_ID LINE\n " + "annotation_comment : ANNOTATION_COMMENT text_or_line" + ) + def p_generic_value(self, p): + if p[1] in ELEMENT_EXPECTED_START_TAG.values(): + self.initialize_new_current_element(TAG_DATA_MODEL_FIELD[p[1]][0]) + if self.check_that_current_element_matches_class_for_value(TAG_DATA_MODEL_FIELD[p[1]][0], p.lineno(1)): + set_value(p, self.current_element) + + @grammar_rule( + "unknown_tag : UNKNOWN_TAG text_or_line\n | UNKNOWN_TAG ISO8601_DATE\n | UNKNOWN_TAG PERSON_VALUE \n" + "| UNKNOWN_TAG" + ) + def p_unknown_tag(self, p): + self.logger.append(f"Unknown tag provided in line {p.lineno(1)}") + + @grammar_rule("text_or_line : TEXT\n line_or_no_assertion_or_none : TEXT") + def p_text(self, p): + p[0] = str_from_text(p[1]) + + @grammar_rule( + "text_or_line : LINE\n line_or_no_assertion : LINE\nline_or_no_assertion_or_none : LINE\n" + "text_or_line : NO_ASSERTION\n text_or_line : NONE" + ) + def p_line(self, p): + p[0] = p[1] + + @grammar_rule( + "license_or_no_assertion_or_none : NO_ASSERTION\n actor_or_no_assertion : NO_ASSERTION\n" + "line_or_no_assertion : NO_ASSERTION\n line_or_no_assertion_or_none : NO_ASSERTION" + ) + def p_no_assertion(self, p): + p[0] = SpdxNoAssertion() + + @grammar_rule("license_or_no_assertion_or_none : NONE\n line_or_no_assertion_or_none : NONE") + def p_none(self, p): + p[0] = SpdxNone() + + @grammar_rule("license_or_no_assertion_or_none : LINE") + def p_license(self, p): + try: + p[0] = get_spdx_licensing().parse(p[1]) + except ExpressionError as err: + error_message = f"Error while parsing license expression: {p[1]}" + if err.args: + error_message += f": {err.args[0]}" + self.current_element["logger"].append(error_message) + + @grammar_rule("actor_or_no_assertion : PERSON_VALUE\n | ORGANIZATION_VALUE") + def p_actor_values(self, p): + p[0] = ActorParser.parse_actor(p[1]) + + @grammar_rule("spdx_id : SPDX_ID LINE") + def p_spdx_id(self, p): + # As all SPDX Ids share the same tag, there is no knowing which spdx_id belongs to the document. + # We assume that to be the first spdx_id we encounter. As the specification does not explicitly require this, + # our approach might lead to unwanted behavior when the document's SPDX Id is defined later in the document. + if "spdx_id" in self.creation_info: + self.current_element["spdx_id"] = p[2] + else: + self.creation_info["spdx_id"] = p[2] + + # parsing methods for creation info / document level + + @grammar_rule( + "license_list_version : LICENSE_LIST_VERSION error\n document_comment : DOC_COMMENT error\n " + "document_namespace : DOC_NAMESPACE error\n data_license : DOC_LICENSE error\n " + "doc_name : DOC_NAME error\n ext_doc_ref : EXT_DOC_REF error\n spdx_version : DOC_VERSION error\n " + "creator_comment : CREATOR_COMMENT error\n creator : CREATOR error\n created : CREATED error" + ) + def p_creation_info_value_error(self, p): + self.creation_info["logger"].append( + f"Error while parsing {p[1]}: Token did not match specified grammar rule. Line: {p.lineno(1)}" + ) + + @grammar_rule( + "document_comment : DOC_COMMENT text_or_line\n document_namespace : DOC_NAMESPACE LINE\n " + "data_license : DOC_LICENSE LINE\n spdx_version : DOC_VERSION LINE\n " + "creator_comment : CREATOR_COMMENT text_or_line\n doc_name : DOC_NAME LINE" + ) + def p_generic_value_creation_info(self, p): + set_value(p, self.creation_info) + + @grammar_rule("license_list_version : LICENSE_LIST_VERSION LINE") + def p_license_list_version(self, p): + set_value(p, self.creation_info, method_to_apply=Version.from_string) + + @grammar_rule("ext_doc_ref : EXT_DOC_REF LINE") + def p_external_document_ref(self, p): + external_doc_ref_regex = re.compile(r"(.*)(\s*SHA1:\s*[a-f0-9]{40})") + external_doc_ref_match = external_doc_ref_regex.match(p[2]) + if not external_doc_ref_match: + self.creation_info["logger"].append( + f"Error while parsing ExternalDocumentRef: Couldn't match Checksum. Line: {p.lineno(1)}" + ) + return + try: + document_ref_id, document_uri = external_doc_ref_match.group(1).strip().split(" ") + except ValueError: + self.creation_info["logger"].append( + f"Error while parsing ExternalDocumentRef: Couldn't split the first part of the value into " + f"document_ref_id and document_uri. Line: {p.lineno(1)}" + ) + return + checksum = parse_checksum(external_doc_ref_match.group(2).strip()) + external_document_ref = ExternalDocumentRef(document_ref_id, document_uri, checksum) + self.creation_info.setdefault("external_document_refs", []).append(external_document_ref) + + @grammar_rule("creator : CREATOR PERSON_VALUE\n| CREATOR TOOL_VALUE\n| CREATOR ORGANIZATION_VALUE") + def p_creator(self, p): + self.creation_info.setdefault("creators", []).append(ActorParser.parse_actor(p[2])) + + @grammar_rule("created : CREATED ISO8601_DATE") + def p_created(self, p): + set_value(p, self.creation_info, method_to_apply=datetime_from_str) + + # parsing methods for extracted licensing info + + @grammar_rule("license_cross_ref : LICENSE_CROSS_REF LINE") + def p_extracted_cross_reference(self, p): + if self.check_that_current_element_matches_class_for_value(ExtractedLicensingInfo, p.lineno(1)): + self.current_element.setdefault("cross_references", []).append(p[2]) + + # parsing methods for file + + @grammar_rule("file_contributor : FILE_CONTRIBUTOR LINE") + def p_file_contributor(self, p): + if self.check_that_current_element_matches_class_for_value(File, p.lineno(1)): + self.current_element.setdefault("contributors", []).append(p[2]) + + @grammar_rule("file_attribution_text : FILE_ATTRIBUTION_TEXT text_or_line") + def p_file_attribution_text(self, p): + if self.check_that_current_element_matches_class_for_value(File, p.lineno(1)): + self.current_element.setdefault("attribution_texts", []).append(p[2]) + + @grammar_rule("file_license_info : FILE_LICENSE_INFO license_or_no_assertion_or_none") + def p_file_license_info(self, p): + if self.check_that_current_element_matches_class_for_value(File, p.lineno(1)): + self.current_element.setdefault("license_info_in_file", []).append(p[2]) + + @grammar_rule("file_type : FILE_TYPE LINE") + def p_file_type(self, p): + if not self.check_that_current_element_matches_class_for_value(File, p.lineno(1)): + return + try: + file_type = FileType[p[2].strip()] + except KeyError: + self.current_element["logger"].append(f"Invalid FileType: {p[2]}. Line {p.lineno(1)}") + return + self.current_element.setdefault("file_types", []).append(file_type) + + @grammar_rule("file_checksum : FILE_CHECKSUM CHECKSUM") + def p_file_checksum(self, p): + if not self.check_that_current_element_matches_class_for_value(File, p.lineno(1)): + return + checksum = parse_checksum(p[2]) + self.current_element.setdefault("checksums", []).append(checksum) + + # parsing methods for package + + @grammar_rule("pkg_attribution_text : PKG_ATTRIBUTION_TEXT text_or_line") + def p_pkg_attribution_text(self, p): + self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)) + self.current_element.setdefault("attribution_texts", []).append(p[2]) + + @grammar_rule( + "pkg_external_ref : PKG_EXTERNAL_REF LINE PKG_EXTERNAL_REF_COMMENT text_or_line\n | PKG_EXTERNAL_REF LINE" + ) + def p_pkg_external_refs(self, p): + if not self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): + return + try: + category, reference_type, locator = p[2].split(" ") + except ValueError: + self.current_element["logger"].append( + f"Couldn't split PackageExternalRef in category, reference_type and locator. Line: {p.lineno(1)}" + ) + return + comment = None + if len(p) == 5: + comment = p[4] + try: + category = ExternalPackageRefCategory[category.replace("-", "_")] + except KeyError: + self.current_element["logger"].append( + f"Invalid ExternalPackageRefCategory: {category}. Line: {p.lineno(1)}" + ) + return + try: + external_package_ref = construct_or_raise_parsing_error( + ExternalPackageRef, + {"category": category, "reference_type": reference_type, "locator": locator, "comment": comment}, + ) + except SPDXParsingError as err: + self.current_element["logger"].append(err.get_messages()) + return + self.current_element.setdefault("external_references", []).append(external_package_ref) + + @grammar_rule("pkg_license_info : PKG_LICENSE_INFO license_or_no_assertion_or_none") + def p_pkg_license_info_from_file(self, p): + if self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): + self.current_element.setdefault("license_info_from_files", []).append(p[2]) + + @grammar_rule("pkg_checksum : PKG_CHECKSUM CHECKSUM") + def p_pkg_checksum(self, p): + if not self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): + return + checksum = parse_checksum(p[2]) + self.current_element.setdefault("checksums", []).append(checksum) + + @grammar_rule("verification_code : PKG_VERIFICATION_CODE LINE") + def p_pkg_verification_code(self, p): + if not self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): + return + + if "verification_code" in self.current_element: + self.current_element["logger"].append(f"Multiple values for {p[1]} found. Line: {p.lineno(1)}") + return + verif_code_regex = re.compile(r"([0-9a-f]{40})\s*(\(excludes:\s*(.+)\))?", re.UNICODE) + verif_code_code_grp = 1 + verif_code_exc_files_grp = 3 + match = verif_code_regex.match(p[2]) + if not match: + self.current_element["logger"].append( + f"Error while parsing {p[1]}: Value did not match expected format. Line: {p.lineno(1)}" + ) + return + value = match.group(verif_code_code_grp) + excluded_files = None + if match.group(verif_code_exc_files_grp): + excluded_files = match.group(verif_code_exc_files_grp).split(",") + self.current_element["verification_code"] = PackageVerificationCode(value, excluded_files) + + @grammar_rule("files_analyzed : PKG_FILES_ANALYZED LINE") + def p_pkg_files_analyzed(self, p): + if not self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): + return + if "files_analyzed" in self.current_element: + self.current_element["logger"].append(f"Multiple values for {p[1]} found. Line: {p.lineno(1)}") + return + if p[2] == "true": + self.current_element["files_analyzed"] = True + elif p[2] == "false": + self.current_element["files_analyzed"] = False + else: + self.current_element["logger"].append( + f'The value of FilesAnalyzed must be either "true" or "false", but is: {p[2]}' + ) + + @grammar_rule("primary_package_purpose : PRIMARY_PACKAGE_PURPOSE LINE") + def p_primary_package_purpose(self, p): + if self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): + set_value(p, self.current_element, method_to_apply=lambda x: PackagePurpose[x.replace("-", "_")]) + + @grammar_rule( + "built_date : BUILT_DATE ISO8601_DATE\n release_date : RELEASE_DATE ISO8601_DATE\n " + "valid_until_date : VALID_UNTIL_DATE ISO8601_DATE" + ) + def p_package_dates(self, p): + if self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): + set_value(p, self.current_element, method_to_apply=datetime_from_str) + + # parsing methods for snippet + + @grammar_rule("snippet_attribution_text : SNIPPET_ATTRIBUTION_TEXT text_or_line") + def p_snippet_attribution_text(self, p): + if self.check_that_current_element_matches_class_for_value(Snippet, p.lineno(1)): + self.current_element.setdefault("attribution_texts", []).append(p[2]) + + @grammar_rule("snippet_license_info : SNIPPET_LICENSE_INFO license_or_no_assertion_or_none") + def p_snippet_license_info(self, p): + if self.check_that_current_element_matches_class_for_value(Snippet, p.lineno(1)): + self.current_element.setdefault("license_info_in_snippet", []).append(p[2]) + + @grammar_rule("snippet_byte_range : SNIPPET_BYTE_RANGE LINE\n snippet_line_range : SNIPPET_LINE_RANGE LINE") + def p_snippet_range(self, p): + if not self.check_that_current_element_matches_class_for_value(Snippet, p.lineno(1)): + return + + argument_name = TAG_DATA_MODEL_FIELD[p[1]][1] + if argument_name in self.current_element: + self.current_element["logger"].append(f"Multiple values for {p[1]} found. Line: {p.lineno(1)}") + return + range_re = re.compile(r"^(\d+):(\d+)$", re.UNICODE) + if not range_re.match(p[2].strip()): + self.current_element["logger"].append( + f"Value for {p[1]} doesn't match valid range pattern. " f"Line: {p.lineno(1)}" + ) + return + startpoint = int(p[2].split(":")[0]) + endpoint = int(p[2].split(":")[-1]) + self.current_element[argument_name] = startpoint, endpoint + + # parsing methods for annotation + + @grammar_rule("annotator : ANNOTATOR PERSON_VALUE\n| ANNOTATOR TOOL_VALUE\n| ANNOTATOR ORGANIZATION_VALUE") + def p_annotator(self, p): + self.initialize_new_current_element(Annotation) + set_value(p, self.current_element, method_to_apply=ActorParser.parse_actor) + + @grammar_rule("annotation_date : ANNOTATION_DATE ISO8601_DATE") + def p_annotation_date(self, p): + if self.check_that_current_element_matches_class_for_value(Annotation, p.lineno(1)): + set_value(p, self.current_element, method_to_apply=datetime_from_str) + + @grammar_rule("annotation_type : ANNOTATION_TYPE LINE") + def p_annotation_type(self, p): + if self.check_that_current_element_matches_class_for_value(Annotation, p.lineno(1)): + set_value(p, self.current_element, method_to_apply=lambda x: AnnotationType[x]) + + # parsing methods for relationship + + @grammar_rule("relationship : RELATIONSHIP LINE RELATIONSHIP_COMMENT text_or_line\n " "| RELATIONSHIP LINE") + def p_relationship(self, p): + self.initialize_new_current_element(Relationship) + try: + spdx_element_id, relationship_type, related_spdx_element_id = p[2].split(" ") + except ValueError: + self.current_element["logger"].append( + f"Relationship couldn't be split in spdx_element_id, relationship_type and " + f"related_spdx_element. Line: {p.lineno(1)}" + ) + return + try: + self.current_element["relationship_type"] = RelationshipType[relationship_type] + except KeyError: + self.current_element["logger"].append(f"Invalid RelationshipType {relationship_type}. Line: {p.lineno(1)}") + if related_spdx_element_id == "NONE": + related_spdx_element_id = SpdxNone() + if related_spdx_element_id == "NOASSERTION": + related_spdx_element_id = SpdxNoAssertion() + self.current_element["related_spdx_element_id"] = related_spdx_element_id + self.current_element["spdx_element_id"] = spdx_element_id + if len(p) == 5: + self.current_element["comment"] = p[4] + + def p_error(self, p): + pass + + def parse(self, text): + # entry point for the tag-value parser + self.yacc.parse(text, lexer=self.lex) + # this constructs the last remaining element; all other elements are constructed at the start of + # their subsequent element + self.construct_current_element() + + # To be able to parse creation info values if they appear in between other elements, e.g. packages, we use + # two different dictionaries to collect the creation info and all other elements. Therefore, we have a separate + # logger for the creation info whose messages we need to add to the main logger to than raise all collected + # messages at once. + creation_info_logger = self.creation_info.pop("logger") + if creation_info_logger.has_messages(): + self.logger.extend([f"Error while parsing CreationInfo: {creation_info_logger.get_messages()}"]) + + raise_parsing_error_if_logger_has_messages(self.logger) + creation_info = construct_or_raise_parsing_error(CreationInfo, self.creation_info) + self.elements_built["creation_info"] = creation_info + document = construct_or_raise_parsing_error(Document, self.elements_built) + return document + + def initialize_new_current_element(self, clazz: Any): + self.construct_current_element() + self.current_element["class"] = clazz + + def check_that_current_element_matches_class_for_value(self, expected_class, line_number) -> bool: + if "class" not in self.current_element or expected_class != self.current_element["class"]: + self.logger.append( + f"Element {expected_class.__name__} is not the current element in scope, probably the expected tag to " + f"start the element ({ELEMENT_EXPECTED_START_TAG[expected_class.__name__]}) is missing. " + f"Line: {line_number}" + ) + return False + return True + + def construct_current_element(self): + if "class" not in self.current_element: + # This happens when the first element is initialized via initialize_new_current_element() or if the first + # element is missing its expected starting tag. In both cases we are unable to construct an element. + return + + clazz = self.current_element.pop("class") + try: + raise_parsing_error_if_logger_has_messages(self.current_element.pop("logger"), clazz.__name__) + self.elements_built.setdefault(CLASS_MAPPING[clazz.__name__], []).append( + construct_or_raise_parsing_error(clazz, self.current_element) + ) + if clazz == File: + self.check_for_preceding_package_and_build_contains_relationship() + except SPDXParsingError as err: + self.logger.extend(err.get_messages()) + self.current_element = {"logger": Logger()} + + def check_for_preceding_package_and_build_contains_relationship(self): + file_spdx_id = self.current_element["spdx_id"] + if "packages" not in self.elements_built: + return + # We assume that all files that are not contained in a package precede any package information. Any file + # information that follows any package information is assigned to the last parsed package by creating a + # corresponding contains relationship. + # (see https://spdx.github.io/spdx-spec/v2.3/composition-of-an-SPDX-document/#5.2.2) + if not self.elements_built["packages"]: + self.logger.append( + f"Error while building contains relationship for file {file_spdx_id}, " + f"preceding package was not parsed successfully." + ) + return + package_spdx_id = self.elements_built["packages"][-1].spdx_id + relationship = Relationship(package_spdx_id, RelationshipType.CONTAINS, file_spdx_id) + if relationship not in self.elements_built.setdefault("relationships", []): + self.elements_built["relationships"].append(relationship) diff --git a/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py b/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py new file mode 100644 index 000000000..c281279e9 --- /dev/null +++ b/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.parser.tagvalue.parser import Parser + + +def parse_from_file(file_name: str, encoding: str = "utf-8") -> Document: + parser = Parser() + with open(file_name, encoding=encoding) as file: + data = file.read() + document: Document = parser.parse(data) + return document diff --git a/src/spdx_tools/spdx/parser/xml/__init__.py b/src/spdx_tools/spdx/parser/xml/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/parser/xml/xml_parser.py b/src/spdx_tools/spdx/parser/xml/xml_parser.py new file mode 100644 index 000000000..ba7ff3491 --- /dev/null +++ b/src/spdx_tools/spdx/parser/xml/xml_parser.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import xmltodict +from beartype.typing import Any, Dict + +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser + +LIST_LIKE_FIELDS = [ + "creators", + "externalDocumentRefs", + "hasExtractedLicensingInfos", + "seeAlsos", + "annotations", + "relationships", + "snippets", + "reviewers", + "fileTypes", + "licenseInfoFromFiles", + "licenseInfoInFiles", + "artifactOf", + "fileContributors", + "fileDependencies", + "files", + "documentDescribes", + "packages", + "checksums", + "hasFiles", + "externalRefs", + "ranges", + "licenseInfoInSnippets", + "packageVerificationCodeExcludedFiles", + "attributionTexts", +] + + +def parse_from_file(file_name: str, encoding: str = "utf-8") -> Document: + with open(file_name, encoding=encoding) as file: + parsed_xml: Dict = xmltodict.parse(file.read(), encoding="utf-8") + + input_doc_as_dict: Dict = _fix_list_like_fields(parsed_xml).get("Document") + + if not input_doc_as_dict: + raise SPDXParsingError(['Did not find the XML top level tag "Document".']) + + return JsonLikeDictParser().parse(input_doc_as_dict) + + +def _fix_list_like_fields(data: Any) -> Any: + """ + XML files do not contain lists. Thus, single fields that should be a list in SPDX have to be manually cast. + This method takes a parsed dictionary and converts all values with key from LIST_LIKE_FIELDS to lists. + """ + if isinstance(data, dict): + new_data = {} + for key, value in data.items(): + if key in LIST_LIKE_FIELDS and not isinstance(value, list): + new_data[key] = [_fix_list_like_fields(value)] if value else [] + else: + new_data[key] = _fix_list_like_fields(value) + return new_data + + if isinstance(data, list): + new_data = [] + for element in data: + new_data.append(_fix_list_like_fields(element)) + return new_data + + return data diff --git a/src/spdx_tools/spdx/parser/yaml/__init__.py b/src/spdx_tools/spdx/parser/yaml/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/parser/yaml/yaml_parser.py b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py new file mode 100644 index 000000000..98fbd7ce8 --- /dev/null +++ b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import yaml +from beartype.typing import Dict + +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser + + +def parse_from_file(file_name: str, encoding: str = "utf-8") -> Document: + with open(file_name, encoding=encoding) as file: + input_doc_as_dict: Dict = yaml.safe_load(file) + + return JsonLikeDictParser().parse(input_doc_as_dict) diff --git a/src/spdx_tools/spdx/py.typed b/src/spdx_tools/spdx/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/rdfschema/__init__.py b/src/spdx_tools/spdx/rdfschema/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/rdfschema/namespace.py b/src/spdx_tools/spdx/rdfschema/namespace.py new file mode 100644 index 000000000..5f330fb82 --- /dev/null +++ b/src/spdx_tools/spdx/rdfschema/namespace.py @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import Namespace + +SPDX_NAMESPACE = Namespace("http://spdx.org/rdf/terms#") +POINTER_NAMESPACE = Namespace("http://www.w3.org/2009/pointers#") +REFERENCE_NAMESPACE = Namespace("http://spdx.org/rdf/references/") +LICENSE_NAMESPACE = Namespace("http://spdx.org/licenses/") diff --git a/src/spdx_tools/spdx/spdx_element_utils.py b/src/spdx_tools/spdx/spdx_element_utils.py new file mode 100644 index 000000000..0d6bd8946 --- /dev/null +++ b/src/spdx_tools/spdx/spdx_element_utils.py @@ -0,0 +1,91 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import hashlib + +from beartype.typing import List, Optional, Type, Union + +from spdx_tools.spdx.model import ( + ChecksumAlgorithm, + Document, + ExternalDocumentRef, + File, + Package, + PackageVerificationCode, + Snippet, +) + + +def get_element_type_from_spdx_id( + spdx_id: str, document: Document +) -> Optional[Union[Type[Package], Type[File], Type[Snippet]]]: + if spdx_id in [package.spdx_id for package in document.packages]: + return Package + if spdx_id in [file.spdx_id for file in document.files]: + return File + if spdx_id in [snippet.spdx_id for snippet in document.snippets]: + return Snippet + return None + + +def get_full_element_spdx_id( + element: Union[Package, File, Snippet], + document_namespace: str, + external_document_refs: List[ExternalDocumentRef], +) -> str: + """ + Returns the spdx_id of the element prefixed with the correct document namespace and, + if the element is from an external document, sets the correct entry in the imports property. + """ + if ":" not in element.spdx_id: + return f"{document_namespace}#{element.spdx_id}" + + external_id, local_id = element.spdx_id.split(":") + external_uri = None + for entry in external_document_refs: + if entry.document_ref_id == external_id: + external_uri = entry.document_uri + break + + if not external_uri: + raise ValueError(f"external id {external_id} not found in external document references") + + return external_uri + "#" + local_id + + +def calculate_package_verification_code(files: List[File]) -> PackageVerificationCode: + list_of_file_hashes = [] + for file in files: + file_checksum_value = None + for checksum in file.checksums: + if checksum.algorithm == ChecksumAlgorithm.SHA1: + file_checksum_value = checksum.value + if not file_checksum_value: + try: + file_checksum_value = calculate_file_checksum(file.name, ChecksumAlgorithm.SHA1) + except FileNotFoundError: + raise FileNotFoundError( + f"Cannot calculate package verification code because the file '{file.name}' " + f"provides no SHA1 checksum and can't be found at the specified location." + ) + list_of_file_hashes.append(file_checksum_value) + + list_of_file_hashes.sort() + hasher = hashlib.new("sha1") + hasher.update("".join(list_of_file_hashes).encode("utf-8")) + value = hasher.hexdigest() + return PackageVerificationCode(value) + + +def calculate_file_checksum(file_name: str, hash_algorithm=ChecksumAlgorithm.SHA1) -> str: + BUFFER_SIZE = 65536 + + file_hash = hashlib.new(hash_algorithm.name.lower()) + with open(file_name, "rb") as file_handle: + while True: + data = file_handle.read(BUFFER_SIZE) + if not data: + break + file_hash.update(data) + + return file_hash.hexdigest() diff --git a/src/spdx_tools/spdx/validation/__init__.py b/src/spdx_tools/spdx/validation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/validation/actor_validator.py b/src/spdx_tools/spdx/validation/actor_validator.py new file mode 100644 index 000000000..3ae5f8656 --- /dev/null +++ b/src/spdx_tools/spdx/validation/actor_validator.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import List + +from spdx_tools.spdx.model import Actor, ActorType +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_actors(actors: List[Actor], parent_id: str) -> List[ValidationMessage]: + validation_messages = [] + for actor in actors: + validation_messages.extend(validate_actor(actor, parent_id)) + + return validation_messages + + +def validate_actor(actor: Actor, parent_id: str) -> List[ValidationMessage]: + validation_messages = [] + + if actor.actor_type == ActorType.TOOL and actor.email is not None: + validation_messages.append( + ValidationMessage( + f"email must be None if actor_type is TOOL, but is: {actor.email}", + ValidationContext(parent_id=parent_id, element_type=SpdxElementType.ACTOR, full_element=actor), + ) + ) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/annotation_validator.py b/src/spdx_tools/spdx/validation/annotation_validator.py new file mode 100644 index 000000000..3fec188c7 --- /dev/null +++ b/src/spdx_tools/spdx/validation/annotation_validator.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import List + +from spdx_tools.spdx.model import Annotation, Document +from spdx_tools.spdx.validation.actor_validator import validate_actor +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_annotations(annotations: List[Annotation], document: Document) -> List[ValidationMessage]: + validation_messages = [] + for annotation in annotations: + validation_messages.extend(validate_annotation(annotation, document)) + + return validation_messages + + +def validate_annotation(annotation: Annotation, document: Document) -> List[ValidationMessage]: + validation_messages = [] + context = ValidationContext(element_type=SpdxElementType.ANNOTATION, full_element=annotation) + + validation_messages.extend(validate_actor(annotation.annotator, "annotation")) + + messages: List[str] = validate_spdx_id(annotation.spdx_id, document, check_document=True) + for message in messages: + validation_messages.append(ValidationMessage(message, context)) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/checksum_validator.py b/src/spdx_tools/spdx/validation/checksum_validator.py new file mode 100644 index 000000000..2a9d055c8 --- /dev/null +++ b/src/spdx_tools/spdx/validation/checksum_validator.py @@ -0,0 +1,74 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import re + +from beartype.typing import Dict, List + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + +# in hexadecimal digits +algorithm_length: Dict = { + ChecksumAlgorithm.SHA1: "40", + ChecksumAlgorithm.SHA224: "56", + ChecksumAlgorithm.SHA256: "64", + ChecksumAlgorithm.SHA384: "96", + ChecksumAlgorithm.SHA512: "128", + ChecksumAlgorithm.SHA3_256: "64", + ChecksumAlgorithm.SHA3_384: "96", + ChecksumAlgorithm.SHA3_512: "128", + ChecksumAlgorithm.BLAKE2B_256: "64", + ChecksumAlgorithm.BLAKE2B_384: "96", + ChecksumAlgorithm.BLAKE2B_512: "128", + ChecksumAlgorithm.BLAKE3: "256,", # at least 256 bits + ChecksumAlgorithm.MD2: "32", + ChecksumAlgorithm.MD4: "32", + ChecksumAlgorithm.MD5: "32", + ChecksumAlgorithm.MD6: "0,512", # between 0 and 512 bits + ChecksumAlgorithm.ADLER32: "8", +} + + +def validate_checksums(checksums: List[Checksum], parent_id: str, spdx_version: str) -> List[ValidationMessage]: + validation_messages = [] + for checksum in checksums: + validation_messages.extend(validate_checksum(checksum, parent_id, spdx_version)) + + return validation_messages + + +def validate_checksum(checksum: Checksum, parent_id: str, spdx_version: str) -> List[ValidationMessage]: + validation_messages = [] + algorithm = checksum.algorithm + context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.CHECKSUM, full_element=checksum) + + if spdx_version == "SPDX-2.2" and algorithm in [ + ChecksumAlgorithm.SHA3_512, + ChecksumAlgorithm.SHA3_384, + ChecksumAlgorithm.SHA3_256, + ChecksumAlgorithm.BLAKE3, + ChecksumAlgorithm.BLAKE2B_512, + ChecksumAlgorithm.BLAKE2B_384, + ChecksumAlgorithm.BLAKE2B_256, + ChecksumAlgorithm.ADLER32, + ]: + return [ValidationMessage(f"{checksum.algorithm.name} is not supported in SPDX-2.2", context)] + + if not re.match("^[0-9a-f]{" + algorithm_length[algorithm] + "}$", checksum.value): + if algorithm == ChecksumAlgorithm.BLAKE3: + length = "at least 256" + elif algorithm == ChecksumAlgorithm.MD6: + length = "between 0 and 512" + else: + length = algorithm_length[algorithm] + validation_messages.append( + ValidationMessage( + f"value of {algorithm} must consist of {length} lowercase hexadecimal digits, but is: " + f"{checksum.value} (length: {len(checksum.value)} digits)", + context, + ) + ) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/creation_info_validator.py b/src/spdx_tools/spdx/validation/creation_info_validator.py new file mode 100644 index 000000000..79490c77c --- /dev/null +++ b/src/spdx_tools/spdx/validation/creation_info_validator.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import List + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import CreationInfo +from spdx_tools.spdx.validation.actor_validator import validate_actors +from spdx_tools.spdx.validation.external_document_ref_validator import validate_external_document_refs +from spdx_tools.spdx.validation.uri_validators import validate_uri +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_creation_info(creation_info: CreationInfo, spdx_version: str) -> List[ValidationMessage]: + validation_messages: List[ValidationMessage] = [] + + context = ValidationContext(spdx_id=creation_info.spdx_id, element_type=SpdxElementType.DOCUMENT) + + if creation_info.spdx_id != DOCUMENT_SPDX_ID: + validation_messages.append( + ValidationMessage(f"spdx_id must be {DOCUMENT_SPDX_ID}, but is: {creation_info.spdx_id}", context) + ) + + if creation_info.data_license != "CC0-1.0": + validation_messages.append( + ValidationMessage(f'data_license must be "CC0-1.0", but is: {creation_info.data_license}', context) + ) + + for message in validate_uri(creation_info.document_namespace): + validation_messages.append(ValidationMessage("document_namespace " + message, context)) + + validation_messages.extend(validate_actors(creation_info.creators, creation_info.spdx_id)) + validation_messages.extend( + validate_external_document_refs(creation_info.external_document_refs, creation_info.spdx_id, spdx_version) + ) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/document_validator.py b/src/spdx_tools/spdx/validation/document_validator.py new file mode 100644 index 000000000..b6fba74b8 --- /dev/null +++ b/src/spdx_tools/spdx/validation/document_validator.py @@ -0,0 +1,97 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + +from spdx_tools.spdx.model import Document, RelationshipType +from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target +from spdx_tools.spdx.validation.annotation_validator import validate_annotations +from spdx_tools.spdx.validation.creation_info_validator import validate_creation_info +from spdx_tools.spdx.validation.extracted_licensing_info_validator import validate_extracted_licensing_infos +from spdx_tools.spdx.validation.file_validator import validate_files +from spdx_tools.spdx.validation.package_validator import validate_packages +from spdx_tools.spdx.validation.relationship_validator import validate_relationships +from spdx_tools.spdx.validation.snippet_validator import validate_snippets +from spdx_tools.spdx.validation.spdx_id_validators import get_list_of_all_spdx_ids +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_full_spdx_document(document: Document, spdx_version: str = None) -> List[ValidationMessage]: + validation_messages: List[ValidationMessage] = [] + + # SPDX version validation has to happen here because subsequent validators rely on it + document_version: str = document.creation_info.spdx_version + context = ValidationContext(spdx_id=document.creation_info.spdx_id, element_type=SpdxElementType.DOCUMENT) + if not spdx_version: + spdx_version = document_version + + if document_version not in ["SPDX-2.2", "SPDX-2.3"]: + validation_messages.append( + ValidationMessage( + f'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: ' + f"{document_version}", + context, + ) + ) + elif spdx_version != document_version: + validation_messages.append( + ValidationMessage( + f"provided SPDX version {spdx_version} does not match " + f"the document's SPDX version {document_version}", + context, + ) + ) + + if validation_messages: + validation_messages.append( + ValidationMessage( + "There are issues concerning the SPDX version of the document. " + "As subsequent validation relies on the correct version, " + "the validation process has been cancelled.", + context, + ) + ) + return validation_messages + + validation_messages.extend(validate_creation_info(document.creation_info, spdx_version)) + validation_messages.extend(validate_packages(document.packages, spdx_version, document)) + validation_messages.extend(validate_files(document.files, spdx_version, document)) + validation_messages.extend(validate_snippets(document.snippets, spdx_version, document)) + validation_messages.extend(validate_annotations(document.annotations, document)) + validation_messages.extend(validate_relationships(document.relationships, spdx_version, document)) + validation_messages.extend(validate_extracted_licensing_infos(document.extracted_licensing_info)) + + document_id = document.creation_info.spdx_id + document_describes_relationships = filter_by_type_and_origin( + document.relationships, RelationshipType.DESCRIBES, document_id + ) + described_by_document_relationships = filter_by_type_and_target( + document.relationships, RelationshipType.DESCRIBED_BY, document_id + ) + + only_a_single_package = len(document.packages) == 1 and not document.files and not document.snippets + if not only_a_single_package and not document_describes_relationships + described_by_document_relationships: + validation_messages.append( + ValidationMessage( + f'there must be at least one relationship "{document_id} DESCRIBES ..." or "... DESCRIBED_BY ' + f'{document_id}" when there is not only a single package present', + ValidationContext(spdx_id=document_id, element_type=SpdxElementType.DOCUMENT), + ) + ) + + all_spdx_ids: List[str] = get_list_of_all_spdx_ids(document) + auxiliary_set = set() + duplicated_spdx_ids = set( + spdx_id for spdx_id in all_spdx_ids if spdx_id in auxiliary_set or auxiliary_set.add(spdx_id) + ) + + if duplicated_spdx_ids: + validation_messages.append( + ValidationMessage( + f"every spdx_id must be unique within the document, but found the following duplicates: " + f"{sorted(duplicated_spdx_ids)}", + context, + ) + ) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/external_document_ref_validator.py b/src/spdx_tools/spdx/validation/external_document_ref_validator.py new file mode 100644 index 000000000..52f50a665 --- /dev/null +++ b/src/spdx_tools/spdx/validation/external_document_ref_validator.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import List + +from spdx_tools.spdx.model import ExternalDocumentRef +from spdx_tools.spdx.validation.checksum_validator import validate_checksum +from spdx_tools.spdx.validation.spdx_id_validators import is_valid_external_doc_ref_id +from spdx_tools.spdx.validation.uri_validators import validate_uri +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_external_document_refs( + external_document_refs: List[ExternalDocumentRef], parent_id: str, spdx_version: str +) -> List[ValidationMessage]: + validation_messages = [] + for external_document_ref in external_document_refs: + validation_messages.extend(validate_external_document_ref(external_document_ref, parent_id, spdx_version)) + + return validation_messages + + +def validate_external_document_ref( + external_document_ref: ExternalDocumentRef, parent_id: str, spdx_version: str +) -> List[ValidationMessage]: + validation_messages = [] + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_DOCUMENT_REF, full_element=external_document_ref + ) + + if not is_valid_external_doc_ref_id(external_document_ref.document_ref_id): + validation_messages.append( + ValidationMessage( + f'document_ref_id must only contain letters, numbers, ".", "-" and "+" and must begin with ' + f'"DocumentRef-", but is: {external_document_ref.document_ref_id}', + context, + ) + ) + + for message in validate_uri(external_document_ref.document_uri): + validation_messages.append(ValidationMessage("document_uri " + message, context)) + + validation_messages.extend(validate_checksum(external_document_ref.checksum, parent_id, spdx_version)) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/external_package_ref_validator.py b/src/spdx_tools/spdx/validation/external_package_ref_validator.py new file mode 100644 index 000000000..7dd316354 --- /dev/null +++ b/src/spdx_tools/spdx/validation/external_package_ref_validator.py @@ -0,0 +1,120 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import re + +import uritools +from beartype.typing import Dict, List + +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.model.package import CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES +from spdx_tools.spdx.validation.uri_validators import validate_url +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + +CPE22TYPE_REGEX = r"^c[pP][eE]:/[AHOaho]?(:[A-Za-z0-9._\-~%]*){0,6}$" +CPE23TYPE_REGEX = ( + r'^cpe:2\.3:[aho\*\-](:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^' + r"`\{\|}~]))+(\?*|\*?))|[\*\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\*\-]))(:(((\?*" + r'|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){4}$' +) +MAVEN_CENTRAL_REGEX = r"^[^:]+:[^:]+(:[^:]+)?$" +NPM_REGEX = r"^[^@]+@[^@]+$" +NUGET_REGEX = r"^[^/]+/[^/]+$" +BOWER_REGEX = r"^[^#]+#[^#]+$" +PURL_REGEX = r"^pkg:.+(\/.+)?\/.+(@.+)?(\?.+)?(#.+)?$" +SWH_REGEX = r"^swh:1:(snp|rel|rev|dir|cnt):[0-9a-fA-F]{40}$" +GITOID_REGEX = r"^gitoid:(blob|tree|commit|tag):(sha1:[0-9a-fA-F]{40}|sha256:[0-9a-fA-F]{64})$" + +TYPE_TO_REGEX: Dict[str, str] = { + "cpe22Type": CPE22TYPE_REGEX, + "cpe23Type": CPE23TYPE_REGEX, + "maven-central": MAVEN_CENTRAL_REGEX, + "npm": NPM_REGEX, + "nuget": NUGET_REGEX, + "bower": BOWER_REGEX, + "purl": PURL_REGEX, + "swh": SWH_REGEX, + "gitoid": GITOID_REGEX, +} + + +def validate_external_package_refs( + external_package_refs: List[ExternalPackageRef], parent_id: str, spdx_version: str +) -> List[ValidationMessage]: + validation_messages = [] + for external_package_ref in external_package_refs: + validation_messages.extend(validate_external_package_ref(external_package_ref, parent_id, spdx_version)) + + return validation_messages + + +def validate_external_package_ref( + external_package_ref: ExternalPackageRef, parent_id: str, spdx_version: str +) -> List[ValidationMessage]: + validation_messages = [] + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, full_element=external_package_ref + ) + + category = external_package_ref.category + locator = external_package_ref.locator + reference_type = external_package_ref.reference_type + + if category == ExternalPackageRefCategory.OTHER: + if " " in locator: + validation_messages.append( + ValidationMessage( + f"externalPackageRef locator in category OTHER must contain no spaces, but is: {locator}", context + ) + ) + + elif spdx_version == "SPDX-2.2" and reference_type in ["advisory", "fix", "url", "swid"]: + return [ValidationMessage(f'externalPackageRef type "{reference_type}" is not supported in SPDX-2.2', context)] + + elif reference_type not in CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[category]: + validation_messages.append( + ValidationMessage( + f"externalPackageRef type in category {category.name} must be one of " + f"{CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[category]}, but is: {reference_type}", + context, + ) + ) + + elif reference_type in ["advisory", "fix", "url"]: + if validate_url(locator): + validation_messages.append( + ValidationMessage( + f'externalPackageRef locator of type "{reference_type}" must be a valid URL, but is: {locator}', + context, + ) + ) + + elif reference_type == "swid": + if not uritools.isuri(locator) or not locator.startswith("swid"): + validation_messages.append( + ValidationMessage( + f'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, ' + f"but is: {locator}", + context, + ) + ) + + else: + validation_messages.extend(validate_against_regex(locator, reference_type, context)) + + return validation_messages + + +def validate_against_regex( + string_to_validate: str, reference_type: str, context: ValidationContext +) -> List[ValidationMessage]: + regex = TYPE_TO_REGEX[reference_type] + if not re.match(regex, string_to_validate): + return [ + ValidationMessage( + f'externalPackageRef locator of type "{reference_type}" must conform with the regex {regex}, ' + f"but is: {string_to_validate}", + context, + ) + ] + return [] diff --git a/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py b/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py new file mode 100644 index 000000000..6cca07576 --- /dev/null +++ b/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import re + +from beartype.typing import List, Optional + +from spdx_tools.spdx.model import ExtractedLicensingInfo +from spdx_tools.spdx.validation.uri_validators import validate_url +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_extracted_licensing_infos( + extracted_licensing_infos: Optional[List[ExtractedLicensingInfo]], +) -> List[ValidationMessage]: + validation_messages = [] + for extracted_licensing_info in extracted_licensing_infos: + validation_messages.extend(validate_extracted_licensing_info(extracted_licensing_info)) + + return validation_messages + + +def validate_extracted_licensing_info(extracted_licensing_infos: ExtractedLicensingInfo) -> List[ValidationMessage]: + validation_messages: List[ValidationMessage] = [] + context = ValidationContext( + element_type=SpdxElementType.EXTRACTED_LICENSING_INFO, full_element=extracted_licensing_infos + ) + + license_id: str = extracted_licensing_infos.license_id + if license_id and not re.match(r"^LicenseRef-[\da-zA-Z.-]+$", license_id): + validation_messages.append( + ValidationMessage( + f'license_id must only contain letters, numbers, "." and "-" and must begin with "LicenseRef-", ' + f"but is: {license_id}", + context, + ) + ) + + if license_id and not extracted_licensing_infos.extracted_text: + validation_messages.append( + ValidationMessage("extracted_text must be provided if there is a license_id assigned", context) + ) + + for cross_reference in extracted_licensing_infos.cross_references: + for message in validate_url(cross_reference): + validation_messages.append(ValidationMessage("cross_reference " + message, context)) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/file_validator.py b/src/spdx_tools/spdx/validation/file_validator.py new file mode 100644 index 000000000..a14efd4c4 --- /dev/null +++ b/src/spdx_tools/spdx/validation/file_validator.py @@ -0,0 +1,85 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import List, Optional + +from spdx_tools.spdx.model import ChecksumAlgorithm, Document, File +from spdx_tools.spdx.validation.checksum_validator import validate_checksums +from spdx_tools.spdx.validation.license_expression_validator import ( + validate_license_expression, + validate_license_expressions, +) +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_files( + files: List[File], spdx_version: str, document: Optional[Document] = None +) -> List[ValidationMessage]: + validation_messages = [] + if document: + for file in files: + validation_messages.extend(validate_file_within_document(file, spdx_version, document)) + else: + for file in files: + validation_messages.extend(validate_file(file, spdx_version)) + + return validation_messages + + +def validate_file_within_document(file: File, spdx_version: str, document: Document) -> List[ValidationMessage]: + validation_messages: List[ValidationMessage] = [] + context = ValidationContext( + spdx_id=file.spdx_id, + parent_id=document.creation_info.spdx_id, + element_type=SpdxElementType.FILE, + full_element=file, + ) + + for message in validate_spdx_id(file.spdx_id, document): + validation_messages.append(ValidationMessage(message, context)) + + validation_messages.extend(validate_license_expression(file.license_concluded, document, file.spdx_id)) + + validation_messages.extend(validate_license_expressions(file.license_info_in_file, document, file.spdx_id)) + + validation_messages.extend(validate_file(file, spdx_version, context)) + + return validation_messages + + +def validate_file( + file: File, spdx_version: str, context: Optional[ValidationContext] = None +) -> List[ValidationMessage]: + validation_messages = [] + if not context: + context = ValidationContext(spdx_id=file.spdx_id, element_type=SpdxElementType.FILE, full_element=file) + + if file.name.startswith("/"): + validation_messages.append( + ValidationMessage( + f'file name must not be an absolute path starting with "/", but is: {file.name}', context + ) + ) + + if ChecksumAlgorithm.SHA1 not in [checksum.algorithm for checksum in file.checksums]: + validation_messages.append( + ValidationMessage( + f"checksums must contain a SHA1 algorithm checksum, but only contains: " + f"{[checksum.algorithm for checksum in file.checksums]}", + context, + ) + ) + + validation_messages.extend(validate_checksums(file.checksums, file.spdx_id, spdx_version)) + + if spdx_version == "SPDX-2.2": + if file.license_concluded is None: + validation_messages.append(ValidationMessage("license_concluded is mandatory in SPDX-2.2", context)) + if not file.license_info_in_file: + validation_messages.append(ValidationMessage("license_info_in_file is mandatory in SPDX-2.2", context)) + if file.copyright_text is None: + validation_messages.append(ValidationMessage("copyright_text is mandatory in SPDX-2.2", context)) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/license_expression_validator.py b/src/spdx_tools/spdx/validation/license_expression_validator.py new file mode 100644 index 000000000..e463aa9b6 --- /dev/null +++ b/src/spdx_tools/spdx/validation/license_expression_validator.py @@ -0,0 +1,96 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import List, Optional, Union +from license_expression import ExpressionError, ExpressionParseError, LicenseExpression + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.validation.spdx_id_validators import is_external_doc_ref_present_in_document +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_license_expressions( + license_expressions: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]], document: Document, parent_id: str +) -> List[ValidationMessage]: + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expressions + ) + validation_messages = [] + + for license_expression in license_expressions: + validation_messages.extend(validate_license_expression(license_expression, document, parent_id, context)) + + return validation_messages + + +def validate_license_expression( + license_expression: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]], + document: Document, + parent_id: str, + context: ValidationContext = None, +) -> List[ValidationMessage]: + if license_expression in [SpdxNoAssertion(), SpdxNone(), None]: + return [] + + if not context: + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression + ) + + validation_messages = [] + license_ref_ids: List[str] = [license_ref.license_id for license_ref in document.extracted_licensing_info] + + for non_spdx_token in spdx_licensing.validate(license_expression).invalid_symbols: + if ":" in non_spdx_token: + split_token: List[str] = non_spdx_token.split(":") + if len(split_token) != 2: + validation_messages.append( + ValidationMessage( + f"Too many colons in license reference: {non_spdx_token}. " + "A license reference must only contain a single colon to " + "separate an external document reference from the license reference.", + context, + ) + ) + else: + if not split_token[1].startswith("LicenseRef-"): + validation_messages.append( + ValidationMessage( + f'A license reference must start with "LicenseRef-", but is: {split_token[1]} ' + f"in external license reference {non_spdx_token}.", + context, + ) + ) + if not is_external_doc_ref_present_in_document(split_token[0], document): + validation_messages.append( + ValidationMessage( + f'Did not find the external document reference "{split_token[0]}" in the SPDX document. ' + f"From the external license reference {non_spdx_token}.", + context, + ) + ) + + elif non_spdx_token not in license_ref_ids: + validation_messages.append( + ValidationMessage( + f"Unrecognized license reference: {non_spdx_token}. license_expression must only use IDs from the " + f"license list or extracted licensing info, but is: {license_expression}", + context, + ) + ) + + try: + spdx_licensing.parse(str(license_expression), validate=True, strict=True) + except ExpressionParseError as err: + # This error is raised when an exception symbol is used as a license symbol and vice versa. + # So far, it only catches the first such error in the provided string. + validation_messages.append(ValidationMessage(f"{err}. for license_expression: {license_expression}", context)) + except ExpressionError: + # This error is raised for invalid symbols within the license_expression, but it provides only a string of + # these. On the other hand, spdx_licensing.validate() gives an actual list of invalid symbols, so this is + # handled above. + pass + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/package_validator.py b/src/spdx_tools/spdx/validation/package_validator.py new file mode 100644 index 000000000..25cd6147f --- /dev/null +++ b/src/spdx_tools/spdx/validation/package_validator.py @@ -0,0 +1,160 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import List, Optional + +from spdx_tools.spdx.model import Document, File, Package, Relationship, RelationshipType +from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target +from spdx_tools.spdx.spdx_element_utils import get_element_type_from_spdx_id +from spdx_tools.spdx.validation.checksum_validator import validate_checksums +from spdx_tools.spdx.validation.external_package_ref_validator import validate_external_package_refs +from spdx_tools.spdx.validation.license_expression_validator import ( + validate_license_expression, + validate_license_expressions, +) +from spdx_tools.spdx.validation.package_verification_code_validator import validate_verification_code +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.uri_validators import validate_download_location, validate_url +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_packages( + packages: List[Package], spdx_version: str, document: Optional[Document] = None +) -> List[ValidationMessage]: + validation_messages: List[ValidationMessage] = [] + if document: + for package in packages: + validation_messages.extend(validate_package_within_document(package, spdx_version, document)) + else: + for package in packages: + validation_messages.extend(validate_package(package, spdx_version)) + + return validation_messages + + +def validate_package_within_document( + package: Package, spdx_version: str, document: Document +) -> List[ValidationMessage]: + validation_messages: List[ValidationMessage] = [] + context = ValidationContext( + spdx_id=package.spdx_id, + parent_id=document.creation_info.spdx_id, + element_type=SpdxElementType.PACKAGE, + full_element=package, + ) + + for message in validate_spdx_id(package.spdx_id, document): + validation_messages.append(ValidationMessage(message, context)) + + if not package.files_analyzed: + package_contains_relationships = filter_by_type_and_origin( + document.relationships, RelationshipType.CONTAINS, package.spdx_id + ) + package_contains_file_relationships = [ + relationship + for relationship in package_contains_relationships + if get_element_type_from_spdx_id(relationship.related_spdx_element_id, document) == File + ] + + contained_in_package_relationships = filter_by_type_and_target( + document.relationships, RelationshipType.CONTAINED_BY, package.spdx_id + ) + file_contained_in_package_relationships = [ + relationship + for relationship in contained_in_package_relationships + if get_element_type_from_spdx_id(relationship.spdx_element_id, document) == File + ] + + combined_relationships: List[Relationship] = ( + package_contains_file_relationships + file_contained_in_package_relationships + ) + + if combined_relationships: + validation_messages.append( + ValidationMessage( + f"package must contain no elements if files_analyzed is False, but found {combined_relationships}", + context, + ) + ) + + validation_messages.extend(validate_license_expression(package.license_concluded, document, package.spdx_id)) + + license_info_from_files = package.license_info_from_files + if license_info_from_files: + if not package.files_analyzed: + validation_messages.append( + ValidationMessage( + f"license_info_from_files must be None if files_analyzed is False, but is: " + f"{license_info_from_files}", + context, + ) + ) + else: + validation_messages.extend( + validate_license_expressions(license_info_from_files, document, package.spdx_id) + ) + + validation_messages.extend(validate_license_expression(package.license_declared, document, package.spdx_id)) + + validation_messages.extend(validate_package(package, spdx_version, context)) + + return validation_messages + + +def validate_package( + package: Package, spdx_version: str, context: Optional[ValidationContext] = None +) -> List[ValidationMessage]: + validation_messages: List[ValidationMessage] = [] + if not context: + context = ValidationContext( + spdx_id=package.spdx_id, element_type=SpdxElementType.PACKAGE, full_element=package + ) + + download_location = package.download_location + if isinstance(download_location, str): + for message in validate_download_location(download_location): + validation_messages.append(ValidationMessage("package download_location " + message, context)) + + homepage = package.homepage + if isinstance(homepage, str): + for message in validate_url(homepage): + validation_messages.append(ValidationMessage("homepage " + message, context)) + + verification_code = package.verification_code + if verification_code: + if not package.files_analyzed: + validation_messages.append( + ValidationMessage( + f"verification_code must be None if files_analyzed is False, but is: {verification_code}", context + ) + ) + else: + validation_messages.extend(validate_verification_code(verification_code, package.spdx_id)) + + validation_messages.extend(validate_checksums(package.checksums, package.spdx_id, spdx_version)) + + validation_messages.extend( + validate_external_package_refs(package.external_references, package.spdx_id, spdx_version) + ) + + if spdx_version == "SPDX-2.2": + if package.primary_package_purpose is not None: + validation_messages.append( + ValidationMessage("primary_package_purpose is not supported in SPDX-2.2", context) + ) + if package.built_date is not None: + validation_messages.append(ValidationMessage("built_date is not supported in SPDX-2.2", context)) + if package.release_date is not None: + validation_messages.append(ValidationMessage("release_date is not supported in SPDX-2.2", context)) + if package.valid_until_date is not None: + validation_messages.append(ValidationMessage("valid_until_date is not supported in SPDX-2.2", context)) + + if package.license_concluded is None: + validation_messages.append(ValidationMessage("license_concluded is mandatory in SPDX-2.2", context)) + if package.license_declared is None: + validation_messages.append(ValidationMessage("license_declared is mandatory in SPDX-2.2", context)) + if package.copyright_text is None: + validation_messages.append(ValidationMessage("copyright_text is mandatory in SPDX-2.2", context)) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/package_verification_code_validator.py b/src/spdx_tools/spdx/validation/package_verification_code_validator.py new file mode 100644 index 000000000..55dd1bb35 --- /dev/null +++ b/src/spdx_tools/spdx/validation/package_verification_code_validator.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import re + +from beartype.typing import List + +from spdx_tools.spdx.model import PackageVerificationCode +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_verification_code(verification_code: PackageVerificationCode, parent_id: str) -> List[ValidationMessage]: + validation_messages: List[ValidationMessage] = [] + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.PACKAGE_VERIFICATION_CODE, full_element=verification_code + ) + + for file in verification_code.excluded_files: + if file.startswith("/"): + validation_messages.append( + ValidationMessage(f'file name must not be an absolute path starting with "/", but is: {file}', context) + ) + + value: str = verification_code.value + if not re.match("^[0-9a-f]{40}$", value): + validation_messages.append( + ValidationMessage( + f"value of verification_code must consist of 40 lowercase hexadecimal digits, but is: {value} " + f"(length: {len(value)} digits)", + context, + ) + ) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/relationship_validator.py b/src/spdx_tools/spdx/validation/relationship_validator.py new file mode 100644 index 000000000..1c194ac99 --- /dev/null +++ b/src/spdx_tools/spdx/validation/relationship_validator.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import List + +from spdx_tools.spdx.model import Document, Relationship, RelationshipType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_relationships( + relationships: List[Relationship], spdx_version: str, document: Document +) -> List[ValidationMessage]: + validation_messages = [] + for relationship in relationships: + validation_messages.extend(validate_relationship(relationship, spdx_version, document)) + + return validation_messages + + +def validate_relationship( + relationship: Relationship, spdx_version: str, document: Document +) -> List[ValidationMessage]: + validation_messages = [] + context = ValidationContext(element_type=SpdxElementType.RELATIONSHIP, full_element=relationship) + + relationship_type: RelationshipType = relationship.relationship_type + + messages: List[str] = validate_spdx_id(relationship.spdx_element_id, document, check_document=True) + for message in messages: + validation_messages.append(ValidationMessage(message, context)) + + if relationship.related_spdx_element_id not in [SpdxNone(), SpdxNoAssertion()]: + messages: List[str] = validate_spdx_id(relationship.related_spdx_element_id, document, check_document=True) + for message in messages: + validation_messages.append(ValidationMessage(message, context)) + + if spdx_version == "SPDX-2.2": + if ( + relationship_type == RelationshipType.SPECIFICATION_FOR + or relationship_type == RelationshipType.REQUIREMENT_DESCRIPTION_FOR + ): + validation_messages.append(ValidationMessage(f"{relationship_type} is not supported in SPDX-2.2", context)) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/snippet_validator.py b/src/spdx_tools/spdx/validation/snippet_validator.py new file mode 100644 index 000000000..8c1aed9c5 --- /dev/null +++ b/src/spdx_tools/spdx/validation/snippet_validator.py @@ -0,0 +1,108 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import List, Optional + +from spdx_tools.spdx.model import Document, Snippet +from spdx_tools.spdx.validation.license_expression_validator import ( + validate_license_expression, + validate_license_expressions, +) +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def validate_snippets( + snippets: List[Snippet], spdx_version: str, document: Optional[Document] = None +) -> List[ValidationMessage]: + validation_messages = [] + if document: + for snippet in snippets: + validation_messages.extend(validate_snippet_within_document(snippet, spdx_version, document)) + else: + for snippet in snippets: + validation_messages.extend(validate_snippet(snippet, spdx_version)) + + return validation_messages + + +def validate_snippet_within_document( + snippet: Snippet, spdx_version: str, document: Document +) -> List[ValidationMessage]: + validation_messages: List[ValidationMessage] = [] + context = ValidationContext( + spdx_id=snippet.spdx_id, + parent_id=document.creation_info.spdx_id, + element_type=SpdxElementType.SNIPPET, + full_element=snippet, + ) + + messages: List[str] = validate_spdx_id(snippet.spdx_id, document) + for message in messages: + validation_messages.append(ValidationMessage(message, context)) + + messages: List[str] = validate_spdx_id(snippet.file_spdx_id, document, check_files=True) + for message in messages: + validation_messages.append(ValidationMessage(message, context)) + + validation_messages.extend(validate_license_expression(snippet.license_concluded, document, snippet.spdx_id)) + + validation_messages.extend( + validate_license_expressions(snippet.license_info_in_snippet, document, snippet.spdx_id) + ) + + validation_messages.extend(validate_snippet(snippet, spdx_version, context)) + + return validation_messages + + +def validate_snippet( + snippet: Snippet, spdx_version: str, context: Optional[ValidationContext] = None +) -> List[ValidationMessage]: + validation_messages = [] + if not context: + context = ValidationContext( + spdx_id=snippet.spdx_id, element_type=SpdxElementType.SNIPPET, full_element=snippet + ) + + if snippet.byte_range[0] < 1: + validation_messages.append( + ValidationMessage( + f"byte_range values must be greater than or equal to 1, but is: {snippet.byte_range}", context + ) + ) + + if snippet.byte_range[0] > snippet.byte_range[1]: + validation_messages.append( + ValidationMessage( + f"the first value of byte_range must be less than or equal to the second, but is: " + f"{snippet.byte_range}", + context, + ) + ) + + if snippet.line_range: + if snippet.line_range[0] < 1: + validation_messages.append( + ValidationMessage( + f"line_range values must be greater than or equal to 1, but is: {snippet.line_range}", context + ) + ) + + if snippet.line_range[0] > snippet.line_range[1]: + validation_messages.append( + ValidationMessage( + f"the first value of line_range must be less than or equal to the second, " + f"but is: {snippet.line_range}", + context, + ) + ) + + if spdx_version == "SPDX-2.2": + if snippet.license_concluded is None: + validation_messages.append(ValidationMessage("license_concluded is mandatory in SPDX-2.2", context)) + if snippet.copyright_text is None: + validation_messages.append(ValidationMessage("copyright_text is mandatory in SPDX-2.2", context)) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/spdx_id_validators.py b/src/spdx_tools/spdx/validation/spdx_id_validators.py new file mode 100644 index 000000000..6441236a9 --- /dev/null +++ b/src/spdx_tools/spdx/validation/spdx_id_validators.py @@ -0,0 +1,99 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import re + +from beartype.typing import List + +from spdx_tools.spdx.document_utils import get_contained_spdx_element_ids +from spdx_tools.spdx.model import Document, File + + +def is_valid_internal_spdx_id(spdx_id: str) -> bool: + return bool(re.match(r"^SPDXRef-[\da-zA-Z.-]+$", spdx_id)) + + +def is_valid_external_doc_ref_id(external_ref_id: str) -> bool: + return bool(re.match(r"^DocumentRef-[\da-zA-Z.+-]+$", external_ref_id)) + + +def is_spdx_id_present_in_files(spdx_id: str, files: List[File]) -> bool: + return spdx_id in [file.spdx_id for file in files] + + +def is_spdx_id_present_in_document(spdx_id: str, document: Document) -> bool: + all_spdx_ids_in_document: List[str] = get_list_of_all_spdx_ids(document) + + return spdx_id in all_spdx_ids_in_document + + +def get_list_of_all_spdx_ids(document: Document) -> List[str]: + all_spdx_ids_in_document: List[str] = [document.creation_info.spdx_id] + all_spdx_ids_in_document.extend(get_contained_spdx_element_ids(document)) + + return all_spdx_ids_in_document + + +def is_external_doc_ref_present_in_document(external_ref_id: str, document: Document) -> bool: + all_external_doc_ref_ids_in_document = [ + external_doc_ref.document_ref_id for external_doc_ref in document.creation_info.external_document_refs + ] + + return external_ref_id in all_external_doc_ref_ids_in_document + + +def validate_spdx_id( + spdx_id: str, document: Document, check_document: bool = False, check_files: bool = False +) -> List[str]: + """Test that the given spdx_id (and a potential DocumentRef to an external document) is valid + and, if it is a reference, actually exists in the document. Optionally checks files or the whole document + for the existence of the spdx_id (i.e. if it is used as a reference). Returns a list of validation messages.""" + + validation_messages: List[str] = [] + split_id: List[str] = spdx_id.split(":") + + # # # invalid case # # # + if len(split_id) > 2: + return [ + f"spdx_id must not contain more than one colon in order to separate the external document reference id " + f"from the internal SPDX id, but is: {spdx_id}" + ] + + # # # case with external document ref prefix # # # + if len(split_id) == 2: + if not is_valid_external_doc_ref_id(split_id[0]): + validation_messages.append( + f'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and ' + f'"+" and must begin with "DocumentRef-", but is: {split_id[0]}' + ) + if not is_valid_internal_spdx_id(split_id[1]): + validation_messages.append( + f'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin ' + f'with "SPDXRef-", but is: {split_id[1]}' + ) + if not is_external_doc_ref_present_in_document(split_id[0], document): + validation_messages.append( + f'did not find the external document reference "{split_id[0]}" in the SPDX document' + ) + + return validation_messages + + # # # "normal" case # # # + if not is_valid_internal_spdx_id(spdx_id): + validation_messages.append( + f'spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: ' + f"{spdx_id}" + ) + + if check_document: + if not is_spdx_id_present_in_document(spdx_id, document): + validation_messages.append(f'did not find the referenced spdx_id "{spdx_id}" in the SPDX document') + + if check_files: + if not is_spdx_id_present_in_files(spdx_id, document.files): + validation_messages.append( + f'did not find the referenced spdx_id "{spdx_id}" in the SPDX document\'s files' + ) + + return validation_messages diff --git a/src/spdx_tools/spdx/validation/uri_validators.py b/src/spdx_tools/spdx/validation/uri_validators.py new file mode 100644 index 000000000..c14d196f4 --- /dev/null +++ b/src/spdx_tools/spdx/validation/uri_validators.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import re + +from beartype.typing import List +from uritools import isabsuri, urisplit + +url_pattern = ( + "(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/|ssh:\\/\\/|git:\\/\\/|svn:\\/\\/|sftp:" + "\\/\\/|ftp:\\/\\/)?([\\w\\-.!~*'()%;:&=+$,]+@)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+){0,100}\\.[a-z]{2,5}" + "(:[0-9]{1,5})?(\\/.*)?" +) +supported_download_repos: str = "(git|hg|svn|bzr)" +git_pattern = "(git\\+git@[a-zA-Z0-9\\.\\-]+:[a-zA-Z0-9/\\\\.@\\-]+)" +bazaar_pattern = "(bzr\\+lp:[a-zA-Z0-9\\.\\-]+)" +download_location_pattern = ( + "^(((" + supported_download_repos + "\\+)?" + url_pattern + ")|" + git_pattern + "|" + bazaar_pattern + ")$" +) + + +def validate_url(url: str) -> List[str]: + if not re.match(url_pattern, url): + return [f"must be a valid URL, but is: {url}"] + + return [] + + +def validate_download_location(location: str) -> List[str]: + if not (validate_url(location) == [] or re.match(download_location_pattern, location)): + return [f"must be a valid URL or download location according to the specification, but is: {location}"] + + return [] + + +def validate_uri(uri: str) -> List[str]: + if not isabsuri(uri): + return [f"must be a valid URI specified in RFC-3986 and must contain no fragment (#), but is: {uri}"] + else: + split = urisplit(uri) + if split.scheme is None: + return [f"must have a URI scheme, but is: {uri}"] + + return [] diff --git a/src/spdx_tools/spdx/validation/validation_message.py b/src/spdx_tools/spdx/validation/validation_message.py new file mode 100644 index 000000000..2ef1ba241 --- /dev/null +++ b/src/spdx_tools/spdx/validation/validation_message.py @@ -0,0 +1,39 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from dataclasses import dataclass +from enum import Enum, auto + +from beartype.typing import Any, Optional + + +class SpdxElementType(Enum): + LICENSE_EXPRESSION = auto() + PACKAGE_VERIFICATION_CODE = auto() + EXTERNAL_DOCUMENT_REF = auto() + CHECKSUM = auto() + EXTERNAL_PACKAGE_REF = auto() + ACTOR = auto() + DOCUMENT = auto() + CREATION_INFO = auto() + PACKAGE = auto() + FILE = auto() + SNIPPET = auto() + ANNOTATION = auto() + RELATIONSHIP = auto() + EXTRACTED_LICENSING_INFO = auto() + + +@dataclass(frozen=True) +class ValidationContext: + spdx_id: Optional[str] = None # not every type has an id, or it might be missing + parent_id: Optional[str] = None # if a parent is known and has a valid id + element_type: Optional[SpdxElementType] = None + full_element: Any = None # can be any class of the data model + + +@dataclass(frozen=True) +class ValidationMessage: + validation_message: str + context: ValidationContext diff --git a/src/spdx_tools/spdx/writer/__init__.py b/src/spdx_tools/spdx/writer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/writer/json/__init__.py b/src/spdx_tools/spdx/writer/json/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/writer/json/json_writer.py b/src/spdx_tools/spdx/writer/json/json_writer.py new file mode 100644 index 000000000..bdcfdf718 --- /dev/null +++ b/src/spdx_tools/spdx/writer/json/json_writer.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import json + +from beartype.typing import IO + +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.writer.write_utils import convert, validate_and_deduplicate + + +def write_document_to_stream( + document: Document, + stream: IO[str], + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, +): + """ + Serializes the provided document to json and writes it to a file with the provided name. Unless validate is set + to False, validates the document before serialization. Unless a DocumentConverter instance is provided, + a new one is created. + """ + document = validate_and_deduplicate(document, validate, drop_duplicates) + document_dict = convert(document, converter) + json.dump(document_dict, stream, indent=4) + + +def write_document_to_file( + document: Document, + file_name: str, + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, +): + with open(file_name, "w", encoding="utf-8") as out: + write_document_to_stream(document, out, validate, converter, drop_duplicates) diff --git a/src/spdx_tools/spdx/writer/rdf/__init__.py b/src/spdx_tools/spdx/writer/rdf/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/writer/rdf/annotation_writer.py b/src/spdx_tools/spdx/writer/rdf/annotation_writer.py new file mode 100644 index 000000000..e973eeb0d --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/annotation_writer.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef + +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model import Annotation +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id + + +def add_annotation_to_graph( + annotation: Annotation, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str] +): + annotation_resource = URIRef( + add_namespace_to_spdx_id(annotation.spdx_id, doc_namespace, external_doc_ref_to_namespace) + ) + annotation_node = BNode() + graph.add((annotation_node, RDF.type, SPDX_NAMESPACE.Annotation)) + graph.add( + ( + annotation_node, + SPDX_NAMESPACE.annotationType, + SPDX_NAMESPACE[f"annotationType_{snake_case_to_camel_case(annotation.annotation_type.name)}"], + ) + ) + graph.add((annotation_node, SPDX_NAMESPACE.annotator, Literal(annotation.annotator.to_serialized_string()))) + graph.add( + (annotation_node, SPDX_NAMESPACE.annotationDate, Literal(datetime_to_iso_string(annotation.annotation_date))) + ) + graph.add((annotation_node, RDFS.comment, Literal(annotation.annotation_comment))) + + graph.add((annotation_resource, SPDX_NAMESPACE.annotation, annotation_node)) diff --git a/src/spdx_tools/spdx/writer/rdf/checksum_writer.py b/src/spdx_tools/spdx/writer/rdf/checksum_writer.py new file mode 100644 index 000000000..1f7172e88 --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/checksum_writer.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDF, BNode, Graph, Literal, URIRef + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def add_checksum_to_graph(checksum: Checksum, graph: Graph, parent: URIRef): + checksum_node = BNode() + graph.add((checksum_node, RDF.type, SPDX_NAMESPACE.Checksum)) + graph.add((checksum_node, SPDX_NAMESPACE.algorithm, algorithm_to_rdf_string(checksum.algorithm))) + graph.add((checksum_node, SPDX_NAMESPACE.checksumValue, Literal(checksum.value))) + + graph.add((parent, SPDX_NAMESPACE.checksum, checksum_node)) + + +def algorithm_to_rdf_string(algorithm: ChecksumAlgorithm) -> URIRef: + if "BLAKE2B" in algorithm.name: + algorithm_rdf_string = algorithm.name.replace("_", "").lower() + else: + algorithm_rdf_string = algorithm.name.lower() + + return SPDX_NAMESPACE[f"checksumAlgorithm_{algorithm_rdf_string}"] diff --git a/src/spdx_tools/spdx/writer/rdf/creation_info_writer.py b/src/spdx_tools/spdx/writer/rdf/creation_info_writer.py new file mode 100644 index 000000000..6e77bc8d9 --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/creation_info_writer.py @@ -0,0 +1,39 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model import CreationInfo +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph +from spdx_tools.spdx.writer.rdf.writer_utils import add_optional_literal + + +def add_creation_info_to_graph(creation_info: CreationInfo, graph: Graph): + doc_node = URIRef(f"{creation_info.document_namespace}#{creation_info.spdx_id}") + graph.add((doc_node, RDF.type, SPDX_NAMESPACE.SpdxDocument)) + graph.add((doc_node, SPDX_NAMESPACE.specVersion, Literal(creation_info.spdx_version))) + graph.add((doc_node, SPDX_NAMESPACE.dataLicense, LICENSE_NAMESPACE[creation_info.data_license])) + graph.add((doc_node, SPDX_NAMESPACE.name, Literal(creation_info.name))) + add_optional_literal(creation_info.document_comment, graph, doc_node, RDFS.comment) + + creation_info_node = BNode() + graph.add((creation_info_node, RDF.type, SPDX_NAMESPACE.CreationInfo)) + + graph.add((creation_info_node, SPDX_NAMESPACE.created, Literal(datetime_to_iso_string(creation_info.created)))) + + for creator in creation_info.creators: + graph.add((creation_info_node, SPDX_NAMESPACE.creator, Literal(creator.to_serialized_string()))) + + add_optional_literal( + creation_info.license_list_version, graph, creation_info_node, SPDX_NAMESPACE.licenseListVersion + ) + add_optional_literal(creation_info.creator_comment, graph, creation_info_node, RDFS.comment) + + graph.add((doc_node, SPDX_NAMESPACE.creationInfo, creation_info_node)) + + for external_document_ref in creation_info.external_document_refs: + add_external_document_ref_to_graph(external_document_ref, graph, doc_node, creation_info.document_namespace) + + return doc_node diff --git a/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py b/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py new file mode 100644 index 000000000..958ac8b5e --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDF, Graph, URIRef + +from spdx_tools.spdx.model import ExternalDocumentRef +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph + + +def add_external_document_ref_to_graph( + external_document_ref: ExternalDocumentRef, graph: Graph, doc_node: URIRef, doc_namespace: str +): + external_document_ref_resource = URIRef(f"{doc_namespace}#{external_document_ref.document_ref_id}") + graph.add((external_document_ref_resource, RDF.type, SPDX_NAMESPACE.ExternalDocumentRef)) + graph.add( + (external_document_ref_resource, SPDX_NAMESPACE.spdxDocument, URIRef(external_document_ref.document_uri)) + ) + add_checksum_to_graph(external_document_ref.checksum, graph, external_document_ref_resource) + + graph.add((doc_node, SPDX_NAMESPACE.externalDocumentRef, external_document_ref_resource)) diff --git a/src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py b/src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py new file mode 100644 index 000000000..f30ab5d60 --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef + +from spdx_tools.spdx.model import ExtractedLicensingInfo +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.writer_utils import add_literal_or_no_assertion, add_optional_literal + + +def add_extracted_licensing_info_to_graph( + extracted_licensing_info: ExtractedLicensingInfo, graph: Graph, doc_node, doc_namespace: str +): + if extracted_licensing_info.license_id: + extracted_licensing_info_resource = URIRef(f"{doc_namespace}#{extracted_licensing_info.license_id}") + graph.add((extracted_licensing_info_resource, RDF.type, SPDX_NAMESPACE.ExtractedLicensingInfo)) + else: + extracted_licensing_info_resource = BNode() + add_optional_literal( + extracted_licensing_info.license_id, graph, extracted_licensing_info_resource, SPDX_NAMESPACE.licenseId + ) + add_optional_literal( + extracted_licensing_info.extracted_text, graph, extracted_licensing_info_resource, SPDX_NAMESPACE.extractedText + ) + add_literal_or_no_assertion( + extracted_licensing_info.license_name, graph, extracted_licensing_info_resource, SPDX_NAMESPACE.name + ) + for cross_reference in extracted_licensing_info.cross_references: + graph.add((extracted_licensing_info_resource, RDFS.seeAlso, Literal(cross_reference))) + add_optional_literal(extracted_licensing_info.comment, graph, extracted_licensing_info_resource, RDFS.comment) + + graph.add((doc_node, SPDX_NAMESPACE.hasExtractedLicensingInfo, extracted_licensing_info_resource)) diff --git a/src/spdx_tools/spdx/writer/rdf/file_writer.py b/src/spdx_tools/spdx/writer/rdf/file_writer.py new file mode 100644 index 000000000..679be8d22 --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/file_writer.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict +from rdflib import RDF, RDFS, Graph, Literal, URIRef + +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.model import File +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph +from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal + + +def add_file_to_graph(file: File, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str]): + file_resource = URIRef(add_namespace_to_spdx_id(file.spdx_id, doc_namespace, external_doc_ref_to_namespace)) + graph.add((file_resource, RDF.type, SPDX_NAMESPACE.File)) + graph.add((file_resource, SPDX_NAMESPACE.fileName, Literal(file.name))) + for file_type in file.file_types: + graph.add( + ( + file_resource, + SPDX_NAMESPACE.fileType, + SPDX_NAMESPACE[f"fileType_{snake_case_to_camel_case(file_type.name)}"], + ) + ) + + for checksum in file.checksums: + add_checksum_to_graph(checksum, graph, file_resource) + + add_license_expression_or_none_or_no_assertion( + file.license_concluded, graph, file_resource, SPDX_NAMESPACE.licenseConcluded, doc_namespace + ) + add_license_expression_or_none_or_no_assertion( + file.license_info_in_file, graph, file_resource, SPDX_NAMESPACE.licenseInfoInFile, doc_namespace + ) + + add_optional_literal(file.license_comment, graph, file_resource, SPDX_NAMESPACE.licenseComments) + add_optional_literal(file.copyright_text, graph, file_resource, SPDX_NAMESPACE.copyrightText) + add_optional_literal(file.comment, graph, file_resource, RDFS.comment) + add_optional_literal(file.notice, graph, file_resource, SPDX_NAMESPACE.noticeText) + for contributor in file.contributors: + graph.add((file_resource, SPDX_NAMESPACE.fileContributor, Literal(contributor))) + for attribution_text in file.attribution_texts: + graph.add((file_resource, SPDX_NAMESPACE.attributionText, Literal(attribution_text))) diff --git a/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py new file mode 100644 index 000000000..c8a76035a --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py @@ -0,0 +1,84 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Union +from boolean import Expression +from license_expression import AND, OR, ExpressionInfo, LicenseExpression, LicenseSymbol, LicenseWithExceptionSymbol +from rdflib import RDF, BNode, Graph, URIRef +from rdflib.term import Literal, Node + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE + + +def add_license_expression_or_none_or_no_assertion( + value: Union[ + List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]], LicenseExpression, SpdxNoAssertion, SpdxNone + ], + graph: Graph, + parent: Node, + predicate: Node, + doc_namespace: str, +): + if isinstance(value, SpdxNoAssertion): + graph.add((parent, predicate, SPDX_NAMESPACE.noassertion)) + return + if isinstance(value, SpdxNone): + graph.add((parent, predicate, SPDX_NAMESPACE.none)) + return + if isinstance(value, list): + for license_expression in value: + add_license_expression_or_none_or_no_assertion(license_expression, graph, parent, predicate, doc_namespace) + if isinstance(value, LicenseExpression): + add_license_expression_to_graph(value, graph, parent, predicate, doc_namespace) + + +def add_license_expression_to_graph( + license_expression: Expression, graph: Graph, parent: Node, predicate: Node, doc_namespace: str +): + if isinstance(license_expression, AND): + member_node = BNode() + graph.add((member_node, RDF.type, SPDX_NAMESPACE.ConjunctiveLicenseSet)) + graph.add((parent, predicate, member_node)) + for arg in license_expression.args: + add_license_expression_to_graph(arg, graph, member_node, SPDX_NAMESPACE.member, doc_namespace) + if isinstance(license_expression, OR): + member_node = BNode() + graph.add((member_node, RDF.type, SPDX_NAMESPACE.DisjunctiveLicenseSet)) + graph.add((parent, predicate, member_node)) + for arg in license_expression.args: + add_license_expression_to_graph(arg, graph, member_node, SPDX_NAMESPACE.member, doc_namespace) + if isinstance(license_expression, LicenseWithExceptionSymbol): + member_node = BNode() + graph.add((member_node, RDF.type, SPDX_NAMESPACE.WithExceptionOperator)) + graph.add((parent, predicate, member_node)) + + add_license_expression_to_graph( + license_expression.license_symbol, graph, member_node, SPDX_NAMESPACE.member, doc_namespace + ) + add_license_exception_to_graph(license_expression.exception_symbol, graph, member_node) + + if isinstance(license_expression, LicenseSymbol): + if license_or_exception_is_on_spdx_licensing_list(license_expression): + graph.add((parent, predicate, LICENSE_NAMESPACE[str(license_expression)])) + else: + # assuming that the license expression is a LicenseRef to an instance of ExtractedLicensingInfo + graph.add((parent, predicate, URIRef(f"{doc_namespace}#{license_expression}"))) + + +def license_or_exception_is_on_spdx_licensing_list(license_symbol: LicenseSymbol) -> bool: + symbol_info: ExpressionInfo = spdx_licensing.validate(license_symbol) + return not symbol_info.errors + + +def add_license_exception_to_graph(license_exception: LicenseSymbol, graph: Graph, parent: Node): + if license_or_exception_is_on_spdx_licensing_list(license_exception): + exception_node = LICENSE_NAMESPACE[str(license_exception)] + graph.add((parent, SPDX_NAMESPACE.licenseException, exception_node)) + else: + exception_node = BNode() + graph.add((exception_node, SPDX_NAMESPACE.licenseExceptionId, Literal(license_exception))) + graph.add((parent, SPDX_NAMESPACE.licenseException, exception_node)) + + graph.add((exception_node, RDF.type, SPDX_NAMESPACE.LicenseException)) diff --git a/src/spdx_tools/spdx/writer/rdf/package_writer.py b/src/spdx_tools/spdx/writer/rdf/package_writer.py new file mode 100644 index 000000000..2137d0dbd --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/package_writer.py @@ -0,0 +1,133 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict +from rdflib import DOAP, RDF, RDFS, XSD, BNode, Graph, Literal, URIRef + +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.model import ExternalPackageRef, Package, PackageVerificationCode +from spdx_tools.spdx.model.package import CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES +from spdx_tools.spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph +from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion +from spdx_tools.spdx.writer.rdf.writer_utils import ( + add_datetime_to_graph, + add_literal_or_no_assertion_or_none, + add_namespace_to_spdx_id, + add_optional_literal, +) + + +def add_package_to_graph( + package: Package, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str] +): + package_resource = URIRef(add_namespace_to_spdx_id(package.spdx_id, doc_namespace, external_doc_ref_to_namespace)) + graph.add((package_resource, RDF.type, SPDX_NAMESPACE.Package)) + + graph.add((package_resource, SPDX_NAMESPACE.name, Literal(package.name))) + add_optional_literal(package.version, graph, package_resource, SPDX_NAMESPACE.versionInfo) + add_optional_literal(package.file_name, graph, package_resource, SPDX_NAMESPACE.packageFileName) + add_optional_literal(package.supplier, graph, package_resource, SPDX_NAMESPACE.supplier) + add_optional_literal(package.originator, graph, package_resource, SPDX_NAMESPACE.originator) + add_literal_or_no_assertion_or_none( + package.download_location, graph, package_resource, SPDX_NAMESPACE.downloadLocation + ) + graph.add((package_resource, SPDX_NAMESPACE.filesAnalyzed, Literal(package.files_analyzed, datatype=XSD.boolean))) + add_package_verification_code_to_graph(package.verification_code, graph, package_resource) + for checksum in package.checksums: + add_checksum_to_graph(checksum, graph, package_resource) + + add_optional_literal(package.homepage, graph, package_resource, DOAP.homepage) + add_optional_literal(package.source_info, graph, package_resource, SPDX_NAMESPACE.sourceInfo) + add_license_expression_or_none_or_no_assertion( + package.license_concluded, graph, package_resource, SPDX_NAMESPACE.licenseConcluded, doc_namespace + ) + add_license_expression_or_none_or_no_assertion( + package.license_info_from_files, graph, package_resource, SPDX_NAMESPACE.licenseInfoFromFiles, doc_namespace + ) + add_license_expression_or_none_or_no_assertion( + package.license_declared, graph, package_resource, SPDX_NAMESPACE.licenseDeclared, doc_namespace + ) + add_optional_literal(package.license_comment, graph, package_resource, SPDX_NAMESPACE.licenseComments) + add_optional_literal(package.copyright_text, graph, package_resource, SPDX_NAMESPACE.copyrightText) + add_optional_literal(package.summary, graph, package_resource, SPDX_NAMESPACE.summary) + add_optional_literal(package.description, graph, package_resource, SPDX_NAMESPACE.description) + add_optional_literal(package.comment, graph, package_resource, RDFS.comment) + for external_reference in package.external_references: + add_external_package_ref_to_graph(external_reference, graph, package_resource, doc_namespace) + for attribution_text in package.attribution_texts: + add_optional_literal(attribution_text, graph, package_resource, SPDX_NAMESPACE.attributionText) + if package.primary_package_purpose: + graph.add( + ( + package_resource, + SPDX_NAMESPACE.primaryPackagePurpose, + SPDX_NAMESPACE[f"purpose_{snake_case_to_camel_case(package.primary_package_purpose.name)}"], + ) + ) + + add_datetime_to_graph(package.release_date, graph, package_resource, SPDX_NAMESPACE.releaseDate) + add_datetime_to_graph(package.built_date, graph, package_resource, SPDX_NAMESPACE.builtDate) + add_datetime_to_graph(package.valid_until_date, graph, package_resource, SPDX_NAMESPACE.validUntilDate) + + +def add_package_verification_code_to_graph( + package_verification_code: PackageVerificationCode, graph: Graph, package_node: URIRef +): + if not package_verification_code: + return + package_verification_code_node = BNode() + graph.add((package_verification_code_node, RDF.type, SPDX_NAMESPACE.PackageVerificationCode)) + graph.add( + ( + package_verification_code_node, + SPDX_NAMESPACE.packageVerificationCodeValue, + Literal(package_verification_code.value), + ) + ) + for excluded_file in package_verification_code.excluded_files: + graph.add( + ( + package_verification_code_node, + SPDX_NAMESPACE.packageVerificationCodeExcludedFile, + Literal(excluded_file), + ) + ) + + graph.add((package_node, SPDX_NAMESPACE.packageVerificationCode, package_verification_code_node)) + + +def add_external_package_ref_to_graph( + external_package_ref: ExternalPackageRef, graph: Graph, package_node: URIRef, doc_namespace: str +): + external_package_ref_node = BNode() + graph.add((external_package_ref_node, RDF.type, SPDX_NAMESPACE.ExternalRef)) + graph.add( + ( + external_package_ref_node, + SPDX_NAMESPACE.referenceCategory, + SPDX_NAMESPACE[f"referenceCategory_{snake_case_to_camel_case(external_package_ref.category.name)}"], + ) + ) + + if external_package_ref.reference_type in CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[external_package_ref.category]: + graph.add( + ( + external_package_ref_node, + SPDX_NAMESPACE.referenceType, + REFERENCE_NAMESPACE[external_package_ref.reference_type], + ) + ) + else: + graph.add( + ( + external_package_ref_node, + SPDX_NAMESPACE.referenceType, + URIRef(f"{doc_namespace}#{external_package_ref.reference_type}"), + ) + ) + graph.add((external_package_ref_node, SPDX_NAMESPACE.referenceLocator, Literal(external_package_ref.locator))) + if external_package_ref.comment: + graph.add((external_package_ref_node, RDFS.comment, Literal(external_package_ref.comment))) + + graph.add((package_node, SPDX_NAMESPACE.externalRef, external_package_ref_node)) diff --git a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py new file mode 100644 index 000000000..206494def --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import IO, Dict +from rdflib import DOAP, Graph +from rdflib.compare import to_isomorphic + +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.annotation_writer import add_annotation_to_graph +from spdx_tools.spdx.writer.rdf.creation_info_writer import add_creation_info_to_graph +from spdx_tools.spdx.writer.rdf.extracted_licensing_info_writer import add_extracted_licensing_info_to_graph +from spdx_tools.spdx.writer.rdf.file_writer import add_file_to_graph +from spdx_tools.spdx.writer.rdf.package_writer import add_package_to_graph +from spdx_tools.spdx.writer.rdf.relationship_writer import add_relationship_to_graph +from spdx_tools.spdx.writer.rdf.snippet_writer import add_snippet_to_graph +from spdx_tools.spdx.writer.write_utils import validate_and_deduplicate + + +def write_document_to_stream( + document: Document, stream: IO[bytes], validate: bool = True, drop_duplicates: bool = True +): + document = validate_and_deduplicate(document, validate, drop_duplicates) + graph = Graph() + doc_namespace = document.creation_info.document_namespace + external_doc_ref_to_namespace: Dict[str, str] = { + external_doc_ref.document_ref_id: external_doc_ref.document_uri + for external_doc_ref in document.creation_info.external_document_refs + } + doc_node = add_creation_info_to_graph(document.creation_info, graph) + for annotation in document.annotations: + add_annotation_to_graph(annotation, graph, doc_namespace, external_doc_ref_to_namespace) + + for file in document.files: + add_file_to_graph(file, graph, doc_namespace, external_doc_ref_to_namespace) + + for package in document.packages: + add_package_to_graph(package, graph, doc_namespace, external_doc_ref_to_namespace) + + for relationship in document.relationships: + add_relationship_to_graph(relationship, graph, doc_namespace, external_doc_ref_to_namespace) + + for snippet in document.snippets: + add_snippet_to_graph(snippet, graph, doc_namespace, external_doc_ref_to_namespace) + + for extracted_licensing_info in document.extracted_licensing_info: + add_extracted_licensing_info_to_graph(extracted_licensing_info, graph, doc_node, doc_namespace) + + graph = to_isomorphic(graph) + graph.bind("spdx", SPDX_NAMESPACE) + graph.bind("doap", DOAP) + graph.bind("ptr", POINTER_NAMESPACE) + graph.serialize(stream, "pretty-xml", encoding="UTF-8", max_depth=100) + + +def write_document_to_file(document: Document, file_name: str, validate: bool = True, drop_duplicates: bool = True): + with open(file_name, "wb") as out: + write_document_to_stream(document, out, validate, drop_duplicates) diff --git a/src/spdx_tools/spdx/writer/rdf/relationship_writer.py b/src/spdx_tools/spdx/writer/rdf/relationship_writer.py new file mode 100644 index 000000000..6d49431af --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/relationship_writer.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef + +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.model import Relationship, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id + + +def add_relationship_to_graph( + relationship: Relationship, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str] +): + relationship_node = BNode() + graph.add((relationship_node, RDF.type, SPDX_NAMESPACE.Relationship)) + graph.add( + ( + relationship_node, + SPDX_NAMESPACE.relationshipType, + SPDX_NAMESPACE[f"relationshipType_{snake_case_to_camel_case(relationship.relationship_type.name)}"], + ) + ) + if isinstance(relationship.related_spdx_element_id, SpdxNone): + graph.add((relationship_node, SPDX_NAMESPACE.relatedSpdxElement, SPDX_NAMESPACE.none)) + elif isinstance(relationship.related_spdx_element_id, SpdxNoAssertion): + graph.add((relationship_node, SPDX_NAMESPACE.relatedSpdxElement, SPDX_NAMESPACE.noassertion)) + else: + graph.add( + ( + relationship_node, + SPDX_NAMESPACE.relatedSpdxElement, + URIRef( + add_namespace_to_spdx_id( + relationship.related_spdx_element_id, doc_namespace, external_doc_ref_to_namespace + ) + ), + ) + ) + if relationship.comment: + graph.add((relationship_node, RDFS.comment, Literal(relationship.comment))) + relationship_resource = URIRef( + add_namespace_to_spdx_id(relationship.spdx_element_id, doc_namespace, external_doc_ref_to_namespace) + ) + graph.add((relationship_resource, SPDX_NAMESPACE.relationship, relationship_node)) diff --git a/src/spdx_tools/spdx/writer/rdf/snippet_writer.py b/src/spdx_tools/spdx/writer/rdf/snippet_writer.py new file mode 100644 index 000000000..0b8cd4e95 --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/snippet_writer.py @@ -0,0 +1,65 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict, Optional, Tuple +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef + +from spdx_tools.spdx.model import Snippet +from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal + + +def add_snippet_to_graph( + snippet: Snippet, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str] +): + snippet_resource = URIRef(add_namespace_to_spdx_id(snippet.spdx_id, doc_namespace, external_doc_ref_to_namespace)) + graph.add((snippet_resource, RDF.type, SPDX_NAMESPACE.Snippet)) + + snippet_from_file_ref = URIRef( + add_namespace_to_spdx_id(snippet.file_spdx_id, doc_namespace, external_doc_ref_to_namespace) + ) + graph.add((snippet_resource, SPDX_NAMESPACE.snippetFromFile, snippet_from_file_ref)) + add_range_to_graph( + snippet.byte_range, graph, snippet_resource, snippet_from_file_ref, POINTER_NAMESPACE.ByteOffsetPointer + ) + add_range_to_graph( + snippet.line_range, graph, snippet_resource, snippet_from_file_ref, POINTER_NAMESPACE.LineCharPointer + ) + add_license_expression_or_none_or_no_assertion( + snippet.license_concluded, graph, snippet_resource, SPDX_NAMESPACE.licenseConcluded, doc_namespace + ) + add_license_expression_or_none_or_no_assertion( + snippet.license_info_in_snippet, graph, snippet_resource, SPDX_NAMESPACE.licenseInfoInSnippet, doc_namespace + ) + add_optional_literal(snippet.license_comment, graph, snippet_resource, SPDX_NAMESPACE.licenseComments) + add_optional_literal(snippet.copyright_text, graph, snippet_resource, SPDX_NAMESPACE.copyrightText) + add_optional_literal(snippet.comment, graph, snippet_resource, RDFS.comment) + add_optional_literal(snippet.name, graph, snippet_resource, SPDX_NAMESPACE.name) + for attribution_text in snippet.attribution_texts: + graph.add((snippet_resource, SPDX_NAMESPACE.attributionText, Literal(attribution_text))) + + +def add_range_to_graph( + range_information: Optional[Tuple[int, int]], + graph: Graph, + snippet_node: URIRef, + snippet_from_file_ref: URIRef, + pointer_class: URIRef, +): + start_end_pointer = BNode() + graph.add((start_end_pointer, RDF.type, POINTER_NAMESPACE.StartEndPointer)) + for predicate, value in [ + (POINTER_NAMESPACE.startPointer, range_information[0]), + (POINTER_NAMESPACE.endPointer, range_information[1]), + ]: + pointer_node = BNode() + graph.add((pointer_node, RDF.type, pointer_class)) + graph.add((start_end_pointer, predicate, pointer_node)) + graph.add((pointer_node, POINTER_NAMESPACE.reference, snippet_from_file_ref)) + if pointer_class == POINTER_NAMESPACE.ByteOffsetPointer: + graph.add((pointer_node, POINTER_NAMESPACE.offset, Literal(value))) + else: + graph.add((pointer_node, POINTER_NAMESPACE.lineNumber, Literal(value))) + + graph.add((snippet_node, SPDX_NAMESPACE.range, start_end_pointer)) diff --git a/src/spdx_tools/spdx/writer/rdf/writer_utils.py b/src/spdx_tools/spdx/writer/rdf/writer_utils.py new file mode 100644 index 000000000..fb27aa18b --- /dev/null +++ b/src/spdx_tools/spdx/writer/rdf/writer_utils.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import logging +from datetime import datetime + +from beartype.typing import Any, Dict, Optional +from rdflib import Graph, Literal +from rdflib.term import Node + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.validation.spdx_id_validators import is_valid_internal_spdx_id + + +def add_optional_literal(value: Any, graph: Graph, parent: Node, predicate: Node): + if value is None: + return + if isinstance(value, list): + for element in value: + graph.add((parent, predicate, Literal(str(element)))) + return + graph.add((parent, predicate, Literal(str(value)))) + + +def add_literal_or_no_assertion_or_none(value: Any, graph: Graph, parent: Node, predicate: Node): + if value is None: + return + if isinstance(value, SpdxNone): + graph.add((parent, predicate, SPDX_NAMESPACE.none)) + return + add_literal_or_no_assertion(value, graph, parent, predicate) + + +def add_literal_or_no_assertion(value: Any, graph: Graph, parent: Node, predicate: Node): + if value is None: + return + if isinstance(value, SpdxNoAssertion): + graph.add((parent, predicate, SPDX_NAMESPACE.noassertion)) + return + add_optional_literal(value, graph, parent, predicate) + + +def add_datetime_to_graph(value: Optional[datetime], graph: Graph, parent: Node, predicate: Node): + if value: + graph.add((parent, predicate, Literal(datetime_to_iso_string(value)))) + + +def add_namespace_to_spdx_id(spdx_id: str, doc_namespace: str, external_doc_namespaces: Dict[str, str]) -> str: + if ":" in spdx_id: + external_doc_ref_id = spdx_id.split(":")[0] + if external_doc_ref_id not in external_doc_namespaces.keys(): + logging.warning(f"No namespace for external document reference with id {external_doc_ref_id} provided.") + return spdx_id + return f"{external_doc_namespaces[external_doc_ref_id]}#{spdx_id.split(':')[1]}" + + if is_valid_internal_spdx_id(spdx_id): + return f"{doc_namespace}#{spdx_id}" + + return spdx_id diff --git a/src/spdx_tools/spdx/writer/tagvalue/__init__.py b/src/spdx_tools/spdx/writer/tagvalue/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py new file mode 100644 index 000000000..71637073f --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from beartype.typing import TextIO + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model import Annotation +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value + + +def write_annotation(annotation: Annotation, text_output: TextIO): + write_value("Annotator", annotation.annotator.to_serialized_string(), text_output) + write_value("AnnotationDate", datetime_to_iso_string(annotation.annotation_date), text_output) + write_value("AnnotationType", annotation.annotation_type.name, text_output) + write_value("SPDXREF", annotation.spdx_id, text_output) + write_text_value("AnnotationComment", annotation.annotation_comment, text_output) diff --git a/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py b/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py new file mode 100644 index 000000000..cf87e1a4e --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm + + +def write_checksum_to_tag_value(checksum: Checksum) -> str: + algorithm_name: str = checksum.algorithm.name + # Convert underscores to dashes, and other Blake2b-specific casing rules + if "_" in algorithm_name: + algorithm_name = CHECKSUM_ALGORITHM_TO_TV.get(algorithm_name) + if algorithm_name is None: + raise ValueError(f"Missing conversion rule for converting {checksum.algorithm.name} to tag-value string") + return f"{algorithm_name}: {checksum.value}" + + +CHECKSUM_ALGORITHM_TO_TV = { + ChecksumAlgorithm.BLAKE2B_256.name: "BLAKE2b-256", + ChecksumAlgorithm.BLAKE2B_384.name: "BLAKE2b-384", + ChecksumAlgorithm.BLAKE2B_512.name: "BLAKE2b-512", + ChecksumAlgorithm.SHA3_256.name: "SHA3-256", + ChecksumAlgorithm.SHA3_384.name: "SHA3-384", + ChecksumAlgorithm.SHA3_512.name: "SHA3-512", +} diff --git a/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py new file mode 100644 index 000000000..81fd3586c --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from beartype.typing import TextIO + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model import CreationInfo +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( + write_optional_heading, + write_separator, + write_text_value, + write_value, +) + + +def write_creation_info(creation_info: CreationInfo, text_output: TextIO): + write_value("SPDXVersion", creation_info.spdx_version, text_output) + write_value("DataLicense", creation_info.data_license, text_output) + write_value("SPDXID", creation_info.spdx_id, text_output) + write_value("DocumentName", creation_info.name, text_output) + write_value("DocumentNamespace", creation_info.document_namespace, text_output) + write_text_value("DocumentComment", creation_info.document_comment, text_output) + + write_optional_heading(creation_info.external_document_refs, "\n## External Document References\n", text_output) + for external_document_ref in creation_info.external_document_refs: + external_document_ref_str = " ".join( + [ + external_document_ref.document_ref_id, + external_document_ref.document_uri, + external_document_ref.checksum.algorithm.name + ": " + external_document_ref.checksum.value, + ] + ) + write_value("ExternalDocumentRef", external_document_ref_str, text_output) + write_separator(text_output) + + text_output.write("## Creation Information\n") + write_value("LicenseListVersion", creation_info.license_list_version, text_output) + for creator in creation_info.creators: + write_value("Creator", creator.to_serialized_string(), text_output) + write_value("Created", datetime_to_iso_string(creation_info.created), text_output) + write_text_value("CreatorComment", creation_info.creator_comment, text_output) diff --git a/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py new file mode 100644 index 000000000..0e89faa34 --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from beartype.typing import TextIO + +from spdx_tools.spdx.model import ExtractedLicensingInfo +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value + + +def write_extracted_licensing_info(extracted_licensing_info: ExtractedLicensingInfo, text_output: TextIO): + write_value("LicenseID", extracted_licensing_info.license_id, text_output) + write_text_value("ExtractedText", extracted_licensing_info.extracted_text, text_output) + write_value("LicenseName", extracted_licensing_info.license_name, text_output) + + for cross_reference in sorted(extracted_licensing_info.cross_references): + write_value("LicenseCrossReference", cross_reference, text_output) + + write_text_value("LicenseComment", extracted_licensing_info.comment, text_output) diff --git a/src/spdx_tools/spdx/writer/tagvalue/file_writer.py b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py new file mode 100644 index 000000000..0b1d8c8f5 --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from beartype.typing import TextIO + +from spdx_tools.spdx.model import File +from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value + + +def write_file(file: File, text_output: TextIO): + text_output.write("## File Information\n") + + write_value("FileName", file.name, text_output) + write_value("SPDXID", file.spdx_id, text_output) + + for file_type in file.file_types: + write_value("FileType", file_type.name, text_output) + + for file_checksum in file.checksums: + write_value("FileChecksum", write_checksum_to_tag_value(file_checksum), text_output) + + write_value("LicenseConcluded", file.license_concluded, text_output) + for license_info in file.license_info_in_file: + write_value("LicenseInfoInFile", license_info, text_output) + write_text_value("LicenseComments", file.license_comment, text_output) + write_text_value("FileCopyrightText", file.copyright_text, text_output) + + write_text_value("FileComment", file.comment, text_output) + write_text_value("FileNotice", file.notice, text_output) + + for contributor in sorted(file.contributors): + write_value("FileContributor", contributor, text_output) + + for attribution_text in file.attribution_texts: + write_text_value("FileAttributionText", attribution_text, text_output) diff --git a/src/spdx_tools/spdx/writer/tagvalue/package_writer.py b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py new file mode 100644 index 000000000..f61474fa6 --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from beartype.typing import TextIO + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model import Package, PackageVerificationCode +from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( + transform_enum_name_to_tv, + write_actor, + write_text_value, + write_value, +) + + +def write_package(package: Package, text_output: TextIO): + text_output.write("## Package Information\n") + + write_value("PackageName", package.name, text_output) + write_value("SPDXID", package.spdx_id, text_output) + write_value("PackageVersion", package.version, text_output) + write_value("PackageFileName", package.file_name, text_output) + write_actor("PackageSupplier", package.supplier, text_output) + write_actor("PackageOriginator", package.originator, text_output) + write_value("PackageDownloadLocation", package.download_location, text_output) + + write_value("FilesAnalyzed", str(package.files_analyzed).lower(), text_output) + if package.verification_code: + package_verification_code = get_package_verification_code_string(package.verification_code) + write_value("PackageVerificationCode", package_verification_code, text_output) + + for package_checksum in package.checksums: + write_value("PackageChecksum", write_checksum_to_tag_value(package_checksum), text_output) + + write_value("PackageHomePage", package.homepage, text_output) + write_text_value("PackageSourceInfo", package.source_info, text_output) + + write_value("PackageLicenseConcluded", package.license_concluded, text_output) + for license_info in package.license_info_from_files: + write_value("PackageLicenseInfoFromFiles", license_info, text_output) + write_value("PackageLicenseDeclared", package.license_declared, text_output) + write_text_value("PackageLicenseComments", package.license_comment, text_output) + write_text_value("PackageCopyrightText", package.copyright_text, text_output) + + write_text_value("PackageSummary", package.summary, text_output) + write_text_value("PackageDescription", package.description, text_output) + write_text_value("PackageComment", package.comment, text_output) + + for external_reference in package.external_references: + external_reference_str = " ".join( + [ + transform_enum_name_to_tv(external_reference.category.name), + external_reference.reference_type, + external_reference.locator, + ] + ) + write_value("ExternalRef", external_reference_str, text_output) + if external_reference.comment: + write_text_value("ExternalRefComment", external_reference.comment, text_output) + + for attribution_text in package.attribution_texts: + write_text_value("PackageAttributionText", attribution_text, text_output) + + if package.primary_package_purpose: + write_value( + "PrimaryPackagePurpose", transform_enum_name_to_tv(package.primary_package_purpose.name), text_output + ) + + if package.release_date: + write_value("ReleaseDate", datetime_to_iso_string(package.release_date), text_output) + if package.built_date: + write_value("BuiltDate", datetime_to_iso_string(package.built_date), text_output) + if package.valid_until_date: + write_value("ValidUntilDate", datetime_to_iso_string(package.valid_until_date), text_output) + + +def get_package_verification_code_string(verification_code: PackageVerificationCode) -> str: + if not verification_code.excluded_files: + return verification_code.value + + excluded_files_str = " (excludes: " + " ".join(verification_code.excluded_files) + ")" + return verification_code.value + excluded_files_str diff --git a/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py new file mode 100644 index 000000000..446bc6fd9 --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from beartype.typing import TextIO + +from spdx_tools.spdx.model import Relationship +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value + + +def write_relationship(relationship: Relationship, text_output: TextIO): + write_value( + "Relationship", + " ".join( + [ + relationship.spdx_element_id, + relationship.relationship_type.name, + str(relationship.related_spdx_element_id), + ] + ), + text_output, + ) + write_text_value("RelationshipComment", relationship.comment, text_output) diff --git a/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py new file mode 100644 index 000000000..f6449951f --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from beartype.typing import TextIO + +from spdx_tools.spdx.model import Snippet +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range, write_text_value, write_value + + +def write_snippet(snippet: Snippet, text_output: TextIO): + text_output.write("## Snippet Information\n") + + write_value("SnippetSPDXID", snippet.spdx_id, text_output) + write_value("SnippetFromFileSPDXID", snippet.file_spdx_id, text_output) + write_range("SnippetByteRange", snippet.byte_range, text_output) + write_range("SnippetLineRange", snippet.line_range, text_output) + + write_value("SnippetLicenseConcluded", snippet.license_concluded, text_output) + for license_info in snippet.license_info_in_snippet: + write_value("LicenseInfoInSnippet", license_info, text_output) + write_text_value("SnippetLicenseComments", snippet.license_comment, text_output) + write_text_value("SnippetCopyrightText", snippet.copyright_text, text_output) + + write_text_value("SnippetComment", snippet.comment, text_output) + write_value("SnippetName", snippet.name, text_output) + + for attribution_text in snippet.attribution_texts: + write_text_value("SnippetAttributionText", attribution_text, text_output) diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py new file mode 100644 index 000000000..6e8de2e94 --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from beartype.typing import TextIO + +from spdx_tools.spdx.model import Document, Relationship, RelationshipType +from spdx_tools.spdx.writer.tagvalue.annotation_writer import write_annotation +from spdx_tools.spdx.writer.tagvalue.creation_info_writer import write_creation_info +from spdx_tools.spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info +from spdx_tools.spdx.writer.tagvalue.file_writer import write_file +from spdx_tools.spdx.writer.tagvalue.package_writer import write_package +from spdx_tools.spdx.writer.tagvalue.relationship_writer import write_relationship +from spdx_tools.spdx.writer.tagvalue.snippet_writer import write_snippet +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( + get_file_ids_with_contained_snippets, + scan_relationships, + write_list_of_elements, + write_optional_heading, + write_separator, +) +from spdx_tools.spdx.writer.write_utils import validate_and_deduplicate + + +def write_document_to_stream(document: Document, stream: TextIO, validate: bool = True, drop_duplicates: bool = True): + document = validate_and_deduplicate(document, validate, drop_duplicates) + write_document(document, stream) + + +def write_document_to_file(document: Document, file_name: str, validate: bool = True, drop_duplicates: bool = True): + with open(file_name, "w", encoding="utf-8") as out: + write_document_to_stream(document, out, validate, drop_duplicates) + + +def write_document(document: Document, text_output: TextIO): + relationships_to_write, contained_files_by_package_id = scan_relationships( + document.relationships, document.packages, document.files + ) + file_ids_with_contained_snippets = get_file_ids_with_contained_snippets(document.snippets, document.files) + packaged_file_ids = [file.spdx_id for files_list in contained_files_by_package_id.values() for file in files_list] + filed_snippet_ids = [ + snippet.spdx_id for snippets_list in file_ids_with_contained_snippets.values() for snippet in snippets_list + ] + + text_output.write("## Document Information\n") + write_creation_info(document.creation_info, text_output) + write_separator(text_output) + + for snippet in document.snippets: + if snippet.spdx_id not in filed_snippet_ids: + write_snippet(snippet, text_output) + write_separator(text_output) + + for file in document.files: + if file.spdx_id not in packaged_file_ids: + write_file(file, text_output) + write_separator(text_output) + if file.spdx_id in file_ids_with_contained_snippets: + write_list_of_elements( + file_ids_with_contained_snippets[file.spdx_id], write_snippet, text_output, with_separator=True + ) + + already_written_file_ids = [] # a file can belong to multiple packages but must appear only once + for package in document.packages: + write_package(package, text_output) + write_separator(text_output) + if package.spdx_id in contained_files_by_package_id: + for file in contained_files_by_package_id[package.spdx_id]: + if file.spdx_id in already_written_file_ids: + relationships_to_write.append( + Relationship(package.spdx_id, RelationshipType.CONTAINS, file.spdx_id) + ) + else: + write_file(file, text_output) + write_separator(text_output) + if file.spdx_id in file_ids_with_contained_snippets: + write_list_of_elements( + file_ids_with_contained_snippets[file.spdx_id], + write_snippet, + text_output, + with_separator=True, + ) + already_written_file_ids.append(file.spdx_id) + + write_optional_heading(document.extracted_licensing_info, "## License Information\n", text_output) + write_list_of_elements( + document.extracted_licensing_info, write_extracted_licensing_info, text_output, with_separator=True + ) + + write_optional_heading(relationships_to_write, "## Relationships\n", text_output) + write_list_of_elements(relationships_to_write, write_relationship, text_output) + write_separator(text_output) + + write_optional_heading(document.annotations, "## Annotations\n", text_output) + write_list_of_elements(document.annotations, write_annotation, text_output, with_separator=True) diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py new file mode 100644 index 000000000..98f670252 --- /dev/null +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2022 spdx contributors +# 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. +from beartype.typing import Any, Callable, Dict, List, Optional, TextIO, Tuple, Union +from license_expression import LicenseExpression + +from spdx_tools.spdx.model import ( + Actor, + File, + Package, + Relationship, + RelationshipType, + Snippet, + SpdxNoAssertion, + SpdxNone, +) + + +def write_separator(out: TextIO): + out.write("\n") + + +def write_value( + tag: str, value: Optional[Union[bool, str, SpdxNone, SpdxNoAssertion, LicenseExpression]], out: TextIO +): + if value is not None: + out.write(f"{tag}: {value}\n") + + +def write_range(tag: str, value: Optional[Tuple[int, int]], out: TextIO): + if value: + out.write(f"{tag}: {value[0]}:{value[1]}\n") + + +def write_text_value(tag: str, value: Optional[Union[str, SpdxNone, SpdxNoAssertion]], out: TextIO): + if isinstance(value, str) and "\n" in value: + out.write(f"{tag}: {value}\n") + else: + write_value(tag, value, out) + + +def transform_enum_name_to_tv(enum_str: str) -> str: + return enum_str.replace("_", "-") + + +def write_optional_heading(optional_field: Any, heading: str, text_output: TextIO): + if optional_field: + text_output.write(heading) + + +def write_list_of_elements( + list_of_elements: List[Any], + write_method: Callable[[Any, TextIO], None], + text_output: TextIO, + with_separator: bool = False, +): + for element in list_of_elements: + write_method(element, text_output) + if with_separator: + write_separator(text_output) + + +def write_actor(tag: str, element_to_write: Optional[Union[Actor, SpdxNoAssertion]], text_output: TextIO): + if isinstance(element_to_write, Actor): + write_value(tag, element_to_write.to_serialized_string(), text_output) + else: + write_value(tag, element_to_write, text_output) + + +def scan_relationships( + relationships: List[Relationship], packages: List[Package], files: List[File] +) -> Tuple[List, Dict]: + contained_files_by_package_id = dict() + relationships_to_write = [] + files_by_spdx_id = {file.spdx_id: file for file in files} + packages_spdx_ids = [package.spdx_id for package in packages] + for relationship in relationships: + if relationship.related_spdx_element_id in [SpdxNoAssertion(), SpdxNone()]: + relationships_to_write.append(relationship) + elif ( + relationship.relationship_type == RelationshipType.CONTAINS + and relationship.spdx_element_id in packages_spdx_ids + and relationship.related_spdx_element_id in files_by_spdx_id.keys() + ): + contained_files_by_package_id.setdefault(relationship.spdx_element_id, []).append( + files_by_spdx_id[relationship.related_spdx_element_id] + ) + if relationship.comment: + relationships_to_write.append(relationship) + elif ( + relationship.relationship_type == RelationshipType.CONTAINED_BY + and relationship.related_spdx_element_id in packages_spdx_ids + and relationship.spdx_element_id in files_by_spdx_id + ): + contained_files_by_package_id.setdefault(relationship.related_spdx_element_id, []).append( + files_by_spdx_id[relationship.spdx_element_id] + ) + if relationship.comment: + relationships_to_write.append(relationship) + else: + relationships_to_write.append(relationship) + + return relationships_to_write, contained_files_by_package_id + + +def get_file_ids_with_contained_snippets(snippets: List[Snippet], files: List[File]) -> Dict: + file_ids_with_contained_snippets = dict() + file_spdx_ids: List[str] = [file.spdx_id for file in files] + for snippet in snippets: + if snippet.file_spdx_id in file_spdx_ids: + file_ids_with_contained_snippets.setdefault(snippet.file_spdx_id, []).append(snippet) + + return file_ids_with_contained_snippets diff --git a/src/spdx_tools/spdx/writer/write_anything.py b/src/spdx_tools/spdx/writer/write_anything.py new file mode 100644 index 000000000..d811b35c9 --- /dev/null +++ b/src/spdx_tools/spdx/writer/write_anything.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx.formats import FileFormat, file_name_to_format +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.writer.json import json_writer +from spdx_tools.spdx.writer.rdf import rdf_writer +from spdx_tools.spdx.writer.tagvalue import tagvalue_writer +from spdx_tools.spdx.writer.xml import xml_writer +from spdx_tools.spdx.writer.yaml import yaml_writer + + +def write_file(document: Document, file_name: str, validate: bool = True): + output_format = file_name_to_format(file_name) + if output_format == FileFormat.JSON: + json_writer.write_document_to_file(document, file_name, validate) + elif output_format == FileFormat.YAML: + yaml_writer.write_document_to_file(document, file_name, validate) + elif output_format == FileFormat.XML: + xml_writer.write_document_to_file(document, file_name, validate) + elif output_format == FileFormat.TAG_VALUE: + tagvalue_writer.write_document_to_file(document, file_name, validate) + elif output_format == FileFormat.RDF_XML: + rdf_writer.write_document_to_file(document, file_name, validate) diff --git a/src/spdx_tools/spdx/writer/write_utils.py b/src/spdx_tools/spdx/writer/write_utils.py new file mode 100644 index 000000000..13a48bb80 --- /dev/null +++ b/src/spdx_tools/spdx/writer/write_utils.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + +from spdx_tools.spdx.document_utils import create_document_without_duplicates +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage + + +def validate_and_deduplicate(document: Document, validate: bool = True, drop_duplicates: bool = True) -> Document: + if validate: + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + if validation_messages: + raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") + if drop_duplicates: + document = create_document_without_duplicates(document) + return document + + +def convert(document: Document, converter: DocumentConverter) -> dict: + if converter is None: + converter = DocumentConverter() + return converter.convert(document) diff --git a/src/spdx_tools/spdx/writer/xml/__init__.py b/src/spdx_tools/spdx/writer/xml/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/writer/xml/xml_writer.py b/src/spdx_tools/spdx/writer/xml/xml_writer.py new file mode 100644 index 000000000..9be152928 --- /dev/null +++ b/src/spdx_tools/spdx/writer/xml/xml_writer.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import xmltodict +from beartype.typing import IO + +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.writer.write_utils import convert, validate_and_deduplicate + + +def write_document_to_stream( + document: Document, + stream: IO[str], + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, +): + """ + Serializes the provided document to XML and writes it to a file with the provided name. Unless validate is set + to False, validates the document before serialization. Unless a DocumentConverter instance is provided, + a new one is created. + """ + document = validate_and_deduplicate(document, validate, drop_duplicates) + document_dict = {"Document": convert(document, converter)} + xmltodict.unparse(document_dict, stream, encoding="utf-8", pretty=True) + + +def write_document_to_file( + document: Document, + file_name: str, + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, +): + with open(file_name, "w", encoding="utf-8") as out: + write_document_to_stream(document, out, validate, converter, drop_duplicates) diff --git a/src/spdx_tools/spdx/writer/yaml/__init__.py b/src/spdx_tools/spdx/writer/yaml/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx/writer/yaml/yaml_writer.py b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py new file mode 100644 index 000000000..b3e105dc6 --- /dev/null +++ b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import yaml +from beartype.typing import IO + +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.writer.write_utils import convert, validate_and_deduplicate + + +def write_document_to_stream( + document: Document, + stream: IO[str], + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, +): + """ + Serializes the provided document to yaml and writes it to a file with the provided name. Unless validate is set + to False, validates the document before serialization. Unless a DocumentConverter instance is provided, + a new one is created. + """ + document = validate_and_deduplicate(document, validate, drop_duplicates) + document_dict = convert(document, converter) + yaml.safe_dump(document_dict, stream, indent=2) + + +def write_document_to_file( + document: Document, + file_name: str, + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, +): + with open(file_name, "w", encoding="utf-8") as out: + write_document_to_stream(document, out, validate, converter, drop_duplicates) diff --git a/src/spdx_tools/spdx3/__init__.py b/src/spdx_tools/spdx3/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/__init__.py b/src/spdx_tools/spdx3/bump_from_spdx2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/actor.py b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py new file mode 100644 index 000000000..3283bf11a --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import Optional + +from beartype.typing import List + +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalIdentifierType, Organization, Person, Tool +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.actor import Actor as Spdx2_Actor +from spdx_tools.spdx.model.actor import ActorType + + +def bump_actor( + spdx2_actor: Spdx2_Actor, payload: Payload, document_namespace: str, creation_info: Optional[CreationInfo] = None +) -> str: + name: str = spdx2_actor.name + email: str = spdx2_actor.email + actor_type: ActorType = spdx2_actor.actor_type + + external_identifiers: List[ExternalIdentifier] = [] + name_without_whitespace = "".join(name.split()) + if email: + external_identifiers.append(ExternalIdentifier(ExternalIdentifierType.EMAIL, email)) + spdx_id: str = f"{document_namespace}#SPDXRef-Actor-{name_without_whitespace}-{email}" + else: + spdx_id: str = f"{document_namespace}#SPDXRef-Actor-{name_without_whitespace}" + + if spdx_id in payload.get_full_map(): # the agent/tool already exists, so we don't need to create a new one + return spdx_id + + value_dict = { + "spdx_id": spdx_id, + "creation_info": creation_info, + "name": name, + "external_identifier": external_identifiers, + } + + if actor_type == ActorType.PERSON: + agent_or_tool = Person(**value_dict) + + elif actor_type == ActorType.ORGANIZATION: + agent_or_tool = Organization(**value_dict) + + elif actor_type == ActorType.TOOL: + agent_or_tool = Tool(**value_dict) + + else: + raise ValueError(f"no conversion rule defined for ActorType {actor_type}") + + payload.add_element(agent_or_tool) + + return spdx_id diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py new file mode 100644 index 000000000..bae61160c --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from copy import deepcopy + +from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model import Annotation, AnnotationType, CreationInfo +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.model.annotation import Annotation as Spdx2_Annotation + + +def bump_annotation( + spdx2_annotation: Spdx2_Annotation, + payload: Payload, + creation_info: CreationInfo, + document_namespace: str, + counter: int, +): + spdx_id: str = "#".join([document_namespace, f"SPDXRef-Annotation-{counter}"]) + creation_info = deepcopy(creation_info) + creation_info.created = spdx2_annotation.annotation_date + + # caution: the annotator and the annotation will only share the same creation_info if the actor + # has not been previously defined + annotator = spdx2_annotation.annotator + creator_id: str = bump_actor(annotator, payload, document_namespace, creation_info) + if annotator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: + creation_info.created_by = [creator_id] + else: + print_missing_conversion( + "Annotator", + 0, + "The SPDX2 annotation is not of Type Person or Organization." + " This case leads to an invalid SPDX3 document and is currently not supported." + "https://github.com/spdx/spdx-3-model/issues/180", + ) + annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] + + payload.add_element( + Annotation( + spdx_id, + annotation_type, + creation_info=creation_info, + subject=f"{document_namespace}#{spdx2_annotation.spdx_id}", + statement=spdx2_annotation.annotation_comment, + ) + ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py b/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py new file mode 100644 index 000000000..f4b6a4bf9 --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Optional, Union + +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone + + +def handle_no_assertion_or_none(field: Union[SpdxNone, SpdxNoAssertion, str], field_name: str) -> Optional[str]: + if isinstance(field, SpdxNone): + print(f"{field_name}: Missing conversion for SpdxNone.") + return None + if isinstance(field, SpdxNoAssertion): + return None + if isinstance(field, str): + return field diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py b/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py new file mode 100644 index 000000000..ae056081f --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model import Hash, HashAlgorithm +from spdx_tools.spdx.model.checksum import Checksum as Spdx2_Checksum +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm + + +def bump_checksum(spdx2_checksum: Spdx2_Checksum) -> Hash: + algorithm: HashAlgorithm = convert_checksum_algorithm_to_hash_algorithm(spdx2_checksum.algorithm) + value: str = spdx2_checksum.value + + return Hash(algorithm, value) + + +def convert_checksum_algorithm_to_hash_algorithm(checksum_algorithm: ChecksumAlgorithm) -> HashAlgorithm: + if checksum_algorithm.name.startswith("BLAKE"): + return HashAlgorithm[checksum_algorithm.name.replace("_", "")] + if checksum_algorithm == ChecksumAlgorithm.ADLER32: + return HashAlgorithm.OTHER + return HashAlgorithm[checksum_algorithm.name] diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py new file mode 100644 index 000000000..914d12226 --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -0,0 +1,79 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List +from semantic_version import Version + +from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor +from spdx_tools.spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifierType, SpdxDocument +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.model.document import CreationInfo as Spdx2_CreationInfo + + +def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload) -> SpdxDocument: + document_namespace = spdx2_creation_info.document_namespace + spdx_id = f"{document_namespace}#{spdx2_creation_info.spdx_id}" + + print_missing_conversion("creation_info.document_namespace", 0, "https://github.com/spdx/spdx-3-model/issues/87") + + namespaces, imports = ( + zip( + *[ + bump_external_document_ref(external_document_ref) + for external_document_ref in spdx2_creation_info.external_document_refs + ] + ) + if spdx2_creation_info.external_document_refs + else ([], []) + ) + namespaces = list(namespaces) + imports = list(imports) + print_missing_conversion( + "creation_info.license_list_version", + 0, + "part of licensing profile, " "https://github.com/spdx/spdx-3-model/issues/131", + ) + creation_info = CreationInfo( + spec_version=Version("3.0.0"), + created=spdx2_creation_info.created, + created_by=[], + profile=[ProfileIdentifierType.CORE, ProfileIdentifierType.SOFTWARE, ProfileIdentifierType.LICENSING], + data_license="https://spdx.org/licenses/" + spdx2_creation_info.data_license, + ) + + # due to creators having a creation_info themselves which inherits from the document's one, + # we have to add them after the creation_info has been initialized + creator_ids: List[str] = [] + tool_ids: List[str] = [] + for creator in spdx2_creation_info.creators: + bumped_actor_id = bump_actor(creator, payload, document_namespace, creation_info) + if creator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: + creator_ids.append(bumped_actor_id) + else: + tool_ids.append(bumped_actor_id) + + if not creator_ids: + print_missing_conversion( + "Creators", + 0, + "The SPDX2 creation_info does not contain creators of Type Person or Organization." + " This case leads to an invalid SPDX3 document and is currently not supported." + "https://github.com/spdx/spdx-3-model/issues/180", + ) + + creation_info.created_by = creator_ids + creation_info.created_using = tool_ids + + return SpdxDocument( + spdx_id=spdx_id, + creation_info=creation_info, + name=spdx2_creation_info.name, + comment=spdx2_creation_info.document_comment, + element=[], + root_element=[], + imports=imports, + namespaces=namespaces, + ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py new file mode 100644 index 000000000..41360ffa4 --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Tuple + +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.model import ExternalMap, Hash, NamespaceMap +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef + + +def bump_external_document_ref(external_document_ref: ExternalDocumentRef) -> Tuple[NamespaceMap, ExternalMap]: + verified_using: List[Hash] = [bump_checksum(external_document_ref.checksum)] + + return NamespaceMap(external_document_ref.document_ref_id, external_document_ref.document_uri + "#"), ExternalMap( + external_id=f"{external_document_ref.document_ref_id}:SPDXRef-DOCUMENT", + verified_using=verified_using, + ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py new file mode 100644 index 000000000..824f95a1f --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -0,0 +1,56 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model import ExternalMap +from spdx_tools.spdx3.model.software import File +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import ExternalDocumentRef, SpdxNoAssertion +from spdx_tools.spdx.model.file import File as Spdx2_File +from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id + + +def bump_file( + spdx2_file: Spdx2_File, + payload: Payload, + document_namespace: str, + external_document_refs: List[ExternalDocumentRef], + imports: List[ExternalMap], +): + spdx_id = get_full_element_spdx_id(spdx2_file, document_namespace, external_document_refs) + if ":" in spdx2_file.spdx_id: + imports.append( + ExternalMap( + external_id=spdx2_file.spdx_id, + defining_document=f"{spdx2_file.spdx_id.split(':')[0]}:SPDXRef-DOCUMENT", + ) + ) + + integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] + print_missing_conversion( + "file.file_type", 0, "different cardinalities, " "https://github.com/spdx/spdx-3-model/issues/82" + ) + copyright_text = None + if isinstance(spdx2_file.copyright_text, str): + copyright_text = spdx2_file.copyright_text + elif isinstance(spdx2_file.copyright_text, SpdxNoAssertion): + print_missing_conversion("package2.copyright_text", 0) + print_missing_conversion( + "file.notice, file.contributors, file.license_info_in_file, file.license_comment", + 0, + "missing definition for license profile", + ) + + payload.add_element( + File( + spdx_id, + name=spdx2_file.name, + comment=spdx2_file.comment, + verified_using=integrity_methods, + copyright_text=copyright_text, + attribution_text=", ".join(spdx2_file.attribution_texts), + ) + ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py new file mode 100644 index 000000000..de5f006d3 --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py @@ -0,0 +1,89 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Union +from license_expression import AND, OR, LicenseExpression, LicenseSymbol, LicenseWithExceptionSymbol + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx3.model.licensing import ( + AnyLicenseInfo, + ConjunctiveLicenseSet, + CustomLicense, + CustomLicenseAddition, + DisjunctiveLicenseSet, + License, + LicenseAddition, + LicenseField, + ListedLicense, + ListedLicenseException, + NoAssertionLicense, + NoneLicense, + WithAdditionOperator, +) +from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion, SpdxNone + + +def bump_license_expression_or_none_or_no_assertion( + element: Union[LicenseExpression, SpdxNoAssertion, SpdxNone], + extracted_licensing_info: List[ExtractedLicensingInfo], +) -> LicenseField: + if isinstance(element, SpdxNone): + return NoneLicense() + elif isinstance(element, SpdxNoAssertion): + return NoAssertionLicense() + else: + return bump_license_expression(element, extracted_licensing_info) + + +def bump_license_expression( + license_expression: LicenseExpression, extracted_licensing_info: List[ExtractedLicensingInfo] +) -> AnyLicenseInfo: + if isinstance(license_expression, AND): + return ConjunctiveLicenseSet( + member=[bump_license_expression(element, extracted_licensing_info) for element in license_expression.args] + ) + if isinstance(license_expression, OR): + return DisjunctiveLicenseSet( + member=[bump_license_expression(element, extracted_licensing_info) for element in license_expression.args] + ) + if isinstance(license_expression, LicenseWithExceptionSymbol): + subject_license = bump_license_expression(license_expression.license_symbol, extracted_licensing_info) + if not isinstance(subject_license, License): + raise ValueError("Subject of LicenseException couldn't be converted to License.") + return WithAdditionOperator( + subject_license=subject_license, + subject_addition=bump_license_exception(license_expression.exception_symbol, extracted_licensing_info), + ) + if isinstance(license_expression, LicenseSymbol): + if not spdx_licensing.validate(license_expression).invalid_symbols: + return ListedLicense(license_expression.key, license_expression.obj, "blank") + else: + for licensing_info in extracted_licensing_info: + if licensing_info.license_id == license_expression.key: + # the fields are optional in ExtractedLicensingInfo, to prevent type errors we use a type + # conversion to str as a quick fix + return CustomLicense( + str(licensing_info.license_id), + str(licensing_info.license_name), + str(licensing_info.extracted_text), + ) + + return CustomLicense(license_expression.key, "", "") + + +def bump_license_exception( + license_exception: LicenseSymbol, extracted_licensing_info: List[ExtractedLicensingInfo] +) -> LicenseAddition: + if not spdx_licensing.validate(license_exception).invalid_symbols: + return ListedLicenseException(license_exception.key, "", "") + else: + for licensing_info in extracted_licensing_info: + if licensing_info.license_id == license_exception.key: + # the fields are optional in ExtractedLicensingInfo, to prevent type errors we use a type conversion + # to str as a quick fix + return CustomLicenseAddition( + str(licensing_info.license_id), + str(licensing_info.license_name), + str(licensing_info.extracted_text), + ) + return CustomLicenseAddition(license_exception.key, "", "") diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/message.py b/src/spdx_tools/spdx3/bump_from_spdx2/message.py new file mode 100644 index 000000000..6351fce89 --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/message.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import sys + +MISSING_CONVERSION_REASONS = {0: "missing conversion rule", 1: "missing implementation"} + + +def print_missing_conversion(field: str, reason, additional_information: str = ""): + print(f"{field} not converted: {MISSING_CONVERSION_REASONS[reason]} {additional_information}", file=sys.stderr) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py new file mode 100644 index 000000000..3d358babd --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -0,0 +1,155 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional, Union + +from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor +from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model import ( + ExternalIdentifier, + ExternalIdentifierType, + ExternalMap, + ExternalReference, + ExternalReferenceType, +) +from spdx_tools.spdx3.model.software import Package, SoftwarePurpose +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import Actor as Spdx2_Actor +from spdx_tools.spdx.model import ExternalDocumentRef, SpdxNoAssertion +from spdx_tools.spdx.model.package import ExternalPackageRef +from spdx_tools.spdx.model.package import Package as Spdx2_Package +from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id + + +def bump_package( + spdx2_package: Spdx2_Package, + payload: Payload, + document_namespace: str, + external_document_refs: List[ExternalDocumentRef], + imports: List[ExternalMap], +): + spdx_id = get_full_element_spdx_id(spdx2_package, document_namespace, external_document_refs) + if ":" in spdx2_package.spdx_id: + imports.append( + ExternalMap( + external_id=spdx2_package.spdx_id, + defining_document=f"{spdx2_package.spdx_id.split(':')[0]}:SPDXRef-DOCUMENT", + ) + ) + + download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") + print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83") + if isinstance(spdx2_package.supplier, Spdx2_Actor): + supplied_by_spdx_id = [bump_actor(spdx2_package.supplier, payload, document_namespace)] + else: + supplied_by_spdx_id = None + if isinstance(spdx2_package.originator, Spdx2_Actor): + originated_by_spdx_id = [bump_actor(spdx2_package.originator, payload, document_namespace)] + else: + originated_by_spdx_id = None + print_missing_conversion("package2.files_analyzed", 0, "https://github.com/spdx/spdx-3-model/issues/84") + print_missing_conversion( + "package2.verification_code", 1, "of IntegrityMethod, https://github.com/spdx/spdx-3-model/issues/85" + ) + integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums] + copyright_text = None + if isinstance(spdx2_package.copyright_text, str): + copyright_text = spdx2_package.copyright_text + elif isinstance(spdx2_package.copyright_text, SpdxNoAssertion): + print_missing_conversion("package2.copyright_text", 0) + print_missing_conversion( + "package2.license_info_from_files, package2.license_comment", + 0, + "and missing definition of license profile", + ) + + external_reference = [] + external_identifier = [] + purl_refs = [ + external_ref for external_ref in spdx2_package.external_references if external_ref.reference_type == "purl" + ] + exactly_one_purl_without_comment = len(purl_refs) == 1 and purl_refs[0].comment is None + package_url = None + if exactly_one_purl_without_comment: + package_url = purl_refs[0].locator + for spdx2_external_ref in spdx2_package.external_references: + if exactly_one_purl_without_comment and spdx2_external_ref.reference_type == "purl": + continue + id_or_ref = bump_external_package_ref(spdx2_external_ref) + if isinstance(id_or_ref, ExternalReference): + external_reference.append(id_or_ref) + elif isinstance(id_or_ref, ExternalIdentifier): + external_identifier.append(id_or_ref) + + package_purpose = ( + SoftwarePurpose[spdx2_package.primary_package_purpose.name] if spdx2_package.primary_package_purpose else None + ) + + payload.add_element( + Package( + spdx_id, + spdx2_package.name, + summary=spdx2_package.summary, + description=spdx2_package.description, + comment=spdx2_package.comment, + verified_using=integrity_methods, + external_reference=external_reference, + external_identifier=external_identifier, + originated_by=originated_by_spdx_id, + supplied_by=supplied_by_spdx_id, + built_time=spdx2_package.built_date, + release_time=spdx2_package.release_date, + valid_until_time=spdx2_package.valid_until_date, + primary_purpose=package_purpose, + package_version=spdx2_package.version, + download_location=download_location, + package_url=package_url, + homepage=spdx2_package.homepage, + source_info=spdx2_package.source_info, + copyright_text=copyright_text, + attribution_text=", ".join(spdx2_package.attribution_texts), + ) + ) + + +external_ref_type_map = { + "cpe22Type": ExternalIdentifierType.CPE22, + "cpe23Type": ExternalIdentifierType.CPE23, + "advisory": ExternalReferenceType.SECURITY_ADVISORY, + "fix": ExternalReferenceType.SECURITY_FIX, + "url": None, + "swid": ExternalIdentifierType.SWID, + "maven-central": None, + "npm": None, + "nuget": None, + "bower": None, + "purl": ExternalIdentifierType.PURL, + "swh": ExternalIdentifierType.SWHID, + "gitoid": ExternalIdentifierType.GITOID, +} + + +def bump_external_package_ref( + spdx2_external_ref: ExternalPackageRef, +) -> Optional[Union[ExternalReference, ExternalIdentifier]]: + reference_type = spdx2_external_ref.reference_type + locator = spdx2_external_ref.locator + comment = spdx2_external_ref.comment + + if reference_type not in external_ref_type_map: + print_missing_conversion( + reference_type, + 0, + f"Conversion of ExternalPackageRef of type {reference_type} is currently not supported." + f"https://github.com/spdx/spdx-3-model/issues/81", + ) + return None + + id_or_ref_type = external_ref_type_map[reference_type] + + if isinstance(id_or_ref_type, ExternalReferenceType): + return ExternalReference(id_or_ref_type, [locator], None, comment) + elif isinstance(id_or_ref_type, ExternalIdentifierType): + return ExternalIdentifier(id_or_ref_type, locator, comment) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py new file mode 100644 index 000000000..918cbdafb --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -0,0 +1,259 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import logging +import sys + +from beartype.typing import Dict, List, Optional, Tuple, Union + +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model import LifecycleScopeType, Relationship, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.model.software import ( + DependencyConditionalityType, + SoftwareDependencyLinkType, + SoftwareDependencyRelationship, +) +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.relationship import Relationship as Spdx2_Relationship +from spdx_tools.spdx.model.relationship import RelationshipType as Spdx2_RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone + +# bump relationship type, map each relationship type to the corresponding class in 3.0, +# the relationship type, other arguments and if swapped +relationship_mapping: Dict[ + Spdx2_RelationshipType, + Tuple[ + Union[Relationship, SoftwareDependencyRelationship], + RelationshipType, + Dict[str, Union[bool, LifecycleScopeType, SoftwareDependencyLinkType, DependencyConditionalityType]], + ], +] = { + Spdx2_RelationshipType.AMENDS: (Relationship, RelationshipType.AMENDS, {}), + Spdx2_RelationshipType.ANCESTOR_OF: (Relationship, RelationshipType.ANCESTOR, {}), + Spdx2_RelationshipType.BUILD_DEPENDENCY_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + { + "scope": LifecycleScopeType.BUILD, + "linkage": SoftwareDependencyLinkType.TOOL, + }, + ), + Spdx2_RelationshipType.BUILD_TOOL_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"scope": LifecycleScopeType.BUILD, "linkage": SoftwareDependencyLinkType.TOOL}, + ), + Spdx2_RelationshipType.CONTAINED_BY: (Relationship, RelationshipType.CONTAINS, {"swap": True}), + Spdx2_RelationshipType.CONTAINS: ( + Relationship, + RelationshipType.CONTAINS, + {}, + ), # might be deleted in favor of depends on + Spdx2_RelationshipType.COPY_OF: (Relationship, RelationshipType.COPY, {}), + Spdx2_RelationshipType.DATA_FILE_OF: (None, None, {}), # not defined, probably input/ output + Spdx2_RelationshipType.DEPENDENCY_MANIFEST_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {}, + ), # "expect purpose has been set to manifest" + Spdx2_RelationshipType.DEPENDENCY_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"swap": True}, + ), + Spdx2_RelationshipType.DEPENDS_ON: (SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, {}), + Spdx2_RelationshipType.DESCENDANT_OF: (Relationship, RelationshipType.ANCESTOR, {"swap": True}), + Spdx2_RelationshipType.DESCRIBED_BY: (Relationship, RelationshipType.DESCRIBES, {"swap": True}), + Spdx2_RelationshipType.DESCRIBES: ( + Relationship, + RelationshipType.DESCRIBES, + {}, + ), # might be deleted in favor of root + # property + Spdx2_RelationshipType.DEV_DEPENDENCY_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"scope": LifecycleScopeType.DEVELOPMENT}, + ), + Spdx2_RelationshipType.DEV_TOOL_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"scope": LifecycleScopeType.DEVELOPMENT, "linkage": SoftwareDependencyLinkType.TOOL}, + ), + Spdx2_RelationshipType.DISTRIBUTION_ARTIFACT: (None, None, {}), # not defined yet, purpose? + Spdx2_RelationshipType.DOCUMENTATION_OF: (Relationship, RelationshipType.DOCUMENTATION, {}), + Spdx2_RelationshipType.DYNAMIC_LINK: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"linkage": SoftwareDependencyLinkType.DYNAMIC}, + ), + Spdx2_RelationshipType.EXAMPLE_OF: (Relationship, RelationshipType.EXAMPLE, {}), + Spdx2_RelationshipType.EXPANDED_FROM_ARCHIVE: (Relationship, RelationshipType.EXPANDED_FROM_ARCHIVE, {}), + Spdx2_RelationshipType.FILE_ADDED: (Relationship, RelationshipType.FILE_ADDED, {}), + Spdx2_RelationshipType.FILE_DELETED: (Relationship, RelationshipType.FILE_DELETED, {}), + Spdx2_RelationshipType.FILE_MODIFIED: (Relationship, RelationshipType.FILE_MODIFIED, {}), + Spdx2_RelationshipType.GENERATED_FROM: (Relationship, RelationshipType.GENERATES, {"swap": True}), + Spdx2_RelationshipType.GENERATES: (Relationship, RelationshipType.GENERATES, {}), + Spdx2_RelationshipType.HAS_PREREQUISITE: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"conditionality": DependencyConditionalityType.PREREQUISITE}, + ), + Spdx2_RelationshipType.METAFILE_OF: (Relationship, RelationshipType.METAFILE, {}), + Spdx2_RelationshipType.OPTIONAL_COMPONENT_OF: (None, None, {}), # converted to depends on and purpose? not clear + Spdx2_RelationshipType.OPTIONAL_DEPENDENCY_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"conditionality": DependencyConditionalityType.OPTIONAL}, + ), + Spdx2_RelationshipType.OTHER: (Relationship, RelationshipType.OTHER, {}), + Spdx2_RelationshipType.PACKAGE_OF: (SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, {}), + Spdx2_RelationshipType.PATCH_APPLIED: (Relationship, RelationshipType.PATCH, {"swap": True}), + Spdx2_RelationshipType.PATCH_FOR: (Relationship, RelationshipType.PATCH, {}), + Spdx2_RelationshipType.PREREQUISITE_FOR: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"conditionality": DependencyConditionalityType.PREREQUISITE}, + ), + Spdx2_RelationshipType.PROVIDED_DEPENDENCY_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"scope": LifecycleScopeType.BUILD, "conditionality": DependencyConditionalityType.PROVIDED}, + ), + Spdx2_RelationshipType.RUNTIME_DEPENDENCY_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"scope": LifecycleScopeType.RUNTIME}, + ), + Spdx2_RelationshipType.STATIC_LINK: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"linkage": SoftwareDependencyLinkType.STATIC}, + ), + Spdx2_RelationshipType.TEST_CASE_OF: (Relationship, RelationshipType.TEST_CASE, {}), + Spdx2_RelationshipType.TEST_DEPENDENCY_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"scope": LifecycleScopeType.TEST}, + ), + Spdx2_RelationshipType.TEST_OF: (Relationship, RelationshipType.TEST, {}), + Spdx2_RelationshipType.TEST_TOOL_OF: ( + SoftwareDependencyRelationship, + RelationshipType.DEPENDS_ON, + {"scope": LifecycleScopeType.TEST, "linkage": SoftwareDependencyLinkType.TOOL}, + ), + Spdx2_RelationshipType.VARIANT_OF: (Relationship, RelationshipType.VARIANT, {}), + Spdx2_RelationshipType.REQUIREMENT_DESCRIPTION_FOR: (Relationship, RelationshipType.REQUIREMENT_FOR, {}), + Spdx2_RelationshipType.SPECIFICATION_FOR: (Relationship, RelationshipType.SPECIFICATION_FOR, {}), +} + + +def bump_relationships( + spdx2_relationships: List[Spdx2_Relationship], + payload: Payload, + document_namespace: str, +): + generated_relationships: Dict[Tuple[str, str], List[Relationship]] = {} + for counter, spdx2_relationship in enumerate(spdx2_relationships): + relationship = bump_relationship(spdx2_relationship, document_namespace, counter) + if relationship: + generated_relationships.setdefault( + (relationship.from_element, relationship.relationship_type.name), [] + ).append(relationship) + + for relationships in generated_relationships.values(): + if len(relationships) > 1: + _merge_relationships_and_add_to_payload(relationships, payload) + else: + payload.add_element(relationships[0]) + + +def bump_relationship( + spdx2_relationship: Spdx2_Relationship, + document_namespace: str, + counter: int, +) -> Optional[Union[Relationship, SoftwareDependencyRelationship]]: + completeness, to = determine_completeness_and_to(spdx2_relationship.related_spdx_element_id) + spdx_id = "#".join([document_namespace, f"SPDXRef-Relationship-{counter}"]) + relationship_class, relationship_type, parameters = relationship_mapping[spdx2_relationship.relationship_type] + if relationship_class is None: + print_missing_conversion(spdx2_relationship.relationship_type.name, 0) + return + + swap_direction = parameters.get("swap", False) + + if swap_direction: + if not to: + print_missing_conversion("Swapped Relationship to NoAssertion/None", 0) + return + from_element = to[0] + to = [spdx2_relationship.spdx_element_id] + else: + from_element = spdx2_relationship.spdx_element_id + + if relationship_class == SoftwareDependencyRelationship: + from_element = spdx2_relationship.spdx_element_id + + return SoftwareDependencyRelationship( + spdx_id, + f"{document_namespace}#{from_element}", + relationship_type, + [f"{document_namespace}#{t}" for t in to], + comment=spdx2_relationship.comment, + completeness=completeness, + scope=parameters.get("scope"), + software_linkage=parameters.get("linkage"), + conditionality=parameters.get("conditionality"), + ) + + return Relationship( + spdx_id, + f"{document_namespace}#{from_element}", + relationship_type, + [f"{document_namespace}#{t}" for t in to], + comment=spdx2_relationship.comment, + completeness=completeness, + ) + + +def determine_completeness_and_to( + related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion] +) -> Tuple[Optional[RelationshipCompleteness], List[str]]: + if isinstance(related_spdx_element_id, SpdxNoAssertion): + completeness = RelationshipCompleteness.NOASSERTION + to = [] + elif isinstance(related_spdx_element_id, SpdxNone): + completeness = RelationshipCompleteness.COMPLETE + to = [] + else: + completeness = None + to = [related_spdx_element_id] + return completeness, to + + +def _merge_relationships_and_add_to_payload(relationships: List[Relationship], payload: Payload): + to = [] + completeness = None + spdx_id = None + merged_relationship = relationships[0] + for merged_relationship in relationships: + if merged_relationship.comment: + payload.add_element(merged_relationship) + continue + if merged_relationship.completeness: + if completeness and completeness != merged_relationship.completeness: + logging.warning( + f"Contradicting information about completeness of relationship: {merged_relationship}", sys.stderr + ) + else: + completeness = merged_relationship.completeness + + to += merged_relationship.to + spdx_id = merged_relationship.spdx_id + if to: + merged_relationship.spdx_id = spdx_id + merged_relationship.to = to + merged_relationship.completeness = completeness + merged_relationship.comment = None + payload.add_element(merged_relationship) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py new file mode 100644 index 000000000..b052511c1 --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional, Tuple + +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model import ExternalMap +from spdx_tools.spdx3.model.positive_integer_range import PositiveIntegerRange +from spdx_tools.spdx3.model.software import Snippet +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import ExternalDocumentRef, SpdxNoAssertion +from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet +from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id + + +def bump_integer_range(spdx2_range: Optional[Tuple[int, int]]) -> PositiveIntegerRange: + return PositiveIntegerRange(spdx2_range[0], spdx2_range[1]) if spdx2_range else None + + +def bump_snippet( + spdx2_snippet: Spdx2_Snippet, + payload: Payload, + document_namespace: str, + external_document_refs: List[ExternalDocumentRef], + imports: List[ExternalMap], +): + spdx_id = get_full_element_spdx_id(spdx2_snippet, document_namespace, external_document_refs) + if ":" in spdx2_snippet.spdx_id: + imports.append( + ExternalMap( + external_id=spdx2_snippet.spdx_id, + defining_document=f"{spdx2_snippet.spdx_id.split(':')[0]}:SPDXRef-DOCUMENT", + ) + ) + + print_missing_conversion("snippet.file_spdx_id", 0, "https://github.com/spdx/spdx-3-model/issues/130") + copyright_text = None + if isinstance(spdx2_snippet.copyright_text, str): + copyright_text = spdx2_snippet.copyright_text + elif isinstance(spdx2_snippet.copyright_text, SpdxNoAssertion): + print_missing_conversion("package2.copyright_text", 0) + print_missing_conversion( + "snippet.license_info_in_snippet, snippet.license_comment,", + 0, + "missing definitions for license profile", + ) + + payload.add_element( + Snippet( + spdx_id=spdx_id, + name=spdx2_snippet.name, + comment=spdx2_snippet.comment, + byte_range=bump_integer_range(spdx2_snippet.byte_range), + line_range=bump_integer_range(spdx2_snippet.line_range), + copyright_text=copyright_text, + attribution_text=", ".join(spdx2_snippet.attribution_texts), + ) + ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py new file mode 100644 index 000000000..0257c403f --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.bump_from_spdx2.annotation import bump_annotation +from spdx_tools.spdx3.bump_from_spdx2.creation_info import bump_creation_info +from spdx_tools.spdx3.bump_from_spdx2.file import bump_file +from spdx_tools.spdx3.bump_from_spdx2.package import bump_package +from spdx_tools.spdx3.bump_from_spdx2.relationship import bump_relationships +from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet +from spdx_tools.spdx3.model import CreationInfo, SpdxDocument +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import RelationshipType +from spdx_tools.spdx.model.document import Document as Spdx2_Document +from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin + +""" We want to implement a bump_from_spdx2 from the data model in src.spdx to the data model in src.spdx3. + As there are many fundamental differences between these version we want each bump_from_spdx2 method to take + the object from src.spdx and add all objects that the input is translated to into the payload.""" + + +def bump_spdx_document(document: Spdx2_Document) -> Payload: + payload = Payload() + document_namespace: str = document.creation_info.document_namespace + spdx_document: SpdxDocument = bump_creation_info(document.creation_info, payload) + spdx_document.root_element = [ + f"{document_namespace}#{relationship.related_spdx_element_id}" + for relationship in filter_by_type_and_origin( + document.relationships, RelationshipType.DESCRIBES, "SPDXRef-DOCUMENT" + ) + ] + + creation_info: CreationInfo = spdx_document.creation_info + + payload.add_element(spdx_document) + + for spdx2_package in document.packages: + bump_package( + spdx2_package, + payload, + document_namespace, + document.creation_info.external_document_refs, + spdx_document.imports, + ) + + for spdx2_file in document.files: + bump_file( + spdx2_file, + payload, + document_namespace, + document.creation_info.external_document_refs, + spdx_document.imports, + ) + + for spdx2_snippet in document.snippets: + bump_snippet( + spdx2_snippet, + payload, + document_namespace, + document.creation_info.external_document_refs, + spdx_document.imports, + ) + + bump_relationships(document.relationships, payload, document_namespace) + + for counter, spdx2_annotation in enumerate(document.annotations): + bump_annotation(spdx2_annotation, payload, creation_info, document_namespace, counter) + + spdx_document.element = [spdx_id for spdx_id in payload.get_full_map() if spdx_id != spdx_document.spdx_id] + + return payload diff --git a/src/spdx_tools/spdx3/clitools/__init__.py b/src/spdx_tools/spdx3/clitools/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/clitools/pyspdxtools3.py b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py new file mode 100644 index 000000000..9dd21a5d1 --- /dev/null +++ b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py @@ -0,0 +1,67 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import sys + +import click +from beartype.typing import List + +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.console.payload_writer import write_payload as write_payload_to_console +from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.parse_anything import parse_file +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage + + +@click.command() +@click.option( + "--infile", "-i", prompt="input file path", help="The file containing the document to be validated or converted." +) +@click.option( + "--outfile", + "-o", + help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion)." + "For now only a prototype serialization to json-ld is available. The provided file will therefore be extended " + "with `.jsonld`.", +) +@click.option( + "--version", + help='The SPDX version to be used during parsing and validation (format "SPDX-2.3").', + default="SPDX-2.3", +) +@click.option("--novalidation", is_flag=True, help="Don't validate the provided document.") +def main(infile: str, outfile: str, version: str, novalidation: bool): + """ + CLI-tool to parse and validate a SPDX 2.x document and migrate it into the prototype of SPDX 3.0. As there is no + definition for a serialization yet output can only be written to stdout. + To use, run: 'pyspdxtools3 --infile -o -' + """ + try: + document: Document = parse_file(infile) + + if not novalidation: + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document, version) + if validation_messages: + print("The document is invalid. The following issues have been found:", file=sys.stderr) + for message in validation_messages: + print(message.validation_message, file=sys.stderr) + sys.exit(1) + else: + print("The document is valid.", file=sys.stderr) + if outfile: + payload: Payload = bump_spdx_document(document) + if outfile == "-": + write_payload_to_console(payload, sys.stdout) + else: + write_payload(payload, outfile) + + except NotImplementedError as err: + print(err.args[0]) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/src/spdx_tools/spdx3/model/__init__.py b/src/spdx_tools/spdx3/model/__init__.py new file mode 100644 index 000000000..8fab45e9e --- /dev/null +++ b/src/spdx_tools/spdx3/model/__init__.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model.profile_identifier import ProfileIdentifierType +from spdx_tools.spdx3.model.creation_info import CreationInfo +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm +from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model.agent import Agent +from spdx_tools.spdx3.model.person import Person +from spdx_tools.spdx3.model.organization import Organization +from spdx_tools.spdx3.model.software_agent import SoftwareAgent +from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.model.spdx_collection import ElementCollection +from spdx_tools.spdx3.model.bundle import Bundle +from spdx_tools.spdx3.model.bom import Bom +from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness +from spdx_tools.spdx3.model.lifecycle_scoped_relationship import LifecycleScopedRelationship, LifecycleScopeType +from spdx_tools.spdx3.model.artifact import Artifact diff --git a/src/spdx_tools/spdx3/model/agent.py b/src/spdx_tools/spdx3/model/agent.py new file mode 100644 index 000000000..9aa326e22 --- /dev/null +++ b/src/spdx_tools/spdx3/model/agent.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod + + +@dataclass_with_properties +class Agent(Element): + def __init__( + self, + spdx_id: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/ai/__init__.py b/src/spdx_tools/spdx3/model/ai/__init__.py new file mode 100644 index 000000000..1f711abf6 --- /dev/null +++ b/src/spdx_tools/spdx3/model/ai/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model.ai.ai_package import AIPackage diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py new file mode 100644 index 000000000..b297385e3 --- /dev/null +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -0,0 +1,102 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime +from enum import Enum, auto + +from beartype.typing import Dict, List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField +from spdx_tools.spdx3.model.software import Package, SoftwarePurpose + + +class SafetyRiskAssessmentType(Enum): + SERIOUS = auto() + HIGH = auto() + MEDIUM = auto() + LOW = auto() + + +@dataclass_with_properties +class AIPackage(Package): + energy_consumption: Optional[str] = None + standard_compliance: List[str] = field(default_factory=list) + limitation: Optional[str] = None + type_of_model: List[str] = field(default_factory=list) + information_about_training: Optional[str] = None + information_about_application: Optional[str] = None + hyperparameter: Dict[str, Optional[str]] = field(default_factory=dict) + model_data_preprocessing: List[str] = field(default_factory=list) + model_explainability: List[str] = field(default_factory=list) + sensitive_personal_information: Optional[bool] = None + metric_decision_threshold: Dict[str, Optional[str]] = field(default_factory=dict) + metric: Dict[str, Optional[str]] = field(default_factory=dict) + domain: List[str] = field(default_factory=list) + autonomy_type: Optional[bool] = None + safety_risk_assessment: Optional[SafetyRiskAssessmentType] = None + + def __init__( + self, + spdx_id: str, + name: str, + supplied_by: List[str], + download_location: str, + package_version: str, + primary_purpose: SoftwarePurpose, + release_time: datetime, + creation_info: Optional[CreationInfo] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + originated_by: List[str] = None, + built_time: Optional[datetime] = None, + valid_until_time: Optional[datetime] = None, + standard: List[str] = None, + content_identifier: Optional[str] = None, + additional_purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, + package_url: Optional[str] = None, + homepage: Optional[str] = None, + source_info: Optional[str] = None, + energy_consumption: Optional[str] = None, + standard_compliance: List[str] = None, + limitation: Optional[str] = None, + type_of_model: List[str] = None, + information_about_training: Optional[str] = None, + information_about_application: Optional[str] = None, + hyperparameter: Dict[str, Optional[str]] = None, + model_data_preprocessing: List[str] = None, + model_explainability: List[str] = None, + sensitive_personal_information: Optional[bool] = None, + metric_decision_threshold: Dict[str, Optional[str]] = None, + metric: Dict[str, Optional[str]] = None, + domain: List[str] = None, + autonomy_type: Optional[bool] = None, + safety_risk_assessment: Optional[SafetyRiskAssessmentType] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + originated_by = [] if originated_by is None else originated_by + additional_purpose = [] if additional_purpose is None else additional_purpose + standard = [] if standard is None else standard + standard_compliance = [] if standard_compliance is None else standard_compliance + type_of_model = [] if type_of_model is None else type_of_model + hyperparameter = {} if hyperparameter is None else hyperparameter + model_data_preprocessing = [] if model_data_preprocessing is None else model_data_preprocessing + model_explainability = [] if model_explainability is None else model_explainability + metric_decision_threshold = {} if metric_decision_threshold is None else metric_decision_threshold + metric = {} if metric is None else metric + domain = [] if domain is None else domain + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py new file mode 100644 index 000000000..e74d9d578 --- /dev/null +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod + + +class AnnotationType(Enum): + REVIEW = auto() + OTHER = auto() + + +@dataclass_with_properties +class Annotation(Element): + annotation_type: AnnotationType = None + subject: str = None + content_type: List[str] = field(default_factory=list) # placeholder for MediaType + statement: Optional[str] = None + + def __init__( + self, + spdx_id: str, + annotation_type: AnnotationType, + subject: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + content_type: List[str] = None, + statement: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + content_type = [] if content_type is None else content_type + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/artifact.py b/src/spdx_tools/spdx3/model/artifact.py new file mode 100644 index 000000000..0fccec89c --- /dev/null +++ b/src/spdx_tools/spdx3/model/artifact.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import abstractmethod +from dataclasses import field +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model import Element + + +@dataclass_with_properties +class Artifact(Element): + originated_by: List[str] = field(default_factory=list) # SPDXID of the Agent/Tool + supplied_by: List[str] = field(default_factory=list) # SPDXID of the Agent/Tool + built_time: Optional[datetime] = None + release_time: Optional[datetime] = None + valid_until_time: Optional[datetime] = None + standard: List[str] = field(default_factory=list) + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py new file mode 100644 index 000000000..a9ad7d57e --- /dev/null +++ b/src/spdx_tools/spdx3/model/bom.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Bundle, + CreationInfo, + ExternalIdentifier, + ExternalMap, + ExternalReference, + IntegrityMethod, + NamespaceMap, +) + + +@dataclass_with_properties +class Bom(Bundle): + # We overwrite the super-__init__ as check_types_and_set_values() + # takes care of all fields (including inherited ones). + + def __init__( + self, + spdx_id: str, + element: List[str], + root_element: List[str], + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + namespaces: List[NamespaceMap] = None, + imports: List[ExternalMap] = None, + context: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/build/__init__.py b/src/spdx_tools/spdx3/model/build/__init__.py new file mode 100644 index 000000000..765cf3c2a --- /dev/null +++ b/src/spdx_tools/spdx3/model/build/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model.build.build import Build diff --git a/src/spdx_tools/spdx3/model/build/build.py b/src/spdx_tools/spdx3/model/build/build.py new file mode 100644 index 000000000..c6662ccce --- /dev/null +++ b/src/spdx_tools/spdx3/model/build/build.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime + +from beartype.typing import Dict, List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, Hash, IntegrityMethod + + +@dataclass_with_properties +class Build(Element): + build_type: str = None + build_id: Optional[str] = None + config_source_entrypoint: List[str] = field(default_factory=list) + config_source_uri: List[str] = field(default_factory=list) + config_source_digest: List[Hash] = field(default_factory=list) + parameters: Dict[str, str] = field(default_factory=dict) + build_start_time: Optional[datetime] = None + build_end_time: Optional[datetime] = None + environment: Dict[str, str] = field(default_factory=dict) + + def __init__( + self, + spdx_id: str, + build_type: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + build_id: Optional[str] = None, + config_source_entrypoint: List[str] = None, + config_source_uri: List[str] = None, + config_source_digest: List[Hash] = None, + parameters: Dict[str, str] = None, + build_start_time: Optional[datetime] = None, + build_end_time: Optional[datetime] = None, + environment: Dict[str, str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + config_source_entrypoint = [] if config_source_entrypoint is None else config_source_entrypoint + config_source_uri = [] if config_source_uri is None else config_source_uri + config_source_digest = [] if config_source_digest is None else config_source_digest + parameters = {} if parameters is None else parameters + environment = {} if environment is None else environment + + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py new file mode 100644 index 000000000..63640f845 --- /dev/null +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ElementCollection, + ExternalIdentifier, + ExternalMap, + ExternalReference, + IntegrityMethod, + NamespaceMap, +) + + +@dataclass_with_properties +class Bundle(ElementCollection): + context: Optional[str] = None + + def __init__( + self, + spdx_id: str, + element: List[str], + root_element: List[str], + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + namespaces: List[NamespaceMap] = None, + imports: List[ExternalMap] = None, + context: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/creation_info.py b/src/spdx_tools/spdx3/model/creation_info.py new file mode 100644 index 000000000..125d4d30d --- /dev/null +++ b/src/spdx_tools/spdx3/model/creation_info.py @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime + +from beartype.typing import List, Optional +from semantic_version import Version + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ProfileIdentifierType + + +@dataclass_with_properties +class CreationInfo: + spec_version: Version + created: datetime + created_by: List[str] # SPDXID of Agents + profile: List[ProfileIdentifierType] + data_license: Optional[str] = "CC0-1.0" + created_using: List[str] = field(default_factory=list) # SPDXID of Tools + comment: Optional[str] = None + + def __init__( + self, + spec_version: Version, + created: datetime, + created_by: List[str], + profile: List[ProfileIdentifierType], + data_license: Optional[str] = "CC0-1.0", + created_using: List[str] = None, + comment: Optional[str] = None, + ): + created_using = [] if created_using is None else created_using + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/dataset/__init__.py b/src/spdx_tools/spdx3/model/dataset/__init__.py new file mode 100644 index 000000000..5e2b4e153 --- /dev/null +++ b/src/spdx_tools/spdx3/model/dataset/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model.dataset.dataset import Dataset, DatasetAvailabilityType, ConfidentialityLevelType diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py new file mode 100644 index 000000000..bbb82cc3a --- /dev/null +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -0,0 +1,120 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime +from enum import Enum, auto + +from beartype.typing import Dict, List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField +from spdx_tools.spdx3.model.software import Package, SoftwarePurpose + + +class DatasetType(Enum): + STRUCTURED = auto() + NUMERIC = auto() + TEXT = auto() + CATEGORICAL = auto() + GRAPH = auto() + TIMESERIES = auto() + TIMESTAMP = auto() + SENSOR = auto() + IMAGE = auto() + SYNTACTIC = auto() + AUDIO = auto() + VIDEO = auto() + OTHER = auto() + NO_ASSERTION = auto() + + +class ConfidentialityLevelType(Enum): + RED = auto() + AMBER = auto() + GREEN = auto() + CLEAR = auto() + + +class DatasetAvailabilityType(Enum): + DIRECT_DOWNLOAD = auto() + SCRAPING_SCRIPT = auto() + QUERY = auto() + CLICKTHROUGH = auto() + REGISTRATION = auto() + + +@dataclass_with_properties +class Dataset(Package): + dataset_type: List[DatasetType] = None + data_collection_process: Optional[str] = None + intended_use: Optional[str] = None + dataset_size: Optional[int] = None + dataset_noise: Optional[str] = None + data_preprocessing: List[str] = field(default_factory=list) + sensor: Dict[str, Optional[str]] = field(default_factory=dict) + known_bias: List[str] = field(default_factory=list) + sensitive_personal_information: Optional[bool] = None + anonymization_method_used: List[str] = field(default_factory=list) + confidentiality_level: Optional[ConfidentialityLevelType] = None + dataset_update_mechanism: Optional[str] = None + dataset_availability: Optional[DatasetAvailabilityType] = None + + def __init__( + self, + spdx_id: str, + name: str, + originated_by: List[str], + download_location: str, + primary_purpose: SoftwarePurpose, + built_time: datetime, + release_time: datetime, + dataset_type: List[DatasetType], + creation_info: Optional[CreationInfo] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + supplied_by: List[str] = None, + valid_until_time: Optional[datetime] = None, + standard: List[str] = None, + content_identifier: Optional[str] = None, + additional_purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, + package_version: Optional[str] = None, + package_url: Optional[str] = None, + homepage: Optional[str] = None, + source_info: Optional[str] = None, + data_collection_process: Optional[str] = None, + intended_use: Optional[str] = None, + dataset_size: Optional[int] = None, + dataset_noise: Optional[str] = None, + data_preprocessing: List[str] = None, + sensor: Dict[str, Optional[str]] = None, + known_bias: List[str] = None, + sensitive_personal_information: Optional[bool] = None, + anonymization_method_used: List[str] = None, + confidentiality_level: Optional[ConfidentialityLevelType] = None, + dataset_update_mechanism: Optional[str] = None, + dataset_availability: Optional[DatasetAvailabilityType] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + originated_by = [] if originated_by is None else originated_by + additional_purpose = [] if additional_purpose is None else additional_purpose + supplied_by = [] if supplied_by is None else supplied_by + standard = [] if standard is None else standard + data_preprocessing = [] if data_preprocessing is None else data_preprocessing + sensor = {} if sensor is None else sensor + known_bias = [] if known_bias is None else known_bias + anonymization_method_used = [] if anonymization_method_used is None else anonymization_method_used + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/element.py b/src/spdx_tools/spdx3/model/element.py new file mode 100644 index 000000000..08f2d7b85 --- /dev/null +++ b/src/spdx_tools/spdx3/model/element.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod +from dataclasses import field + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod + + +@dataclass_with_properties +class Element(ABC): + spdx_id: str # IRI + creation_info: Optional[CreationInfo] = None + name: Optional[str] = None + summary: Optional[str] = None + description: Optional[str] = None + comment: Optional[str] = None + verified_using: List[IntegrityMethod] = field(default_factory=list) + external_reference: List[ExternalReference] = field(default_factory=list) + external_identifier: List[ExternalIdentifier] = field(default_factory=list) + extension: Optional[str] = None # placeholder for extension + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/external_identifier.py b/src/spdx_tools/spdx3/model/external_identifier.py new file mode 100644 index 000000000..ee458151e --- /dev/null +++ b/src/spdx_tools/spdx3/model/external_identifier.py @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values + + +class ExternalIdentifierType(Enum): + CPE22 = auto() + CPE23 = auto() + CVE = auto() + EMAIL = auto() + GITOID = auto() + PURL = auto() + SECURITY_OTHER = auto() + SWHID = auto() + SWID = auto() + URL_SCHEME = auto() + OTHER = auto() + + +@dataclass_with_properties +class ExternalIdentifier: + external_identifier_type: ExternalIdentifierType + identifier: str + comment: Optional[str] = None + identifier_locator: List[str] = field(default_factory=list) + issuing_authority: Optional[str] = None + + def __init__( + self, + external_identifier_type: ExternalIdentifierType, + identifier: str, + comment: Optional[str] = None, + identifier_locator: List[str] = None, + issuing_authority: Optional[str] = None, + ): + identifier_locator = [] if identifier_locator is None else identifier_locator + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/external_map.py b/src/spdx_tools/spdx3/model/external_map.py new file mode 100644 index 000000000..ab88a49e2 --- /dev/null +++ b/src/spdx_tools/spdx3/model/external_map.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import IntegrityMethod + + +@dataclass_with_properties +class ExternalMap: + external_id: str # anyURI + verified_using: List[IntegrityMethod] = field(default_factory=list) + location_hint: Optional[str] = None # anyURI + defining_document: Optional[str] = None + + def __init__( + self, + external_id: str, + verified_using: List[IntegrityMethod] = None, + location_hint: Optional[str] = None, + defining_document: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/external_reference.py b/src/spdx_tools/spdx3/model/external_reference.py new file mode 100644 index 000000000..2f44a54d6 --- /dev/null +++ b/src/spdx_tools/spdx3/model/external_reference.py @@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values + + +class ExternalReferenceType(Enum): + ALT_DOWNLOAD_LOCATION = auto() + ALT_WEB_PAGE = auto() + BINARY_ARTIFACT = auto() + BUILD_META = auto() + BUILD_SYSTEM = auto() + CERTIFICATION_REPORT = auto() + CHAT = auto() + COMPONENT_ANALYSIS_REPORT = auto() + DOCUMENTATION = auto() + DYNAMIC_ANALYSIS_REPORT = auto() + EOL_NOTICE = auto() + FUNDING = auto() + ISSUE_TRACKER = auto() + LICENSE = auto() + MAILING_LIST = auto() + METRICS = auto() + OTHER = auto() + PRODUCT_METADATA = auto() + QUALITY_ASSESSMENT_REPORT = auto() + RELEASE_HISTORY = auto() + RELEASE_NOTES = auto() + RISK_ASSESSMENT = auto() + RUNTIME_ANALYSIS_REPORT = auto() + SECURE_SOFTWARE_ATTESTATION = auto() + SECURITY_ADVERSARY_MODEL = auto() + SECURITY_ADVISORY = auto() + SECURITY_FIX = auto() + SECURITY_OTHER = auto() + SECURITY_PEN_TEST_REPORT = auto() + SECURITY_POLICY = auto() + SECURITY_THREAT_MODEL = auto() + SOCIAL_MEDIA = auto() + SOURCE_ARTIFACT = auto() + STATIC_ANALYSIS_REPORT = auto() + SUPPORT = auto() + VCS = auto() + VULNERABILITY_DISCLOSURE_REPORT = auto() + VULNERABILITY_EXPLOITABILITY_ASSESSMENT = auto() + + +@dataclass_with_properties +class ExternalReference: + external_reference_type: Optional[ExternalReferenceType] = None + locator: List[str] = field(default_factory=list) + content_type: Optional[str] = None # placeholder for MediaType + comment: Optional[str] = None + + def __init__( + self, + external_reference_type: Optional[ExternalReferenceType] = None, + locator: List[str] = None, + content_type: Optional[str] = None, + comment: Optional[str] = None, + ): + locator = [] if locator is None else locator + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/hash.py b/src/spdx_tools/spdx3/model/hash.py new file mode 100644 index 000000000..42ef4ff4d --- /dev/null +++ b/src/spdx_tools/spdx3/model/hash.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto + +from beartype.typing import Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import IntegrityMethod + + +class HashAlgorithm(Enum): + BLAKE2B256 = auto() + BLAKE2B384 = auto() + BLAKE2B512 = auto() + BLAKE3 = auto() + CRYSTALS_KYBER = auto() + CRYSTALS_DILITHIUM = auto() + FALCON = auto() + MD2 = auto() + MD4 = auto() + MD5 = auto() + MD6 = auto() + OTHER = auto() + SHA1 = auto() + SHA224 = auto() + SHA256 = auto() + SHA3_224 = auto() + SHA3_256 = auto() + SHA3_384 = auto() + SHA3_512 = auto() + SHA384 = auto() + SHA512 = auto() + SPDXPVCSHA1 = auto() + SPDXPVCSHA256 = auto() + SPHINCS_PLUS = auto() + + +@dataclass_with_properties +class Hash(IntegrityMethod): + algorithm: HashAlgorithm = None + hash_value: str = None + + def __init__(self, algorithm: HashAlgorithm, hash_value: str, comment: Optional[str] = None): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/integrity_method.py b/src/spdx_tools/spdx3/model/integrity_method.py new file mode 100644 index 000000000..17fefef16 --- /dev/null +++ b/src/spdx_tools/spdx3/model/integrity_method.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod + +from beartype.typing import Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties + + +@dataclass_with_properties +class IntegrityMethod(ABC): + comment: Optional[str] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/__init__.py b/src/spdx_tools/spdx3/model/licensing/__init__.py new file mode 100644 index 000000000..8d9b9c6af --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/__init__.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from .any_license_info import AnyLicenseInfo +from .conjunctive_license_set import ConjunctiveLicenseSet +from .custom_license import CustomLicense +from .custom_license_addition import CustomLicenseAddition +from .disjunctive_license_set import DisjunctiveLicenseSet +from .license import License +from .license_addition import LicenseAddition +from .license_field import LicenseField +from .listed_license import ListedLicense +from .listed_license_exception import ListedLicenseException +from .no_assertion_license import NoAssertionLicense +from .none_license import NoneLicense +from .or_later_operator import OrLaterOperator +from .with_addition_operator import WithAdditionOperator diff --git a/src/spdx_tools/spdx3/model/licensing/any_license_info.py b/src/spdx_tools/spdx3/model/licensing/any_license_info.py new file mode 100644 index 000000000..1f1402427 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/any_license_info.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import abstractmethod + +from spdx_tools.spdx3.model.licensing.license_field import LicenseField + + +class AnyLicenseInfo(LicenseField): + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py b/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py new file mode 100644 index 000000000..fe5605761 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo + + +@dataclass_with_properties +class ConjunctiveLicenseSet(AnyLicenseInfo): + member: List[AnyLicenseInfo] + + def __init__(self, member: List[AnyLicenseInfo]): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/custom_license.py b/src/spdx_tools/spdx3/model/licensing/custom_license.py new file mode 100644 index 000000000..4617a18db --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/custom_license.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.license import License + + +@dataclass_with_properties +class CustomLicense(License): + def __init__( + self, + license_id: str, + license_name: str, + license_text: str, + license_comment: Optional[str] = None, + see_also: List[str] = None, + is_osi_approved: Optional[bool] = None, + is_fsf_libre: Optional[bool] = None, + standard_license_header: Optional[str] = None, + standard_license_template: Optional[str] = None, + is_deprecated_license_id: Optional[bool] = None, + obsoleted_by: Optional[str] = None, + ): + see_also = [] if see_also is None else see_also + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py b/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py new file mode 100644 index 000000000..b50d27770 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.license_addition import LicenseAddition + + +@dataclass_with_properties +class CustomLicenseAddition(LicenseAddition): + def __init__( + self, + addition_id: str, + addition_name: str, + addition_text: str, + addition_comment: Optional[str] = None, + see_also: List[str] = None, + standard_addition_template: Optional[str] = None, + is_deprecated_addition_id: Optional[bool] = None, + obsoleted_by: Optional[str] = None, + ): + see_also = [] if see_also is None else see_also + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py b/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py new file mode 100644 index 000000000..a5ac3bdc8 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo + + +@dataclass_with_properties +class DisjunctiveLicenseSet(AnyLicenseInfo): + member: List[AnyLicenseInfo] + + def __init__(self, member: List[AnyLicenseInfo]): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/license.py b/src/spdx_tools/spdx3/model/licensing/license.py new file mode 100644 index 000000000..e2fd625ff --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/license.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import abstractmethod +from dataclasses import field + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo + + +@dataclass_with_properties +class License(AnyLicenseInfo): + license_id: str + license_name: str + license_text: str + license_comment: Optional[str] = None + see_also: List[str] = field(default_factory=list) + is_osi_approved: Optional[bool] = None + is_fsf_libre: Optional[bool] = None + standard_license_header: Optional[str] = None + standard_license_template: Optional[str] = None + is_deprecated_license_id: Optional[bool] = None + obsoleted_by: Optional[str] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/license_addition.py b/src/spdx_tools/spdx3/model/licensing/license_addition.py new file mode 100644 index 000000000..e3669b5cb --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/license_addition.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod +from dataclasses import field + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties + + +@dataclass_with_properties +class LicenseAddition(ABC): + addition_id: str + addition_name: str + addition_text: str + addition_comment: Optional[str] = None + see_also: List[str] = field(default_factory=list) + standard_addition_template: Optional[str] = None + is_deprecated_addition_id: Optional[bool] = None + obsoleted_by: Optional[str] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/license_field.py b/src/spdx_tools/spdx3/model/licensing/license_field.py new file mode 100644 index 000000000..babe141f2 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/license_field.py @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod + + +class LicenseField(ABC): + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/listed_license.py b/src/spdx_tools/spdx3/model/licensing/listed_license.py new file mode 100644 index 000000000..2c0b02b3d --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/listed_license.py @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.license import License + + +@dataclass_with_properties +class ListedLicense(License): + list_version_added: Optional[str] = None + deprecated_version: Optional[str] = None + + def __init__( + self, + license_id: str, + license_name: str, + license_text: str, + license_comment: Optional[str] = None, + see_also: List[str] = None, + is_osi_approved: Optional[bool] = None, + is_fsf_libre: Optional[bool] = None, + standard_license_header: Optional[str] = None, + standard_license_template: Optional[str] = None, + is_deprecated_license_id: Optional[bool] = None, + obsoleted_by: Optional[str] = None, + list_version_added: Optional[str] = None, + deprecated_version: Optional[str] = None, + ): + see_also = [] if see_also is None else see_also + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py b/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py new file mode 100644 index 000000000..799fcedae --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.license_addition import LicenseAddition + + +@dataclass_with_properties +class ListedLicenseException(LicenseAddition): + list_version_added: Optional[str] = None + deprecated_version: Optional[str] = None + + def __init__( + self, + addition_id: str, + addition_name: str, + addition_text: str, + addition_comment: Optional[str] = None, + see_also: List[str] = None, + standard_addition_template: Optional[str] = None, + is_deprecated_addition_id: Optional[bool] = None, + obsoleted_by: Optional[str] = None, + list_version_added: Optional[str] = None, + deprecated_version: Optional[str] = None, + ): + see_also = [] if see_also is None else see_also + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py b/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py new file mode 100644 index 000000000..66a00b261 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model.licensing.license_field import LicenseField + + +class NoAssertionLicense(LicenseField): + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/none_license.py b/src/spdx_tools/spdx3/model/licensing/none_license.py new file mode 100644 index 000000000..e34253608 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/none_license.py @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model.licensing.license_field import LicenseField + + +class NoneLicense(LicenseField): + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/or_later_operator.py b/src/spdx_tools/spdx3/model/licensing/or_later_operator.py new file mode 100644 index 000000000..2aa204b98 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/or_later_operator.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo +from spdx_tools.spdx3.model.licensing.license import License + + +@dataclass_with_properties +class OrLaterOperator(AnyLicenseInfo): + subject_license: License + + def __init__(self, subject_license: License): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/with_addition_operator.py b/src/spdx_tools/spdx3/model/licensing/with_addition_operator.py new file mode 100644 index 000000000..9e79f8d98 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/with_addition_operator.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo +from spdx_tools.spdx3.model.licensing.license import License +from spdx_tools.spdx3.model.licensing.license_addition import LicenseAddition + + +@dataclass_with_properties +class WithAdditionOperator(AnyLicenseInfo): + subject_license: License + subject_addition: LicenseAddition + + def __init__(self, subject_license: License, subject_addition: LicenseAddition): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py new file mode 100644 index 000000000..a06e108ce --- /dev/null +++ b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py @@ -0,0 +1,59 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + Relationship, + RelationshipCompleteness, + RelationshipType, +) + + +class LifecycleScopeType(Enum): + DESIGN = auto() + BUILD = auto() + DEVELOPMENT = auto() + TEST = auto() + RUNTIME = auto() + OTHER = auto() + + +@dataclass_with_properties +class LifecycleScopedRelationship(Relationship): + scope: Optional[LifecycleScopeType] = None + + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str] = None, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + scope: Optional[LifecycleScopeType] = None, + ): + to = [] if to is None else to + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/namespace_map.py b/src/spdx_tools/spdx3/model/namespace_map.py new file mode 100644 index 000000000..c4d1217a5 --- /dev/null +++ b/src/spdx_tools/spdx3/model/namespace_map.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values + + +@dataclass_with_properties +class NamespaceMap: + prefix: str + namespace: str # anyURI + + def __init__(self, prefix: str, namespace: str): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/organization.py b/src/spdx_tools/spdx3/model/organization.py new file mode 100644 index 000000000..c297b24b3 --- /dev/null +++ b/src/spdx_tools/spdx3/model/organization.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import Agent, CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod + + +@dataclass_with_properties +class Organization(Agent): + def __init__( + self, + spdx_id: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/person.py b/src/spdx_tools/spdx3/model/person.py new file mode 100644 index 000000000..782e5a366 --- /dev/null +++ b/src/spdx_tools/spdx3/model/person.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import Agent, CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod + + +@dataclass_with_properties +class Person(Agent): + def __init__( + self, + spdx_id: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/positive_integer_range.py b/src/spdx_tools/spdx3/model/positive_integer_range.py new file mode 100644 index 000000000..cbe1c6322 --- /dev/null +++ b/src/spdx_tools/spdx3/model/positive_integer_range.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values + + +@dataclass_with_properties +class PositiveIntegerRange: + begin: int + end: int + + def __init__( + self, + begin: int, + end: int, + ): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/profile_identifier.py b/src/spdx_tools/spdx3/model/profile_identifier.py new file mode 100644 index 000000000..40fe7ac41 --- /dev/null +++ b/src/spdx_tools/spdx3/model/profile_identifier.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto + + +class ProfileIdentifierType(Enum): + CORE = auto() + SOFTWARE = auto() + LICENSING = auto() + SECURITY = auto() + BUILD = auto() + AI = auto() + DATASET = auto() + USAGE = auto() + EXTENSION = auto() diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py new file mode 100644 index 000000000..873559460 --- /dev/null +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -0,0 +1,120 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod + + +class RelationshipType(Enum): + AFFECTS = auto() + AMENDS = auto() + ANCESTOR = auto() + AVAILABLE_FROM = auto() + BUILD_DEPENDENCY = auto() + BUILD_TOOL = auto() + COORDINATED_BY = auto() + CONTAINS = auto() + CONFIG_OF = auto() + COPY = auto() + DATA_FILE = auto() + DEPENDENCY_MANIFEST = auto() + DEPENDS_ON = auto() + DESCENDANT = auto() + DESCRIBES = auto() + DEV_DEPENDENCY = auto() + DEV_TOOL = auto() + DISTRIBUTION_ARTIFACT = auto() + DOCUMENTATION = auto() + DOES_NOT_AFFECT = auto() + DYNAMIC_LINK = auto() + EXAMPLE = auto() + EVIDENCE_FOR = auto() + EXPANDED_FROM_ARCHIVE = auto() + EXPLOIT_CREATED_BY = auto() + FILE_ADDED = auto() + FILE_DELETED = auto() + FILE_MODIFIED = auto() + FIXED_BY = auto() + FIXED_IN = auto() + FOUND_BY = auto() + GENERATES = auto() + HAS_ASSESSMENT_FOR = auto() + HAS_ASSOCIATED_VULNERABILITY = auto() + HOST_OF = auto() + INPUT_OF = auto() + INVOKED_BY = auto() + METAFILE = auto() + ON_BEHALF_OF = auto() + OPTIONAL_COMPONENT = auto() + OPTIONAL_DEPENDENCY = auto() + OTHER = auto() + OUTPUT_OF = auto() + PACKAGES = auto() + PATCH = auto() + PREREQUISITE = auto() + PROVIDED_DEPENDENCY = auto() + PUBLISHED_BY = auto() + REPORTED_BY = auto() + REPUBLISHED_BY = auto() + REQUIREMENT_FOR = auto() + RUNTIME_DEPENDENCY = auto() + SPECIFICATION_FOR = auto() + STATIC_LINK = auto() + TEST = auto() + TEST_CASE = auto() + TEST_DEPENDENCY = auto() + TEST_TOOL = auto() + TESTED_ON = auto() + TRAINED_ON = auto() + UNDER_INVESTIGATION_FOR = auto() + VARIANT = auto() + + +class RelationshipCompleteness(Enum): + INCOMPLETE = auto() + COMPLETE = auto() + NOASSERTION = auto() + + +@dataclass_with_properties +class Relationship(Element): + # due to the inheritance we need to make all fields non-default in the __annotation__, + # the __init__ method still raises an error if required fields are not set + from_element: str = None + to: List[str] = field(default_factory=list) + relationship_type: RelationshipType = None + completeness: Optional[RelationshipCompleteness] = None + start_time: Optional[datetime] = None + end_time: Optional[datetime] = None + + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str] = None, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + ): + to = [] if to is None else to + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/__init__.py b/src/spdx_tools/spdx3/model/security/__init__.py new file mode 100644 index 000000000..3407981c8 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/__init__.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from .cvss_v2_vuln_assessment_relationship import CvssV2VulnAssessmentRelationship +from .cvss_v3_vuln_assessment_relationship import CvssV3VulnAssessmentRelationship +from .epss_vuln_assessment_relationship import EpssVulnAssessmentRelationship +from .exploit_catalog_vuln_assessment_relationship import ExploitCatalogVulnAssessmentRelationship, ExploitCatalogType +from .ssvc_vuln_assessment_relationship import SsvcVulnAssessmentRelationship, SsvcDecisionType +from .vex_affected_vuln_assessment_relationship import VexAffectedVulnAssessmentRelationship +from .vex_fixed_vuln_assessment_relationship import VexFixedVulnAssessmentRelationship +from .vex_not_affected_vuln_assessment_relationship import ( + VexNotAffectedVulnAssessmentRelationship, + VexJustificationType, +) +from .vex_under_investigation_vuln_assessment_relationship import VexUnderInvestigationVulnAssessmentRelationship +from .vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from .vuln_assessment_relationship import VulnAssessmentRelationship +from .vulnerability import Vulnerability diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py new file mode 100644 index 000000000..c686f9dfc --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + RelationshipCompleteness, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType + + +@dataclass_with_properties +class CvssV2VulnAssessmentRelationship(VulnAssessmentRelationship): + score: str = None + severity: Optional[str] = None + vector: Optional[str] = None + + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str], + score: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + assessed_element: Optional[str] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[str] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + severity: Optional[str] = None, + vector: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py new file mode 100644 index 000000000..ab8a803af --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + RelationshipCompleteness, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType + + +@dataclass_with_properties +class CvssV3VulnAssessmentRelationship(VulnAssessmentRelationship): + score: str = None + severity: Optional[str] = None + vector: Optional[str] = None + + def __init__( + self, + spdx_id: str, + from_element: str, + to: List[str], + relationship_type: RelationshipType, + score: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + assessed_element: Optional[str] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[str] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + severity: Optional[str] = None, + vector: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py new file mode 100644 index 000000000..f5001a92d --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + RelationshipCompleteness, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType + + +@dataclass_with_properties +class EpssVulnAssessmentRelationship(VulnAssessmentRelationship): + probability: int = None + severity: Optional[str] = None + + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str], + probability: int, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + assessed_element: Optional[str] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[str] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + severity: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py new file mode 100644 index 000000000..a7a67ac68 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -0,0 +1,63 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + RelationshipCompleteness, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType + + +class ExploitCatalogType(Enum): + KEV = auto() + OTHER = auto() + + +@dataclass_with_properties +class ExploitCatalogVulnAssessmentRelationship(VulnAssessmentRelationship): + catalog_type: ExploitCatalogType = None + exploited: bool = None + locator: str = None + + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str], + catalog_type: ExploitCatalogType, + exploited: bool, + locator: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + assessed_element: Optional[str] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[str] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py new file mode 100644 index 000000000..d98803874 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + RelationshipCompleteness, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType + + +class SsvcDecisionType(Enum): + ACT = auto() + ATTEND = auto() + TRACK = auto() + TRACK_STAR = auto() + + +@dataclass_with_properties +class SsvcVulnAssessmentRelationship(VulnAssessmentRelationship): + decision_type: SsvcDecisionType = None + + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str], + decision_type: SsvcDecisionType, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + assessed_element: Optional[str] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[str] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py new file mode 100644 index 000000000..2dc242273 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -0,0 +1,59 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + RelationshipCompleteness, +) +from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType + + +@dataclass_with_properties +class VexAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): + action_statement: Optional[str] = None + action_statement_time: List[datetime] = field(default_factory=list) + + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str], + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + assessed_element: Optional[str] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[str] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + vex_version: Optional[str] = None, + status_notes: Optional[str] = None, + action_statement: Optional[str] = None, + action_statement_time: List[datetime] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + action_statement_time = [] if action_statement_time is None else action_statement_time + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py new file mode 100644 index 000000000..c8bdc2b38 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + RelationshipCompleteness, +) +from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType + + +@dataclass_with_properties +class VexFixedVulnAssessmentRelationship(VexVulnAssessmentRelationship): + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str], + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + assessed_element: Optional[str] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[str] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + vex_version: Optional[str] = None, + status_notes: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py new file mode 100644 index 000000000..4c019a973 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + RelationshipCompleteness, +) +from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType + + +class VexJustificationType(Enum): + COMPONENT_NOT_PRESENT = auto() + VULNERABLE_CODE_NOT_PRESENT = auto() + VULNERABLE_CODE_CANNOT_BE_CONTROLLED_BY_ADVERSARY = auto() + VULNERABLE_CODE_NOT_IN_EXECUTE_PATH = auto() + INLINE_MITIGATIONS_ALREADY_EXIST = auto() + + +@dataclass_with_properties +class VexNotAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): + justification_type: Optional[VexJustificationType] = None + impact_statement: Optional[str] = None + impact_statement_time: Optional[datetime] = None + + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str], + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + assessed_element: Optional[str] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[str] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + vex_version: Optional[str] = None, + status_notes: Optional[str] = None, + justification_type: Optional[VexJustificationType] = None, + impact_statement: Optional[str] = None, + impact_statement_time: Optional[datetime] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py new file mode 100644 index 000000000..ba63480bc --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + RelationshipCompleteness, +) +from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType + + +@dataclass_with_properties +class VexUnderInvestigationVulnAssessmentRelationship(VexVulnAssessmentRelationship): + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str], + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + assessed_element: Optional[str] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[str] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + vex_version: Optional[str] = None, + status_notes: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py new file mode 100644 index 000000000..8b5c0fc68 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import abstractmethod + +from beartype.typing import Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship + + +@dataclass_with_properties +class VexVulnAssessmentRelationship(VulnAssessmentRelationship): + vex_version: Optional[str] = None + status_notes: Optional[str] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py new file mode 100644 index 000000000..f20303743 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import abstractmethod +from datetime import datetime + +from beartype.typing import Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model import Relationship + + +@dataclass_with_properties +class VulnAssessmentRelationship(Relationship): + assessed_element: Optional[str] = None # id of the element + published_time: Optional[datetime] = None + supplied_by: Optional[str] = None + modified_time: Optional[datetime] = None + withdrawn_time: Optional[datetime] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/security/vulnerability.py b/src/spdx_tools/spdx3/model/security/vulnerability.py new file mode 100644 index 000000000..a137b1cb7 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vulnerability.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod + + +@dataclass_with_properties +class Vulnerability(Element): + published_time: Optional[datetime] = None + modified_time: Optional[datetime] = None + withdrawn_time: Optional[datetime] = None + + def __init__( + self, + spdx_id: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + published_time: Optional[datetime] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/__init__.py b/src/spdx_tools/spdx3/model/software/__init__.py new file mode 100644 index 000000000..f3b157024 --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/__init__.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.model.software.package import Package +from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.model.software.sbom import Sbom, SBOMType +from spdx_tools.spdx3.model.software.software_dependency_relationship import ( + SoftwareDependencyRelationship, + SoftwareDependencyLinkType, + DependencyConditionalityType, +) diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py new file mode 100644 index 000000000..c962b4dbd --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField +from spdx_tools.spdx3.model.software import SoftwarePurpose +from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact + + +@dataclass_with_properties +class File(SoftwareArtifact): + content_type: Optional[str] = None # placeholder for MediaType + + def __init__( + self, + spdx_id: str, + name: str, + creation_info: Optional[CreationInfo] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + originated_by: List[str] = None, + supplied_by: List[str] = None, + built_time: Optional[datetime] = None, + release_time: Optional[datetime] = None, + valid_until_time: Optional[datetime] = None, + standard: List[str] = None, + content_identifier: Optional[str] = None, + primary_purpose: Optional[SoftwarePurpose] = None, + additional_purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, + content_type: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + originated_by = [] if originated_by is None else originated_by + supplied_by = [] if supplied_by is None else supplied_by + standard = [] if standard is None else standard + additional_purpose = [] if additional_purpose is None else additional_purpose + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py new file mode 100644 index 000000000..0c249cc1b --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -0,0 +1,62 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField +from spdx_tools.spdx3.model.software import SoftwarePurpose +from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact + + +@dataclass_with_properties +class Package(SoftwareArtifact): + package_version: Optional[str] = None + download_location: Optional[str] = None # anyURI + package_url: Optional[str] = None # anyURI + homepage: Optional[str] = None # anyURI + source_info: Optional[str] = None + + def __init__( + self, + spdx_id: str, + name: str, + creation_info: Optional[CreationInfo] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + originated_by: List[str] = None, + supplied_by: List[str] = None, + built_time: Optional[datetime] = None, + release_time: Optional[datetime] = None, + valid_until_time: Optional[datetime] = None, + standard: List[str] = None, + content_identifier: Optional[str] = None, + primary_purpose: Optional[SoftwarePurpose] = None, + additional_purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, + package_version: Optional[str] = None, + download_location: Optional[str] = None, + package_url: Optional[str] = None, + homepage: Optional[str] = None, + source_info: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + originated_by = [] if originated_by is None else originated_by + supplied_by = [] if supplied_by is None else supplied_by + standard = [] if standard is None else standard + additional_purpose = [] if additional_purpose is None else additional_purpose + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py new file mode 100644 index 000000000..1fb06f615 --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -0,0 +1,62 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Bom, + CreationInfo, + ExternalIdentifier, + ExternalMap, + ExternalReference, + IntegrityMethod, + NamespaceMap, +) + + +class SBOMType(Enum): + DESIGN = auto() + SOURCE = auto() + BUILD = auto() + DEPLOYED = auto() + RUNTIME = auto() + ANALYZED = auto() + + +@dataclass_with_properties +class Sbom(Bom): + sbom_type: List[SBOMType] = field(default_factory=list) + + # We overwrite the super-__init__ as check_types_and_set_values() + # takes care of all fields (including inherited ones). + def __init__( + self, + spdx_id: str, + element: List[str], + root_element: List[str], + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + namespaces: List[NamespaceMap] = None, + imports: List[ExternalMap] = None, + context: Optional[str] = None, + sbom_type: List[SBOMType] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports + sbom_type = [] if sbom_type is None else sbom_type + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py new file mode 100644 index 000000000..b3ab61396 --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField +from spdx_tools.spdx3.model.positive_integer_range import PositiveIntegerRange +from spdx_tools.spdx3.model.software import SoftwarePurpose +from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact + + +@dataclass_with_properties +class Snippet(SoftwareArtifact): + byte_range: Optional[PositiveIntegerRange] = None + line_range: Optional[PositiveIntegerRange] = None + + def __init__( + self, + spdx_id: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + originated_by: List[str] = None, + supplied_by: List[str] = None, + built_time: Optional[datetime] = None, + release_time: Optional[datetime] = None, + valid_until_time: Optional[datetime] = None, + standard: List[str] = None, + content_identifier: Optional[str] = None, + primary_purpose: Optional[SoftwarePurpose] = None, + additional_purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, + byte_range: Optional[PositiveIntegerRange] = None, + line_range: Optional[PositiveIntegerRange] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + originated_by = [] if originated_by is None else originated_by + supplied_by = [] if supplied_by is None else supplied_by + standard = [] if standard is None else standard + additional_purpose = [] if additional_purpose is None else additional_purpose + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/software_artifact.py b/src/spdx_tools/spdx3/model/software/software_artifact.py new file mode 100644 index 000000000..afc2b7ff3 --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/software_artifact.py @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import abstractmethod +from dataclasses import field + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model import Artifact +from spdx_tools.spdx3.model.licensing import LicenseField +from spdx_tools.spdx3.model.software import SoftwarePurpose + + +@dataclass_with_properties +class SoftwareArtifact(Artifact): + content_identifier: Optional[str] = None + primary_purpose: Optional[SoftwarePurpose] = None + additional_purpose: List[SoftwarePurpose] = field(default_factory=list) + concluded_license: Optional[LicenseField] = None + declared_license: Optional[LicenseField] = None + copyright_text: Optional[str] = None + attribution_text: Optional[str] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py new file mode 100644 index 000000000..c6751ecaa --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py @@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import Enum, auto + +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + LifecycleScopedRelationship, + LifecycleScopeType, + RelationshipCompleteness, + RelationshipType, +) + + +class SoftwareDependencyLinkType(Enum): + STATIC = auto() + DYNAMIC = auto() + TOOL = auto() + OTHER = auto() + + +class DependencyConditionalityType(Enum): + OPTIONAL = auto() + REQUIRED = auto() + PROVIDED = auto() + PREREQUISITE = auto() + OTHER = auto() + + +@dataclass_with_properties +class SoftwareDependencyRelationship(LifecycleScopedRelationship): + software_linkage: Optional[SoftwareDependencyLinkType] = None + conditionality: Optional[DependencyConditionalityType] = None + + def __init__( + self, + spdx_id: str, + from_element: str, + relationship_type: RelationshipType, + to: List[str] = None, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + scope: Optional[LifecycleScopeType] = None, + software_linkage: Optional[SoftwareDependencyLinkType] = None, + conditionality: Optional[DependencyConditionalityType] = None, + ): + to = [] if to is None else to + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/software_purpose.py b/src/spdx_tools/spdx3/model/software/software_purpose.py new file mode 100644 index 000000000..e3a4d48cf --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/software_purpose.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto + + +class SoftwarePurpose(Enum): + APPLICATION = auto() + ARCHIVE = auto() + BOM = auto() + CONFIGURATION = auto() + CONTAINER = auto() + DATA = auto() + DEVICE = auto() + DOCUMENTATION = auto() + EXECUTABLE = auto() + FILE = auto() + FIRMWARE = auto() + FRAMEWORK = auto() + INSTALL = auto() + LIBRARY = auto() + MODEL = auto() + MODULE = auto() + OPERATING_SYSTEM = auto() + OTHER = auto() + PATCH = auto() + REQUIREMENT = auto() + SOURCE = auto() + TEST = auto() diff --git a/src/spdx_tools/spdx3/model/software_agent.py b/src/spdx_tools/spdx3/model/software_agent.py new file mode 100644 index 000000000..28e4b33a2 --- /dev/null +++ b/src/spdx_tools/spdx3/model/software_agent.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import Agent, CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod + + +@dataclass_with_properties +class SoftwareAgent(Agent): + def __init__( + self, + spdx_id: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/spdx_collection.py b/src/spdx_tools/spdx3/model/spdx_collection.py new file mode 100644 index 000000000..65c28951a --- /dev/null +++ b/src/spdx_tools/spdx3/model/spdx_collection.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import abstractmethod +from dataclasses import field + +from beartype.typing import List + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model import Element, ExternalMap, NamespaceMap + + +@dataclass_with_properties +class ElementCollection(Element): + # due to the inheritance we need to make all fields non-default in the __annotation__, + # the __init__ method still raises an error if required fields are not set + element: List[str] = field(default_factory=list) + root_element: List[str] = field(default_factory=list) + namespaces: List[NamespaceMap] = field(default_factory=list) + imports: List[ExternalMap] = field(default_factory=list) + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py new file mode 100644 index 000000000..d9c70401c --- /dev/null +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Bundle, + CreationInfo, + ExternalIdentifier, + ExternalMap, + ExternalReference, + IntegrityMethod, + NamespaceMap, +) + + +@dataclass_with_properties +class SpdxDocument(Bundle): + # The inherited field "name" is required for a SpdxDocument, no longer optional. + # We overwrite the super-__init__ as check_types_and_set_values() + # takes care of all fields (including inherited ones). + def __init__( + self, + spdx_id: str, + name: str, + element: List[str], + root_element: List[str], + creation_info: Optional[CreationInfo] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + namespaces: List[NamespaceMap] = None, + imports: List[ExternalMap] = None, + context: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/tool.py b/src/spdx_tools/spdx3/model/tool.py new file mode 100644 index 000000000..b4ba72cf3 --- /dev/null +++ b/src/spdx_tools/spdx3/model/tool.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod + + +@dataclass_with_properties +class Tool(Element): + def __init__( + self, + spdx_id: str, + creation_info: Optional[CreationInfo] = None, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_reference: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_reference = [] if external_reference is None else external_reference + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/payload.py b/src/spdx_tools/spdx3/payload.py new file mode 100644 index 000000000..17bc78c91 --- /dev/null +++ b/src/spdx_tools/spdx3/payload.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Dict + +from spdx_tools.spdx3.model import Element + + +class Payload: + _spdx_id_map: Dict[str, Element] + + def __init__(self, spdx_id_map: Dict[str, Element] = None): + self._spdx_id_map = spdx_id_map if spdx_id_map else {} + + def add_element(self, element: Element): + self._spdx_id_map[element.spdx_id] = element + + def get_element(self, spdx_id: str) -> Element: + return self._spdx_id_map[spdx_id] + + def get_full_map(self) -> Dict[str, Element]: + return self._spdx_id_map diff --git a/src/spdx_tools/spdx3/validation/__init__.py b/src/spdx_tools/spdx3/validation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/validation/json_ld/__init__.py b/src/spdx_tools/spdx3/validation/json_ld/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py new file mode 100644 index 000000000..e7b3c8776 --- /dev/null +++ b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import Optional +from pyshacl import validate +from rdflib import Graph + + +def validate_against_shacl_from_file( + data_file: str, shacl_file: str, data_format: Optional[str] = "json-ld", shacl_format: Optional[str] = "ttl" +): + data_graph = Graph() + with open(data_file) as file: + data_graph.parse(file, format=data_format) + + shacl_graph = Graph() + with open(shacl_file) as file: + shacl_graph.parse(file, format=shacl_format) + + return validate(data_graph=data_graph, shacl_graph=shacl_graph, ont_graph=shacl_graph) diff --git a/src/spdx_tools/spdx3/writer/__init__.py b/src/spdx_tools/spdx3/writer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/console/__init__.py b/src/spdx_tools/spdx3/writer/console/__init__.py new file mode 100644 index 000000000..39bbda884 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/__init__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +""" This is a temporary package to write the implemented model of spdx_tools.spdx3.0 to console. As soon as + serialization formats are properly defined this package can be deleted.""" diff --git a/src/spdx_tools/spdx3/writer/console/agent_writer.py b/src/spdx_tools/spdx3/writer/console/agent_writer.py new file mode 100644 index 000000000..a1c12a9e0 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/agent_writer.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import Agent, Organization, Person, SoftwareAgent +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties + + +def write_agent(agent: Agent, text_output: TextIO, heading: bool = True): + if heading: + if isinstance(agent, Person): + text_output.write("## Person\n") + if isinstance(agent, Organization): + text_output.write("## Organization\n") + if isinstance(agent, SoftwareAgent): + text_output.write("## SoftwareAgent\n") + write_element_properties(agent, text_output) diff --git a/src/spdx_tools/spdx3/writer/console/ai/__init__.py b/src/spdx_tools/spdx3/writer/console/ai/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py b/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py new file mode 100644 index 000000000..025ae613a --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model.ai import AIPackage +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.software.package_writer import write_package + + +def write_ai_package(ai_package: AIPackage, text_output: TextIO): + text_output.write("## AI Package\n") + write_package(ai_package, text_output, False) + + for property_name in AIPackage.__annotations__.keys(): + write_value(property_name, getattr(ai_package, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/annotation_writer.py b/src/spdx_tools/spdx3/writer/console/annotation_writer.py new file mode 100644 index 000000000..3261a69bd --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/annotation_writer.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import Annotation +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties + + +def write_annotation(annotation: Annotation, text_output: TextIO): + text_output.write("## Annotation\n") + write_element_properties(annotation, text_output) + + for property_name in Annotation.__annotations__.keys(): + write_value(property_name, getattr(annotation, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/artifact_writer.py b/src/spdx_tools/spdx3/writer/console/artifact_writer.py new file mode 100644 index 000000000..f55d29e05 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/artifact_writer.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import Artifact +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties + + +def write_artifact_properties(artifact: Artifact, text_output: TextIO): + write_element_properties(artifact, text_output) + + for property_name in Artifact.__annotations__.keys(): + write_value(property_name, getattr(artifact, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/bom_writer.py b/src/spdx_tools/spdx3/writer/console/bom_writer.py new file mode 100644 index 000000000..04fcb283d --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/bom_writer.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import Bom +from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle + + +def write_bom(bom: Bom, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Bom\n") + write_bundle(bom, text_output, False) diff --git a/src/spdx_tools/spdx3/writer/console/build/__init__.py b/src/spdx_tools/spdx3/writer/console/build/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/console/build/build_writer.py b/src/spdx_tools/spdx3/writer/console/build/build_writer.py new file mode 100644 index 000000000..3edc9c6fb --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/build/build_writer.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model.build import Build +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties +from spdx_tools.spdx3.writer.console.hash_writer import write_hash +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading + + +def write_build(build: Build, text_output: TextIO): + text_output.write("## Build\n") + write_element_properties(build, text_output) + + for property_name in Build.__annotations__.keys(): + if property_name == "config_source_digest": + write_optional_heading(build.config_source_digest, "config_source_digest", text_output) + for digest_hash in build.config_source_digest: + write_hash(digest_hash, text_output, heading=False) + continue + + write_value(property_name, getattr(build, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/bundle_writer.py b/src/spdx_tools/spdx3/writer/console/bundle_writer.py new file mode 100644 index 000000000..5930db5ee --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/bundle_writer.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import Bundle +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.spdx_collection_writer import write_collection + + +def write_bundle(bundle: Bundle, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Bundle\n") + write_collection(bundle, text_output) + write_value("context", bundle.context, text_output) diff --git a/src/spdx_tools/spdx3/writer/console/console.py b/src/spdx_tools/spdx3/writer/console/console.py new file mode 100644 index 000000000..28b5f9cfa --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/console.py @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum + +from beartype.typing import Optional, TextIO, Union + + +def write_value(tag: str, value: Optional[Union[bool, str, dict, list, Enum]], out: TextIO, indent: bool = False): + """This function is duplicated from spdx_tools.spdx.writer.tagvalue.tag_value_writer_helper_functions + and slightly adapted to make indentation of output possible.""" + if not value: + return + if isinstance(value, dict): + value = ", ".join([f"{tag}: ({key}: {val})" for key, val in value.items()]) + if isinstance(value, list): + value = ", ".join([entry for entry in value]) + if isinstance(value, Enum): + value = value.name + write_and_possibly_indent(f"{tag}: {value}", indent, out) + + +def write_and_possibly_indent(text: str, indent: bool, out: TextIO): + if indent: + out.write(f" {text}\n") + else: + out.write(f"{text}\n") diff --git a/src/spdx_tools/spdx3/writer/console/creation_info_writer.py b/src/spdx_tools/spdx3/writer/console/creation_info_writer.py new file mode 100644 index 000000000..c91e6781d --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/creation_info_writer.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import CreationInfo +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string + + +def write_creation_info(creation_info: CreationInfo, text_output: TextIO, indent: bool = True): + text_output.write("# Creation Information\n") + write_value("specVersion", str(creation_info.spec_version), text_output, indent) + write_value("created", datetime_to_iso_string(creation_info.created), text_output, indent) + for created_by in creation_info.created_by: + write_value("created by", created_by, text_output, indent) + for created_using in creation_info.created_using: + write_value("created using", created_using, text_output, indent) + write_value("profile", [profile.name for profile in creation_info.profile], text_output, indent) + write_value("data license", creation_info.data_license, text_output, indent) + write_value("comment", creation_info.comment, text_output, indent) diff --git a/src/spdx_tools/spdx3/writer/console/dataset/__init__.py b/src/spdx_tools/spdx3/writer/console/dataset/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py new file mode 100644 index 000000000..91131240a --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model.dataset import Dataset +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.software.package_writer import write_package + + +def write_dataset(dataset: Dataset, text_output: TextIO): + text_output.write("## Dataset\n") + write_package(dataset, text_output, False) + + for property_name in Dataset.__annotations__.keys(): + write_value(property_name, getattr(dataset, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/element_writer.py b/src/spdx_tools/spdx3/writer/console/element_writer.py new file mode 100644 index 000000000..61eb72ecd --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/element_writer.py @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import Element +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.creation_info_writer import write_creation_info +from spdx_tools.spdx3.writer.console.external_identifier_writer import write_external_identifier +from spdx_tools.spdx3.writer.console.external_reference_writer import write_external_reference +from spdx_tools.spdx3.writer.console.hash_writer import write_hash +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading + + +def write_element_properties(element: Element, text_output: TextIO): + write_value("SPDXID", element.spdx_id, text_output) + write_value("name", element.name, text_output) + if element.creation_info: + write_creation_info(element.creation_info, text_output, True) + write_value("summary", element.summary, text_output) + write_value("description", element.description, text_output) + write_value("comment", element.comment, text_output) + write_optional_heading(element.verified_using, "verified using:\n", text_output) + for integrity_method in element.verified_using: + # for now Hash is the only child class of the abstract class IntegrityMethod, + # as soon as there are more inherited classes we need to implement a logic + # that determines the correct write function for the "integrity_method" object + write_hash(integrity_method, text_output, heading=False) + write_optional_heading(element.external_reference, "External Reference\n", text_output) + for external_reference in element.external_reference: + write_external_reference(external_reference, text_output) + write_optional_heading(element.external_identifier, "External Identifier\n", text_output) + for external_identifier in element.external_identifier: + write_external_identifier(external_identifier, text_output) diff --git a/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py new file mode 100644 index 000000000..40f2d0e97 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import ExternalIdentifier +from spdx_tools.spdx3.writer.console.console import write_value + + +def write_external_identifier(external_identifier: ExternalIdentifier, text_output: TextIO): + for property_name in ExternalIdentifier.__annotations__.keys(): + write_value(property_name, getattr(external_identifier, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/external_map_writer.py b/src/spdx_tools/spdx3/writer/console/external_map_writer.py new file mode 100644 index 000000000..41f59dc5d --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/external_map_writer.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import ExternalMap +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.hash_writer import write_hash +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading + + +def write_external_map(external_map: ExternalMap, text_output: TextIO): + write_value("external_id", external_map.external_id, text_output) + write_optional_heading(external_map.verified_using, "verified using\n", text_output) + for integrity_method in external_map.verified_using: + # for now Hash is the only child class of the abstract class IntegrityMethod, + # as soon as there are more inherited classes we need to implement a logic + # that determines the correct write function for the "integrity_method" object + write_hash(integrity_method, text_output, heading=False) + write_value("location_hint", external_map.location_hint, text_output) diff --git a/src/spdx_tools/spdx3/writer/console/external_reference_writer.py b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py new file mode 100644 index 000000000..fa6cc79eb --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import ExternalReference +from spdx_tools.spdx3.writer.console.console import write_value + + +def write_external_reference(external_reference: ExternalReference, text_output: TextIO): + for property_name in ExternalReference.__annotations__.keys(): + write_value(property_name, getattr(external_reference, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/hash_writer.py b/src/spdx_tools/spdx3/writer/console/hash_writer.py new file mode 100644 index 000000000..970a49b56 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/hash_writer.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import Hash +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.integrity_method_writer import write_integrity_method + + +def write_hash(hash_object: Hash, text_output: TextIO, heading: bool, indent: bool = True): + if heading: + text_output.write("## Hash\n") + write_value("algorithm", hash_object.algorithm, text_output, indent) + write_value("hash_value", hash_object.hash_value, text_output, indent) + write_integrity_method(hash_object, text_output, indent) diff --git a/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py b/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py new file mode 100644 index 000000000..df233c997 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import IntegrityMethod +from spdx_tools.spdx3.writer.console.console import write_value + + +def write_integrity_method(integrity_method: IntegrityMethod, text_output: TextIO, indent: bool = True): + write_value("comment", integrity_method.comment, text_output, indent) diff --git a/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py b/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py new file mode 100644 index 000000000..5710ae6e8 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import LifecycleScopedRelationship +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.relationship_writer import write_relationship + + +def write_lifecycle_scoped_relationship( + relationship: LifecycleScopedRelationship, text_output: TextIO, heading: bool = True +): + if heading: + text_output.write("## LifecycleScopedRelationship\n") + write_relationship(relationship, text_output, heading=False) + + for property_name in LifecycleScopedRelationship.__annotations__.keys(): + write_value(property_name, getattr(relationship, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py new file mode 100644 index 000000000..d83ccb05a --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import NamespaceMap +from spdx_tools.spdx3.writer.console.console import write_value + + +def write_namespace_map(namespace_map: NamespaceMap, text_output: TextIO): + for property_name in NamespaceMap.__annotations__.keys(): + write_value(property_name, getattr(namespace_map, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/payload_writer.py b/src/spdx_tools/spdx3/writer/console/payload_writer.py new file mode 100644 index 000000000..34532f364 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/payload_writer.py @@ -0,0 +1,65 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import ( + Annotation, + Bom, + Bundle, + Organization, + Person, + Relationship, + SoftwareAgent, + SpdxDocument, + Tool, +) +from spdx_tools.spdx3.model.ai import AIPackage +from spdx_tools.spdx3.model.build import Build +from spdx_tools.spdx3.model.dataset import Dataset +from spdx_tools.spdx3.model.software import File, Package, Sbom, Snippet, SoftwareDependencyRelationship +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.console.agent_writer import write_agent +from spdx_tools.spdx3.writer.console.ai.ai_package_writer import write_ai_package +from spdx_tools.spdx3.writer.console.annotation_writer import write_annotation +from spdx_tools.spdx3.writer.console.bom_writer import write_bom +from spdx_tools.spdx3.writer.console.build.build_writer import write_build +from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle +from spdx_tools.spdx3.writer.console.dataset.dataset_writer import write_dataset +from spdx_tools.spdx3.writer.console.relationship_writer import write_relationship +from spdx_tools.spdx3.writer.console.software.file_writer import write_file +from spdx_tools.spdx3.writer.console.software.package_writer import write_package +from spdx_tools.spdx3.writer.console.software.sbom_writer import write_sbom +from spdx_tools.spdx3.writer.console.software.snippet_writer import write_snippet +from spdx_tools.spdx3.writer.console.software.software_dependency_relationship_writer import ( + write_software_dependency_relationship, +) +from spdx_tools.spdx3.writer.console.spdx_document_writer import write_spdx_document +from spdx_tools.spdx3.writer.console.tool_writer import write_tool + +MAP_CLASS_TO_WRITE_METHOD = { + Annotation: write_annotation, + Relationship: write_relationship, + SoftwareDependencyRelationship: write_software_dependency_relationship, + Bundle: write_bundle, + SpdxDocument: write_spdx_document, + Bom: write_bom, + File: write_file, + Package: write_package, + Snippet: write_snippet, + Sbom: write_sbom, + Person: write_agent, + Organization: write_agent, + SoftwareAgent: write_agent, + Tool: write_tool, + AIPackage: write_ai_package, + Dataset: write_dataset, + Build: write_build, +} + + +def write_payload(payload: Payload, text_output: TextIO): + for element in payload.get_full_map().values(): + write_method = MAP_CLASS_TO_WRITE_METHOD[type(element)] + write_method(element, text_output) + text_output.write("\n") diff --git a/src/spdx_tools/spdx3/writer/console/relationship_writer.py b/src/spdx_tools/spdx3/writer/console/relationship_writer.py new file mode 100644 index 000000000..1a8b16a3e --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/relationship_writer.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import Relationship +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties + + +def write_relationship(relationship: Relationship, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Relationship\n") + write_element_properties(relationship, text_output) + for property_name in relationship.__annotations__.keys(): + write_value(property_name, getattr(relationship, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/software/__init__.py b/src/spdx_tools/spdx3/writer/console/software/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/console/software/file_writer.py b/src/spdx_tools/spdx3/writer/console/software/file_writer.py new file mode 100644 index 000000000..ec631f024 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/software/file_writer.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model.software import File +from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties +from spdx_tools.spdx3.writer.console.console import write_value + + +def write_file(file: File, text_output: TextIO): + text_output.write("## File\n") + write_artifact_properties(file, text_output) + + for property_name in File.__annotations__.keys(): + if property_name == "file_purpose": + write_value( + property_name, ", ".join([purpose.name for purpose in getattr(file, property_name)]), text_output + ) + continue + write_value(property_name, getattr(file, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/software/package_writer.py b/src/spdx_tools/spdx3/writer/console/software/package_writer.py new file mode 100644 index 000000000..1f66f989b --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/software/package_writer.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model.software import Package +from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties +from spdx_tools.spdx3.writer.console.console import write_value + + +def write_package(package: Package, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Package\n") + write_artifact_properties(package, text_output) + + for property_name in Package.__annotations__.keys(): + if property_name == "package_purpose": + write_value( + property_name, ", ".join([purpose.name for purpose in getattr(package, property_name)]), text_output + ) + continue + write_value(property_name, getattr(package, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py b/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py new file mode 100644 index 000000000..2e34a6b00 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model.software import Sbom +from spdx_tools.spdx3.writer.console.bom_writer import write_bom + + +def write_sbom(sbom: Sbom, text_output: TextIO): + text_output.write("## Sbom\n") + write_bom(sbom, text_output, False) diff --git a/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py new file mode 100644 index 000000000..b0ea7bbc7 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model.software import Snippet +from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties +from spdx_tools.spdx3.writer.console.console import write_value + + +def write_snippet(snippet: Snippet, text_output: TextIO): + text_output.write("## Snippet\n") + write_artifact_properties(snippet, text_output) + + for property_name in Snippet.__annotations__.keys(): + if property_name == "snippet_purpose": + write_value( + property_name, ", ".join([purpose.name for purpose in getattr(snippet, property_name)]), text_output + ) + continue + write_value(property_name, getattr(snippet, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py b/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py new file mode 100644 index 000000000..8064c76a1 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from beartype.typing import TextIO + +from spdx_tools.spdx3.model.software import SoftwareDependencyRelationship +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.lifecycle_scoped_relationship_writer import write_lifecycle_scoped_relationship + + +def write_software_dependency_relationship( + relationship: SoftwareDependencyRelationship, text_output: TextIO, heading: bool = True +): + if heading: + text_output.write("## SoftwareDependencyRelationship\n") + write_lifecycle_scoped_relationship(relationship, text_output, heading=False) + + for property_name in SoftwareDependencyRelationship.__annotations__.keys(): + write_value(property_name, getattr(relationship, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py new file mode 100644 index 000000000..7654329b2 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import ElementCollection +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties +from spdx_tools.spdx3.writer.console.external_map_writer import write_external_map +from spdx_tools.spdx3.writer.console.namespace_map_writer import write_namespace_map +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading + + +def write_collection(collection: ElementCollection, text_output: TextIO): + write_element_properties(collection, text_output) + text_output.write(f"elements: {', '.join(collection.element)}\n") + write_optional_heading(collection.namespaces, "# Namespaces\n", text_output) + for namespace_map in collection.namespaces: + write_namespace_map(namespace_map, text_output) + write_optional_heading(collection.imports, "# Imports\n", text_output) + for external_map in collection.imports: + write_external_map(external_map, text_output) diff --git a/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py b/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py new file mode 100644 index 000000000..8c2cdf649 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import SpdxDocument +from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle + + +def write_spdx_document(spdx_document: SpdxDocument, text_output: TextIO): + text_output.write("## SPDX Document\n") + write_bundle(spdx_document, text_output, False) diff --git a/src/spdx_tools/spdx3/writer/console/tool_writer.py b/src/spdx_tools/spdx3/writer/console/tool_writer.py new file mode 100644 index 000000000..1873263bc --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/tool_writer.py @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 spdx contributors +# 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. +from beartype.typing import TextIO + +from spdx_tools.spdx3.model import Tool +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties + + +def write_tool(tool: Tool, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Tool\n") + write_element_properties(tool, text_output) diff --git a/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json new file mode 100644 index 000000000..96e744e79 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json @@ -0,0 +1,5448 @@ +{ + "@context": { + "ai": "https://spdx.org/rdf/AI/", + "build": "https://spdx.org/rdf/Build/", + "core": "https://spdx.org/rdf/Core/", + "dataset": "https://spdx.org/rdf/Dataset/", + "licensing": "https://spdx.org/rdf/Licensing/", + "ns0": "http://www.w3.org/2003/06/sw-vocab-status/ns#", + "owl": "http://www.w3.org/2002/07/owl#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "security": "https://spdx.org/rdf/Security/", + "sh": "http://www.w3.org/ns/shacl#", + "software": "https://spdx.org/rdf/Software/", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + { + "@id": "ai:AIPackage", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "Metadata information that can be added to a package to describe an AI application or trained AI model.\nExternal property restriction on /Core/Artifact/suppliedBy: minCount: 1\nExternal property restriction on /Software/Package/downloadLocation: minCount: 1\nExternal property restriction on /Software/Package/packageVersion: minCount: 1\nExternal property restriction on /Software/SoftwareArtifact/purpose: minCount: 1\nExternal property restriction on /Core/Artifact/releaseTime: minCount: 1", + "rdfs:subClassOf": { + "@id": "software:Package" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "metric", + "sh:path": { + "@id": "ai:metric" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "modelExplainability", + "sh:path": { + "@id": "ai:modelExplainability" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "domain", + "sh:path": { + "@id": "ai:domain" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "standardCompliance", + "sh:path": { + "@id": "ai:standardCompliance" + } + }, + { + "sh:class": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "hyperparameter", + "sh:path": { + "@id": "ai:hyperparameter" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "energyConsumption", + "sh:path": { + "@id": "ai:energyConsumption" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "limitation", + "sh:path": { + "@id": "ai:limitation" + } + }, + { + "sh:class": { + "@id": "ai:SafetyRiskAssessmentType" + }, + "sh:maxCount": 1, + "sh:name": "safetyRiskAssessment", + "sh:path": { + "@id": "ai:safetyRiskAssessment" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "modelDataPreprocessing", + "sh:path": { + "@id": "ai:modelDataPreprocessing" + } + }, + { + "sh:class": { + "@id": "ai:PresenceType" + }, + "sh:maxCount": 1, + "sh:name": "sensitivePersonalInformation", + "sh:path": { + "@id": "ai:sensitivePersonalInformation" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "informationAboutTraining", + "sh:path": { + "@id": "ai:informationAboutTraining" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "informationAboutApplication", + "sh:path": { + "@id": "ai:informationAboutApplication" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "typeOfModel", + "sh:path": { + "@id": "ai:typeOfModel" + } + }, + { + "sh:class": { + "@id": "ai:PresenceType" + }, + "sh:maxCount": 1, + "sh:name": "autonomyType", + "sh:path": { + "@id": "ai:autonomyType" + } + }, + { + "sh:class": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "metricDecisionThreshold", + "sh:path": { + "@id": "ai:metricDecisionThreshold" + } + } + ] + }, + { + "@id": "https://spdx.org/rdf/AI/PresenceType/no", + "@type": [ + "owl:NamedIndividual", + "ai:PresenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/AI/PresenceType/noAssertion", + "@type": [ + "owl:NamedIndividual", + "ai:PresenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/AI/PresenceType/yes", + "@type": [ + "owl:NamedIndividual", + "ai:PresenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/AI/SafetyRiskAssessmentType/high", + "@type": [ + "owl:NamedIndividual", + "ai:SafetyRiskAssessmentType" + ] + }, + { + "@id": "https://spdx.org/rdf/AI/SafetyRiskAssessmentType/low", + "@type": [ + "owl:NamedIndividual", + "ai:SafetyRiskAssessmentType" + ] + }, + { + "@id": "https://spdx.org/rdf/AI/SafetyRiskAssessmentType/medium", + "@type": [ + "owl:NamedIndividual", + "ai:SafetyRiskAssessmentType" + ] + }, + { + "@id": "https://spdx.org/rdf/AI/SafetyRiskAssessmentType/serious", + "@type": [ + "owl:NamedIndividual", + "ai:SafetyRiskAssessmentType" + ] + }, + { + "@id": "build:Build", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A build is a representation of the process in which a piece of software or artifact is built. It encapsulates information related to a build process and\nprovides an element from which relationships can be created to describe the build's inputs, outputs, and related entities (e.g. builders, identities, etc.).\n\nDefinitions of \"BuildType\", \"ConfigSource\", \"Parameters\" and \"Environment\" follow\nthose defined in [SLSA provenance](https://slsa.dev/provenance/v0.2).\n\nExternalIdentifier of type \"urlScheme\" may be used to identify build logs. In this case, the comment of the ExternalIdentifier should be \"LogReference\".\n\nNote that buildStart and buildEnd are optional, and may be omitted to simplify creating reproducible builds.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "core:Hash" + }, + "sh:name": "configSourceDigest", + "sh:path": { + "@id": "build:configSourceDigest" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "configSourceUri", + "sh:path": { + "@id": "build:configSourceUri" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "buildId", + "sh:path": { + "@id": "build:buildId" + } + }, + { + "sh:class": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "parameters", + "sh:path": { + "@id": "build:parameters" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "buildEndTime", + "sh:path": { + "@id": "build:buildEndTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "buildStartTime", + "sh:path": { + "@id": "build:buildStartTime" + } + }, + { + "sh:class": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "environment", + "sh:path": { + "@id": "build:environment" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "buildType", + "sh:path": { + "@id": "build:buildType" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "configSourceEntrypoint", + "sh:path": { + "@id": "build:configSourceEntrypoint" + } + } + ] + }, + { + "@id": "core:Annotation", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An Annotation is an assertion made in relation to one or more elements.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "statement", + "sh:path": { + "@id": "core:statement" + } + }, + { + "sh:class": { + "@id": "core:Element" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "subject", + "sh:path": { + "@id": "core:subject" + } + }, + { + "sh:datatype": { + "@id": "core:MediaType" + }, + "sh:name": "contentType", + "sh:path": { + "@id": "core:contentType" + } + }, + { + "sh:class": { + "@id": "core:AnnotationType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "annotationType", + "sh:path": { + "@id": "core:annotationType" + } + } + ] + }, + { + "@id": "https://spdx.org/rdf/Core/AnnotationType/other", + "@type": [ + "owl:NamedIndividual", + "core:AnnotationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/AnnotationType/review", + "@type": [ + "owl:NamedIndividual", + "core:AnnotationType" + ] + }, + { + "@id": "core:AnonymousPayload", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "TODO", + "rdfs:subClassOf": { + "@id": "core:Payload" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "core:CreationInfo" + }, + "sh:maxCount": 1, + "sh:name": "creationInfo", + "sh:path": { + "@id": "core:creationInfo" + } + }, + { + "sh:class": { + "@id": "core:NamespaceMap" + }, + "sh:name": "namespaces", + "sh:path": { + "@id": "core:namespaces" + } + }, + { + "sh:class": { + "@id": "core:ExternalMap" + }, + "sh:name": "imports", + "sh:path": { + "@id": "core:imports" + } + } + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/cpe22", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/cpe23", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/cve", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/email", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/gitoid", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/other", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/pkgUrl", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/securityOther", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/swhid", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/swid", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/urlScheme", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/altDownloadLocation", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/altWebPage", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/binaryArtifact", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/buildMeta", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/buildSystem", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/chat", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/documentation", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/funding", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/issueTracker", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/license", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/mailingList", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/metrics", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/other", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/releaseHistory", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/releaseNotes", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/securityAdvisory", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/securityFix", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/securityOther", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/socialMedia", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/sourceArtifact", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/support", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/vcs", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/blake2b256", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/blake2b384", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/blake2b512", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/blake3", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/crystalsDilithium", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/crystalsKyber", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/falcon", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/md2", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/md4", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/md5", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/md6", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/other", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha1", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha224", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha256", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha384", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha3_224", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha3_256", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha3_384", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha3_512", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha512", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/spdxPvcSha1", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/spdxPvcSha256", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sphincsPlus", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/build", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/design", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/development", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/other", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/runtime", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/test", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType" + ] + }, + { + "@id": "core:Organization", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An Organization is a group of people who work together in an organized way for a shared purpose.", + "rdfs:subClassOf": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Person", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Person is an individual human being.", + "rdfs:subClassOf": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/ai", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/build", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/core", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/dataset", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/extension", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/licensing", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/security", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/software", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/usage", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipCompleteness/complete", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipCompleteness" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipCompleteness/incomplete", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipCompleteness" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipCompleteness/noAssertion", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipCompleteness" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/affects", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/amends", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/ancestor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/availableFrom", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildConfigOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildHostOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildInputOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildInvokedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildOnBehalfOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildOutputOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildTool", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/contains", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/coordinatedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/copy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/dataFile", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/dependencyManifest", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/dependsOn", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/descendant", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/describes", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/devDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/devTool", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/distributionArtifact", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/documentation", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/doesNotAffect", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/dynamicLink", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/example", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/expandedFromArchive", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/exploitCreatedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/fileAdded", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/fileDeleted", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/fileModified", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/fixedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/fixedIn", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/foundBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/generates", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/hasAssessmentFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/hasAssociatedVulnerability", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/metafile", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/optionalComponent", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/optionalDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/other", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/packages", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/patch", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/prerequisite", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/providedDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/publishedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/reportedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/republishedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/requirementFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/runtimeDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/specificationFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/staticLink", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/test", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/testCase", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/testDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/testTool", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/underInvestigationFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/RelationshipType/variant", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:SoftwareAgent", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A SoftwareAgent is a software program that is given the authority (similar to a user's authority) to act on a system.", + "rdfs:subClassOf": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:SpdxDocument", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An SpdxDocument assembles a collection of Elements under a common string, the name of the document.\nCommonly used when representing a unit of transfer of SPDX Elements.\nExternal property restriction on /Core/Element/name: minCount: 1", + "rdfs:subClassOf": { + "@id": "core:Bundle" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "name", + "sh:path": { + "@id": "core:name" + } + } + }, + { + "@id": "https://spdx.org/rdf/Dataset/ConfidentialityLevelType/Amber", + "@type": [ + "owl:NamedIndividual", + "dataset:ConfidentialityLevelType" + ] + }, + { + "@id": "https://spdx.org/rdf/Dataset/ConfidentialityLevelType/Clear", + "@type": [ + "owl:NamedIndividual", + "dataset:ConfidentialityLevelType" + ] + }, + { + "@id": "https://spdx.org/rdf/Dataset/ConfidentialityLevelType/Green", + "@type": [ + "owl:NamedIndividual", + "dataset:ConfidentialityLevelType" + ] + }, + { + "@id": "https://spdx.org/rdf/Dataset/ConfidentialityLevelType/Red", + "@type": [ + "owl:NamedIndividual", + "dataset:ConfidentialityLevelType" + ] + }, + { + "@id": "dataset:Dataset", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "Metadata information that can be added to a dataset that may be used in a software or to train/test an AI package.\nExternal property restriction on /Core/Artifact/originatedBy: minCount: 1\nExternal property restriction on /Software/Package/downloadLocation: minCount: 1\nExternal property restriction on /Software/SoftwareArtifact/purpose: minCount: 1\nExternal property restriction on /Core/Artifact/releaseTime: minCount: 1\nExternal property restriction on /Core/Artifact/builtTime: minCount: 1", + "rdfs:subClassOf": { + "@id": "software:Package" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "dataset:DatasetAvailabilityType" + }, + "sh:maxCount": 1, + "sh:name": "datasetAvailability", + "sh:path": { + "@id": "dataset:datasetAvailability" + } + }, + { + "sh:class": { + "@id": "dataset:ConfidentialityLevelType" + }, + "sh:maxCount": 1, + "sh:name": "confidentialityLevel", + "sh:path": { + "@id": "dataset:confidentialityLevel" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "dataCollectionProcess", + "sh:path": { + "@id": "dataset:dataCollectionProcess" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "datasetUpdateMechanism", + "sh:path": { + "@id": "dataset:datasetUpdateMechanism" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "knownBias", + "sh:path": { + "@id": "dataset:knownBias" + } + }, + { + "sh:datatype": { + "@id": "xsd:nonNegativeInteger" + }, + "sh:maxCount": 1, + "sh:name": "datasetSize", + "sh:path": { + "@id": "dataset:datasetSize" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "intendedUse", + "sh:path": { + "@id": "dataset:intendedUse" + } + }, + { + "sh:datatype": { + "@id": "dataset:PresenceType" + }, + "sh:maxCount": 1, + "sh:name": "sensitivePersonalInformation", + "sh:path": { + "@id": "dataset:sensitivePersonalInformation" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "dataPreprocessing", + "sh:path": { + "@id": "dataset:dataPreprocessing" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "datasetNoise", + "sh:path": { + "@id": "dataset:datasetNoise" + } + }, + { + "sh:class": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "sensor", + "sh:path": { + "@id": "dataset:sensor" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "datasetType", + "sh:path": { + "@id": "dataset:datasetType" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "anonymizationMethodUsed", + "sh:path": { + "@id": "dataset:anonymizationMethodUsed" + } + } + ] + }, + { + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Clickthrough", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Direct-Download", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Query", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Registration", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Scraping-Script", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "licensing:ConjunctiveLicenseSet", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A ConjunctiveLicenseSet indicates that _each_ of its subsidiary\nAnyLicenseInfos apply. In other words, a ConjunctiveLicenseSet of two or\nmore licenses represents a licensing situation where _all_ of the specified\nlicenses are to be complied with. It is represented in the SPDX License\nExpression Syntax by the `AND` operator.\n\nIt is syntactically correct to specify a ConjunctiveLicenseSet where the\nsubsidiary AnyLicenseInfos may be \"incompatible\" according to a particular\ninterpretation of the corresponding Licenses. The SPDX License Expression\nSyntax does not take into account interpretation of license texts, which is\nleft to the consumer of SPDX data to determine for themselves.", + "rdfs:subClassOf": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:class": { + "@id": "licensing:AnyLicenseInfo" + }, + "sh:minCount": 2, + "sh:name": "member", + "sh:path": { + "@id": "licensing:member" + } + } + }, + { + "@id": "licensing:CustomLicense", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A CustomLicense represents a License that is not listed on the SPDX License\nList at https://spdx.org/licenses, and is therefore defined by an SPDX data\ncreator.", + "rdfs:subClassOf": { + "@id": "licensing:License" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:CustomLicenseAddition", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A CustomLicenseAddition represents an addition to a License that is not listed\non the SPDX Exceptions List at https://spdx.org/licenses/exceptions-index.html,\nand is therefore defined by an SPDX data creator.\n\nIt is intended to represent additional language which is meant to be added to\na License, but which is not itself a standalone License.", + "rdfs:subClassOf": { + "@id": "licensing:LicenseAddition" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:DisjunctiveLicenseSet", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A DisjunctiveLicenseSet indicates that _only one_ of its subsidiary\nAnyLicenseInfos is required to apply. In other words, a\nDisjunctiveLicenseSet of two or more licenses represents a licensing\nsituation where _only one_ of the specified licenses are to be complied with.\nA consumer of SPDX data would typically understand this to permit the recipient\nof the licensed content to choose which of the corresponding license they\nwould prefer to use. It is represented in the SPDX License Expression Syntax\nby the `OR` operator.", + "rdfs:subClassOf": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:class": { + "@id": "licensing:AnyLicenseInfo" + }, + "sh:minCount": 2, + "sh:name": "member", + "sh:path": { + "@id": "licensing:member" + } + } + }, + { + "@id": "licensing:ListedLicense", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A ListedLicense represents a License that is listed on the SPDX License List\nat https://spdx.org/licenses.", + "rdfs:subClassOf": { + "@id": "licensing:License" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "deprecatedVersion", + "sh:path": { + "@id": "licensing:deprecatedVersion" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "listVersionAdded", + "sh:path": { + "@id": "licensing:listVersionAdded" + } + } + ] + }, + { + "@id": "licensing:ListedLicenseException", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A ListedLicenseException represents an exception to a License (in other words,\nan exception to a license condition or an additional permission beyond those\ngranted in a License) which is listed on the SPDX Exceptions List at\nhttps://spdx.org/licenses/exceptions-index.html.", + "rdfs:subClassOf": { + "@id": "licensing:LicenseAddition" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "deprecatedVersion", + "sh:path": { + "@id": "licensing:deprecatedVersion" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "listVersionAdded", + "sh:path": { + "@id": "licensing:listVersionAdded" + } + } + ] + }, + { + "@id": "licensing:NoAssertionLicense", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A NoAssertionLicense is the primary value that is used by a concludedLicense\nor declaredLicense field that indicates that the SPDX data creator is making\nno assertion about the license information for the corresponding software\nPackage, File or Snippet.\n\nThe specific meaning of NoAssertionLicense in the context of a\nconcludedLicense or declaredLicense field is more fully set forth in the\nProperty definitions for those fields.", + "rdfs:subClassOf": { + "@id": "licensing:LicenseField" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:NoneLicense", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A NoneLicense is the primary value that is used by a concludedLicense or\ndeclaredLicense field that indicates the absence of license information from\nthe corresponding software Package, File or Snippet.\n\nThe specific meaning of NoneLicense in the context of a concludedLicense or\ndeclaredLicense field is more fully set forth in the Property definitions for\nthose fields.", + "rdfs:subClassOf": { + "@id": "licensing:LicenseField" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:OrLaterOperator", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An OrLaterOperator indicates that this portion of the AnyLicenseInfo\nrepresents either (1) the specified version of the corresponding License, or\n(2) any later version of that License. It is represented in the SPDX License\nExpression Syntax by the `+` operator.\n\nIt is context-dependent, and unspecified by SPDX, as to what constitutes a\n\"later version\" of any particular License. Some Licenses may not be versioned,\nor may not have clearly-defined ordering for versions. The consumer of SPDX\ndata will need to determine for themselves what meaning to attribute to a\n\"later version\" operator for a particular License.", + "rdfs:subClassOf": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:class": { + "@id": "licensing:License" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "subjectLicense", + "sh:path": { + "@id": "licensing:subjectLicense" + } + } + }, + { + "@id": "licensing:WithAdditionOperator", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A WithAdditionOperator indicates that the designated License is subject to the\ndesignated LicenseAddition, which might be a license exception on the SPDX\nExceptions List (ListedLicenseException) or may be other additional text\n(CustomLicenseAddition). It is represented in the SPDX License Expression\nSyntax by the `WITH` operator.", + "rdfs:subClassOf": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "licensing:License" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "subjectLicense", + "sh:path": { + "@id": "licensing:subjectLicense" + } + }, + { + "sh:class": { + "@id": "licensing:LicenseAddition" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "subjectAddition", + "sh:path": { + "@id": "licensing:subjectAddition" + } + } + ] + }, + { + "@id": "security:CvssV2VulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A CvssV2VulnAssessmentRelationship relationship describes the determined score and vector of a vulnerability using version 2.0 of the Common Vulnerability Scoring System\n(CVSS) as defined on [https://www.first.org/cvss/v2/guide](https://www.first.org/cvss/v2/guide). It is intented to communicate the results of using a CVSS calculator.\n\n**Constraints**\n\n- The value of severity must be one of 'low', 'medium' or 'high'\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"CvssV2VulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:cvssv2-cve-2020-28498\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"score\": 4.3,\n \"vector\": \"(AV:N/AC:M/Au:N/C:P/I:N/A:N)\",\n \"severity\": \"low\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityFix\",\n \"locator\": \"https://github.com/indutny/elliptic/commit/441b742\"\n }\n ],\n \"suppliedBy\": [\"urn:spdx.dev:agent-my-security-vendor\"],\n \"publishedTime\": \"2023-05-06T10:06:13Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\", \n \"relationshipType\": \"publishedBy\", \n \"from\": \"urn:spdx.dev:cvssv2-cve-2020-28498\",\n \"to\": [\"urn:spdx.dev:agent-snyk\"],\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:decimal" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "score", + "sh:path": { + "@id": "security:score" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "severity", + "sh:path": { + "@id": "security:severity" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "vector", + "sh:path": { + "@id": "security:vector" + } + } + ] + }, + { + "@id": "security:CvssV3VulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A CvssV3VulnAssessmentRelationship relationship describes the determined score,\nseverity, and vector of a vulnerability using version 3.1 of the Common\nVulnerability Scoring System (CVSS) as defined on \n[https://www.first.org/cvss/v3.1/specification-document](https://www.first.org/cvss/v3.1/specification-document). It is intented to communicate the results of using a CVSS calculator.\n\n**Constraints**\n\n- The value of severity must be one of 'none', 'low', 'medium', 'high' or 'critical'.\n- Absence of the property shall be interpreted as 'none'.\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"CvssV3VulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:cvssv3-cve-2020-28498\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"severity\": \"medium\",\n \"score\": 6.8,\n \"vector\": \"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityFix\",\n \"locator\": \"https://github.com/indutny/elliptic/commit/441b742\"\n }\n ],\n \"suppliedBy\": [\"urn:spdx.dev:agent-my-security-vendor\"],\n \"publishedTime\": \"2023-05-06T10:06:13Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\",\n \"relationshipType\": \"publishedBy\",\n \"from\": \"urn:spdx.dev:cvssv3-cve-2020-28498\",\n \"to\": \"urn:spdx.dev:agent-snyk\",\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:decimal" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "score", + "sh:path": { + "@id": "security:score" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "vector", + "sh:path": { + "@id": "security:vector" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "severity", + "sh:path": { + "@id": "security:severity" + } + } + ] + }, + { + "@id": "security:EpssVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An EpssVulnAssessmentRelationship relationship describes the likelihood or\nprobability that a vulnerability will be exploited in the wild using the Exploit\nPrediction Scoring System (EPSS) as defined on \n[https://www.first.org/epss/model](https://www.first.org/epss/model).\n\n**Constraints**\n\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"EpssVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:epss-1\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"probability\": 80,\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:nonNegativeInteger" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "probability", + "sh:path": { + "@id": "security:probability" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "severity", + "sh:path": { + "@id": "security:severity" + } + } + ] + }, + { + "@id": "https://spdx.org/rdf/Security/ExploitCatalogType/kev", + "@type": [ + "owl:NamedIndividual", + "security:ExploitCatalogType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/ExploitCatalogType/other", + "@type": [ + "owl:NamedIndividual", + "security:ExploitCatalogType" + ] + }, + { + "@id": "security:ExploitCatalogVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An ExploitCatalogVulnAssessmentRelationship describes if a vulnerability is\nlisted in any exploit catalog such as the CISA Known Exploited Vulnerabilities\nCatalog (KEV) \n[https://www.cisa.gov/known-exploited-vulnerabilities-catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog).\n\n**Constraints**\n\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"ExploitCatalogVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:exploit-catalog-1\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"catalogType\": \"kev\",\n \"locator\": \"https://www.cisa.gov/known-exploited-vulnerabilities-catalog\",\n \"exploited\": \"true\",\n \"from\": \"urn:spdx.dev:vuln-cve-2023-2136\",\n \"to\": [\"urn:product-google-chrome-112.0.5615.136\"],\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "locator", + "sh:path": { + "@id": "security:locator" + } + }, + { + "sh:class": { + "@id": "security:ExploitCatalogType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "catalogType", + "sh:path": { + "@id": "security:catalogType" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "exploited", + "sh:path": { + "@id": "security:exploited" + } + } + ] + }, + { + "@id": "https://spdx.org/rdf/Security/SsvcDecisionType/act", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/SsvcDecisionType/attend", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/SsvcDecisionType/track", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/SsvcDecisionType/trackStar", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "security:SsvcVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An SsvcVulnAssessmentRelationship describes the decision made using the\nStakeholder-Specific Vulnerability Categorization (SSVC) decision tree as\ndefined on [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc).\nIt is intended to communicate the results of using the CISA SSVC Calculator.\n\n**Constraints**\n\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"SsvcVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:ssvc-1\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"decisionType\": \"act\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:class": { + "@id": "security:SsvcDecisionType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "decisionType", + "sh:path": { + "@id": "security:decisionType" + } + } + }, + { + "@id": "security:VexAffectedVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexAffectedVulnAssessmentRelationship connects a vulnerability and a number\nof elements. The relationship marks these elements as products affected by the\nvulnerability. This relationship corresponds to the VEX affected status.\n\n**Constraints**\n\nWhen linking elements using a VexAffectedVulnAssessmentRelationship, the\nfollowing requirements must be observed:\n\n- Elements linked with a VulnVexAffectedAssessmentRelationship are constrained\nto the affects relationship type.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"VexAffectedVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:vex-affected-1\",\n \"relationshipType\": \"affects\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"actionStatement\": \"Upgrade to version 1.4 of ACME application.\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VexVulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:name": "actionStatementTime", + "sh:path": { + "@id": "security:actionStatementTime" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "actionStatement", + "sh:path": { + "@id": "security:actionStatement" + } + } + ] + }, + { + "@id": "security:VexFixedVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexFixedVulnAssessmentRelationship links a vulnerability to a number of elements\nrepresenting VEX products where a vulnerability has been fixed and are no longer\naffected. It represents the VEX fixed status.\n\n**Constraints**\n\nWhen linking elements using a VexFixedVulnAssessmentRelationship, the following\nrequirements must be observed:\n\n- Elements linked with a VulnVexFixedAssessmentRelationship are constrained to\nusing the fixedIn relationship type.\n- The from: end of the relationship must ve a /Security/Vulnerability classed\nelement.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"VexFixedVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:vex-fixed-in-1\",\n \"relationshipType\": \"fixedIn\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.4\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VexVulnAssessmentRelationship" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/componentNotPresent", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/inlineMitigationsAlreadyExist", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/vulnerableCodeCannotBeControlledByAdversary", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/vulnerableCodeNotInExecutePath", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/vulnerableCodeNotPresent", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "security:VexNotAffectedVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexNotAffectedVulnAssessmentRelationship connects a vulnerability and a number\nof elements designating them as products not affected by the vulnerability.\nThis relationship corresponds to the VEX not_affected status.\n\n**Constraints**\n\nWhen linking elements using a VexNotVulnAffectedAssessmentRelationship, the\nfollowing requirements must be observed:\n\n* Relating elements with a VexNotAffectedVulnAssessmentRelationship is restricted\nto the doesNotAffect relationship type.\n* The from: end of the relationship must be a /Security/Vulnerability classed\nelement.\n* Both impactStatement and justificationType properties have a cardinality of\n0..1 making them optional. Nevertheless, to produce a valid VEX not_affected\nstatement, one of them MUST be defined. This is specified in the Minimum Elements\nfor VEX.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"VexNotAffectedVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:vex-not-affected-1\",\n \"relationshipType\": \"doesNotAffect\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"justificationType\": \"componentNotPresent\",\n \"impactStatement\": \"Not using this vulnerable part of this library.\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VexVulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "impactStatementTime", + "sh:path": { + "@id": "security:impactStatementTime" + } + }, + { + "sh:class": { + "@id": "security:VexJustificationType" + }, + "sh:maxCount": 1, + "sh:name": "justificationType", + "sh:path": { + "@id": "security:justificationType" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "impactStatement", + "sh:path": { + "@id": "security:impactStatement" + } + } + ] + }, + { + "@id": "security:VexUnderInvestigationVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexUnderInvestigationVulnAssessmentRelationship links a vulnerability to a\nnumber of products stating the vulnerability's impact on them is being\ninvestigated. It represents the VEX under_investigation status.\n\n**Constraints**\n\nWhen linking elements using a VexUnderInvestigationVulnAssessmentRelationship\nthe following requirements must be observed:\n\n- Elements linked with a VexUnderInvestigationVulnAssessmentRelationship are\nconstrained to using the underInvestigationFor relationship type.\n- The from: end of the relationship must ve a /Security/Vulnerability classed\nelement.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"VexUnderInvestigationVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:vex-underInvestigation-1\",\n \"relationshipType\": \"underInvestigationFor\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VexVulnAssessmentRelationship" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:Vulnerability", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "Specifies a vulnerability and its associated information.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"Vulnerability\",\n \"@id\": \"urn:spdx.dev:vuln-1\",\n \"summary\": \"Use of a Broken or Risky Cryptographic Algorithm\",\n \"description\": \"The npm package `elliptic` before version 6.5.4 are vulnerable to Cryptographic Issues via the secp256k1 implementation in elliptic/ec/key.js. There is no check to confirm that the public key point passed into the derive function actually exists on the secp256k1 curve. This results in the potential for the private key used in this implementation to be revealed after a number of ECDH operations are performed.\", \n \"modified\": \"2021-03-08T16:02:43Z\",\n \"published\": \"2021-03-08T16:06:50Z\",\n \"externalIdentifiers\": [\n {\n \"@type\": \"ExternalIdentifier\",\n \"externalIdentifierType\": \"cve\",\n \"identifier\": \"CVE-2020-2849\",\n \"identifierLocator\": [\n \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-28498\",\n \"https://www.cve.org/CVERecord?id=CVE-2020-28498\"\n ],\n \"issuingAuthority\": \"urn:spdx.dev:agent-cve.org\"\n },\n {\n \"type\": \"ExternalIdentifier\",\n \"externalIdentifierType\": \"securityOther\",\n \"identifier\": \"GHSA-r9p9-mrjm-926w\",\n \"identifierLocator\": \"https://github.com/advisories/GHSA-r9p9-mrjm-926w\"\n },\n {\n \"type\": \"ExternalIdentifier\",\n \"externalIdentifierType\": \"securityOther\",\n \"identifier\": \"SNYK-JS-ELLIPTIC-1064899\",\n \"identifierLocator\": \"https://security.snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n }\n ],\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://ubuntu.com/security/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityOther\",\n \"locator\": \"https://github.com/indutny/elliptic/pull/244/commits\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityOther\",\n \"locator\": \"https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md\"\n }\n ]\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnRelationship-1\",\n \"relationshipType\": \"hasAssociatedVulnerability\",\n \"from\": \"urn:npm-elliptic-6.5.2\",\n \"to\": [\"urn:spdx.dev:vuln-1\"],\n \"startTime\": \"2021-03-08T16:06:50Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\", \n \"relationshipType\": \"publishedBy\", \n \"from\": \"urn:spdx.dev:vuln-1\",\n \"to\": [\"urn:spdx.dev:agent-snyk\"],\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "publishedTime", + "sh:path": { + "@id": "security:publishedTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "modifiedTime", + "sh:path": { + "@id": "security:modifiedTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "withdrawnTime", + "sh:path": { + "@id": "security:withdrawnTime" + } + } + ] + }, + { + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/optional", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/other", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/prerequisite", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/provided", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/required", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType" + ] + }, + { + "@id": "software:File", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "Refers to any object that stores content on a computer.\nThe type of content can optionally be provided in the contentType property.\nExternal property restriction on /Core/Element/name: minCount: 1", + "rdfs:subClassOf": { + "@id": "software:SoftwareArtifact" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "core:MediaType" + }, + "sh:maxCount": 1, + "sh:name": "contentType", + "sh:path": { + "@id": "software:contentType" + } + } + }, + { + "@id": "https://spdx.org/rdf/Software/SBOMType/analyzed", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SBOMType/build", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SBOMType/deployed", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SBOMType/design", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SBOMType/runtime", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SBOMType/source", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "software:Sbom", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Software Bill of Materials (SBOM) is a collection of SPDX Elements describing a single package.\nThis could include details of the content and composition of the product,\nprovenance details of the product and/or\nits composition, licensing information, known quality or security issues, etc.", + "rdfs:subClassOf": { + "@id": "core:Bom" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:class": { + "@id": "software:SBOMType" + }, + "sh:name": "sbomType", + "sh:path": { + "@id": "software:sbomType" + } + } + }, + { + "@id": "software:Snippet", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Snippet describes a certain part of a file and can be used when the file is known to have some content\nthat has been included from another original source. Snippets are useful for denoting when part of a file\nmay have been originally created under another license or copied from a place with a known vulnerability.", + "rdfs:subClassOf": { + "@id": "software:SoftwareArtifact" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "core:PositiveIntegerRange" + }, + "sh:maxCount": 1, + "sh:name": "byteRange", + "sh:path": { + "@id": "software:byteRange" + } + }, + { + "sh:class": { + "@id": "core:PositiveIntegerRange" + }, + "sh:maxCount": 1, + "sh:name": "lineRange", + "sh:path": { + "@id": "software:lineRange" + } + } + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwareDependencyLinkType/dynamic", + "@type": [ + "owl:NamedIndividual", + "software:SoftwareDependencyLinkType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwareDependencyLinkType/other", + "@type": [ + "owl:NamedIndividual", + "software:SoftwareDependencyLinkType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwareDependencyLinkType/static", + "@type": [ + "owl:NamedIndividual", + "software:SoftwareDependencyLinkType" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwareDependencyLinkType/tool", + "@type": [ + "owl:NamedIndividual", + "software:SoftwareDependencyLinkType" + ] + }, + { + "@id": "software:SoftwareDependencyRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "TODO", + "rdfs:subClassOf": { + "@id": "core:LifecycleScopedRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "software:SoftwareDependencyLinkType" + }, + "sh:maxCount": 1, + "sh:name": "softwareLinkage", + "sh:path": { + "@id": "software:softwareLinkage" + } + }, + { + "sh:class": { + "@id": "software:DependencyConditionalityType" + }, + "sh:maxCount": 1, + "sh:name": "conditionality", + "sh:path": { + "@id": "software:conditionality" + } + } + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/application", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/archive", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/bom", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/configuration", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/container", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/data", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/device", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/documentation", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/evidence", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/executable", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/file", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/firmware", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/framework", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/install", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/library", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/manifest", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/module", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/operatingSystem", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/other", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/patch", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/requirement", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/source", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/specification", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "ai:autonomyType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "AutonomyType indicates if a human is involved in any of the decisions of the AI software\nor if that software is fully automatic.", + "rdfs:range": { + "@id": "ai:PresenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:domain", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Domain describes the domain in which the AI model contained in the AI software\ncan be expected to operate successfully. Examples include computer vision, natural language etc.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:energyConsumption", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "EnergyConsumption captures the amount of energy needed to train and operate the AI model. \nThis value is also known as training energy consumption or inference energy consumption.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:hyperparameter", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field records a hyperparameter value.\nHyperparameters are parameters of the machine learning model that are used to control the learning process,\nfor example the optimization and learning rate used during the training of the model.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:informationAboutApplication", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "InformationAboutApplication describes any relevant information in free form text about \nhow the AI model is used inside the software, as well as any relevant pre-processing steps, third party APIs etc.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:informationAboutTraining", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "InformationAboutTraining describes the specific steps involved in the training of the AI model.\nFor example, it can be specified whether supervised fine-tuning \nor active learning is used as part of training the model.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:limitation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Limitation captures a limitation of the AI Package (or of the AI models present in the AI package),\nexpressed as free form text. Note that this is not guaranteed to be exhaustive.\nFor instance, a limitation might be that the AI package cannot be used on datasets from a certain demography.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:metric", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Metric records the measurement with which the AI model was evaluated. \nThis makes statements about the prediction quality including uncertainty,\naccuracy, characteristics of the tested population, quality, fairness, explainability, robustness etc.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:metricDecisionThreshold", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Each metric might be computed based on a decision threshold. \nFor instance, precision or recall is typically computed by checking\nif the probability of the outcome is larger than 0.5.\nEach decision threshold should match with a metric field defined in the AI Package.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:modelDataPreprocessing", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ModelDataPreprocessing is a free form text that describes the preprocessing steps\napplied to the training data before training of the model(s) contained in the AI software.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:modelExplainability", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ModelExplainability is a free form text that lists the different explainability mechanisms\n(such as SHAP, or other model specific explainability mechanisms) that can be used to explain the model.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:safetyRiskAssessment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SafetyRiskAssessment categorizes the safety risk impact of the AI software\nin accordance with Article 20 of [EC Regulation No 765/2008](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).", + "rdfs:range": { + "@id": "ai:SafetyRiskAssessmentType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:sensitivePersonalInformation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SensitivePersonalInformation notes if sensitive personal information\nis used in the training or inference of the AI models.\nThis might include biometric data, addresses or other data that can be used to infer a person's identity.", + "rdfs:range": { + "@id": "ai:PresenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:standardCompliance", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "StandardCompliance captures a standard that the AI software complies with. \nThis includes both published and unpublished standards, for example ISO, IEEE, ETSI etc. \nThe standard could (but not necessarily have to) be used to satisfy a legal or regulatory requirement.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:typeOfModel", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TypeOfModel records the type of the AI model(s) used in the software. \nFor instance, if it is a supervised model, unsupervised model, reinforcement learning model or a combination of those.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildEndTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "buildEndTime describes the time at which a build stops or finishes. This value is typically recorded by the builder.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A buildId is a locally unique identifier to identify a unique instance of a build. This identifier differs based on build toolchain, platform, or naming convention used by an organization or standard.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildStartTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "buildStartTime is the time at which a build is triggered. The builder typically records this value.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A buildType is a URI expressing the toolchain, platform, or infrastructure that the build was invoked on. For example, if the build was invoked on GitHub's CI platform using github actions, the buildType can be expressed as `https://github.com/actions`. In contrast, if the build was invoked on a local machine, the buildType can be expressed as `file://username@host/path/to/build`.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:configSourceDigest", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "configSourceDigest is the checksum of the build configuration file used by a builder to execute a build. This Property uses the Core model's [Hash](../../Core/Classes/Hash.md) class.", + "rdfs:range": { + "@id": "core:Hash" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:configSourceEntrypoint", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A build entrypoint is the invoked executable of a build which always runs when the build is triggered. For example, when a build is triggered by running a shell script, the entrypoint is `script.sh`. In terms of a declared build, the entrypoint is the position in a configuration file or a build declaration which is always run when the build is triggered. For example, in the following configuration file, the entrypoint of the build is `publish`.\n\n```\nname: Publish packages to PyPI\n\non:\ncreate:\ntags: \"*\"\n\njobs:\npublish:\nruns-on: ubuntu-latest\nif: startsWith(github.ref, 'refs/tags/')\nsteps:\n\n...\n```", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:configSourceUri", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. \nm", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:environment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "environment is a map of environment variables and values that are set during a build session. This is different from the [parameters](parameters.md) property in that it describes the environment variables set before a build is invoked rather than the variables provided to the builder.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:parameters", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "parameters is a key-value map of all build parameters and their values that were provided to the builder for a build instance. This is different from the [environment](environment.md) property in that the keys and values are provided as command line arguments or a configuration file to the builder.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Artifact", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An artifact is a distinct article or unit within the digital domain,\nsuch as an electronic file, a software package, a device or an element of data.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "validUntilTime", + "sh:path": { + "@id": "core:validUntilTime" + } + }, + { + "sh:class": { + "@id": "core:Agent" + }, + "sh:name": "originatedBy", + "sh:path": { + "@id": "core:originatedBy" + } + }, + { + "sh:class": { + "@id": "core:Agent" + }, + "sh:name": "suppliedBy", + "sh:path": { + "@id": "core:suppliedBy" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "builtTime", + "sh:path": { + "@id": "core:builtTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "releaseTime", + "sh:path": { + "@id": "core:releaseTime" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "standard", + "sh:path": { + "@id": "core:standard" + } + } + ] + }, + { + "@id": "core:Bom", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Bill Of Materials (BOM) is a container for a grouping of SPDX-3.0 content\ncharacterizing details about a product.\nThis could include details of the content and composition of the product,\nprovenence details of the product and/or\nits composition, licensing information, known quality or security issues, etc.", + "rdfs:subClassOf": { + "@id": "core:Bundle" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:ElementCollection", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An SpdxCollection is a collection of Elements, not necessarily with unifying context.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "core:ExternalMap" + }, + "sh:name": "imports", + "sh:path": { + "@id": "core:imports" + } + }, + { + "sh:class": { + "@id": "core:Element" + }, + "sh:minCount": 1, + "sh:name": "rootElement", + "sh:path": { + "@id": "core:rootElement" + } + }, + { + "sh:class": { + "@id": "core:NamespaceMap" + }, + "sh:name": "namespaces", + "sh:path": { + "@id": "core:namespaces" + } + }, + { + "sh:class": { + "@id": "core:Element" + }, + "sh:minCount": 1, + "sh:name": "element", + "sh:path": { + "@id": "core:element" + } + } + ] + }, + { + "@id": "core:LifecycleScopedRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "TODO", + "rdfs:subClassOf": { + "@id": "core:Relationship" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:class": { + "@id": "core:LifecycleScopeType" + }, + "sh:maxCount": 1, + "sh:name": "scope", + "sh:path": { + "@id": "core:scope" + } + } + }, + { + "@id": "core:algorithm", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An algorithm specifies the algorithm that was used for calculating the hash value.", + "rdfs:range": { + "@id": "core:HashAlgorithm" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:annotationType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An annotationType describes the type of an annotation.", + "rdfs:range": { + "@id": "core:AnnotationType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:begin", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "begin is a positive integer that defines the beginning of a range.", + "rdfs:range": { + "@id": "xsd:positiveInteger" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:builtTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A builtTime specifies the time an artifact was built.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:completeness", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Completeness gives information about whether the provided relationships are\ncomplete, known to be incomplete or if no assertion is made either way.", + "rdfs:range": { + "@id": "core:RelationshipCompleteness" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:context", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A context gives information about the circumstances or unifying properties\nthat Elements of the bundle have been assembled under.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:created", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Created is a date that identifies when the Element was originally created.\nThe time stamp can serve as an indication as to whether the analysis needs to be updated. This is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:createdBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "CreatedBy identifies who or what created the Element.\nThe generation method will assist the recipient of the Element in assessing\nthe general reliability/accuracy of the analysis information.", + "rdfs:range": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:createdUsing", + "@type": "owl:ObjectProperty", + "rdfs:comment": "CreatedUsing identifies the tooling that was used during the creation of the Element.\nThe generation method will assist the recipient of the Element in assessing\nthe general reliability/accuracy of the analysis information.", + "rdfs:range": { + "@id": "core:Tool" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:dataLicense", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The data license provides the license under which the SPDX documentation of the Element can be used.\nThis is to alleviate any concern that content (the data or database) in an SPDX file\nis subject to any form of intellectual property right that could restrict the re-use\nof the information or the creation of another SPDX file for the same project(s).\nThis approach avoids intellectual property and related restrictions over the SPDX file,\nhowever individuals can still contract with each other to restrict release\nof specific collections of SPDX files (which map to software bill of materials)\nand the identification of the supplier of SPDX files.\nCompliance with this document includes populating the SPDX fields therein\nwith data related to such fields (\"SPDX-Metadata\"). \nThis document contains numerous fields where an SPDX file creator may provide\nrelevant explanatory text in SPDX-Metadata. Without opining on the lawfulness\nof \"database rights\" (in jurisdictions where applicable),\nsuch explanatory text is copyrightable subject matter in most Berne Convention countries.\nBy using the SPDX specification, or any portion hereof,\nyou hereby agree that any copyright rights (as determined by your jurisdiction)\nin any SPDX-Metadata, including without limitation explanatory text,\nshall be subject to the terms of the Creative Commons CC0 1.0 Universal license. \nFor SPDX-Metadata not containing any copyright rights, \nyou hereby agree and acknowledge that the SPDX-Metadata is provided to you “as-is”\nand without any representations or warranties of any kind concerning the SPDX-Metadata,\nexpress, implied, statutory or otherwise, including without limitation warranties\nof title, merchantability, fitness for a particular purpose, non-infringement,\nor the absence of latent or other defects, accuracy, or the presence or absence of errors,\nwhether or not discoverable, all to the greatest extent permissible under applicable law.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:definingDocument", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A definingDocument property is used to link an Element identifier to an SpdxDocument which contains the definition for the Element.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:description", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field is a detailed description of the Element. It may also be extracted from the Element itself.\nThe intent is to provide recipients of the SPDX file with a detailed technical explanation\nof the functionality, anticipated use, and anticipated implementation of the Element.\nThis field may also include a description of improvements over prior versions of the Element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:element", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field refers to one or more Elements that are part of an ElementCollection.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:end", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "end is a positive integer that defines the end of a range.", + "rdfs:range": { + "@id": "xsd:positiveInteger" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:endTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A endTime specifies the time from which element is no applicable / valid.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:extension", + "rdfs:comment": "TODO", + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ExternalId identifies an external Element used within a Document but defined external to that Document.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalIdentifier", + "@type": "owl:ObjectProperty", + "rdfs:comment": "ExternalIdentifier points to a resource outside the scope of SPDX-3.0 content\nthat uniquely identifies an Element.", + "rdfs:range": { + "@id": "core:ExternalIdentifier" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalIdentifierType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An externalIdentifierType specifies the type of the external identifier.", + "rdfs:range": { + "@id": "core:ExternalIdentifierType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalReference", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field points to a resource outside the scope of the SPDX-3.0 content\nthat provides additional characteristics of an Element.", + "rdfs:range": { + "@id": "core:ExternalReference" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalReferenceType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An externalReferenceType specifies the type of the external reference.", + "rdfs:range": { + "@id": "core:ExternalReferenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:from", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field references the Element on the left-hand side of a relationship.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:hashValue", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "HashValue is the result of applying a hash algorithm to an Element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:identifier", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An identifier uniquely identifies an external element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:identifierLocator", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A identifierLocator is TODO", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:issuingAuthority", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A issuingAuthority is TODO", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:key", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A key used in generic a key-value pair.\nA key-value pair can be used to implement a dictionary which associates a key with a value.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:locationHint", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A locationHint provides an indication of where to retrieve an external Element.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:locator", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A locator provides the location of an external reference.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:namespace", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A namespace provides an unambiguous mechanism for other documents to reference Elements within this document.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:originatedBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "OriginatedBy identifies from where or whom the Element originally came.", + "rdfs:range": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:prefix", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A prefix is a substitute for a URI.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:profile", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field provides information about which profiles the Element belongs to.", + "rdfs:range": { + "@id": "core:ProfileIdentifierType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:relationshipType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field provides information about the relationship between two Elements.\nFor example, you can represent a relationship between two different Files,\nbetween a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument.", + "rdfs:range": { + "@id": "core:RelationshipType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:releaseTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A releaseTime specifies the time an artifact was released.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:rootElement", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A rootElement of a collection is the top level Element from which all other Elements are reached via relationships.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:scope", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A scope is TODO", + "rdfs:range": { + "@id": "core:LifecycleScopeType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:specVersion", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The specVersion provides a reference number that can be used to understand how to parse and interpret an Element.\nIt will enable both future changes to the specification and to support backward compatibility.\nThe major version number shall be incremented when incompatible changes between versions are made\n(one or more sections are created, modified or deleted).\nThe minor version number shall be incremented when backwards compatible changes are made.\n\nHere, parties exchanging information in accordance with the SPDX specification need to provide \n100% transparency as to which SPDX specification version such information is conforming to.", + "rdfs:range": { + "@id": "core:SemVer" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:standard", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Various standards may be relevant to useful to capture for specific artifacts.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:startTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A startTime specifies the time from which element is applicable / valid.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:statement", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A statement is a commentary on an assertion that an annotator has made.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:subject", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A subject is an Element an annotator has made an assertion about.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:summary", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A summary is a short description of an Element. Here, the intent is to allow the Element creator to \nprovide concise information about the function or use of the Element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:suppliedBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "Identify the actual distribution source for the Artifact being referenced.\nThis might or might not be different from the originating distribution source for the artifact.", + "rdfs:range": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:to", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field references an Element on the right-hand side of a relationship.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:validUntilTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A validUntilTime specifies until when the artifact can be used before its usage needs to be reassessed.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:value", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A value used in a generic key-value pair.\nA key-value pair can be used to implement a dictionary which associates a key with a value.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:anonymizationMethodUsed", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "AnonymizationMethodUsed describes the methods used to anonymize the dataset (of fields in the dataset).", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:confidentialityLevel", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ConfidentialityLevel describes the levels of confidentiality of the data points contained in the dataset.", + "rdfs:range": { + "@id": "dataset:ConfidentialityLevelType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:dataCollectionProcess", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DataCollectionProcess describes how a dataset was collected.\nExamples include the sources from which a dataset was scrapped or\nthe interview protocol that was used for data collection.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:dataPreprocessing", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DataPreprocessing describes the various preprocessing steps\nthat were applied to the raw data to create the dataset.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetAvailability", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Some datasets are publicly available and can be downloaded directly. Others are only accessible behind a clickthrough, or after filling a registration form. This field will describe the dataset availability from that perspective.", + "rdfs:range": { + "@id": "dataset:DatasetAvailabilityType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetNoise", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DatasetNoise describes what kinds of noises a dataset might encompass.\nThe field uses free form text to specify the fields or the samples that might be noisy.\nAlternatively, it can also be used to describe various noises that could impact the whole dataset.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetSize", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DatasetSize Captures how large a dataset is.\nThe size is to be measured in bytes.", + "rdfs:range": { + "@id": "xsd:nonNegativeInteger" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Type describes the datatype contained in the dataset. For example a dataset can be a image dataset or a text dataset or sometimes a multimodal dataset that contains multiple types of data", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetUpdateMechanism", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DatasetUpdateMechanism describes a mechanism to update the dataset.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:intendedUse", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "IntendedUse describes what the given dataset should be used for.\nSome datasets are collected to be used only for particular purposes. \nFor example, medical data collected from a specific demography might only be applicable\nfor training machine learning models to make predictions for that demography.\nIn such a case, the intendedUse field would capture this information.\nSimilarly, if a dataset is collected for building a facial recognition model,\nthe intendedUse field would specify that.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:knownBias", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "KnownBias is a free form text field that describes the different biases that the dataset encompasses.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:sensitivePersonalInformation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SensitivePersonalInformation indicates the presence of sensitive personal data\nor information that allows drawing conclusions about a person's identity.", + "rdfs:range": { + "@id": "dataset:PresenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:sensor", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Sensor describes a sensor that was used for collecting the data\nand its calibration value as a key-value pair.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:additionComment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An additionComment for a LicenseAddition describes general factual information\nabout the LicenseAddition. It should not contain information (or links to\ninformation) that includes any kind of interpretation about the meaning or\neffect of the License, even if written by the license addition's author.\n\nExamples of information for an additionComment may include the following:\n\n* If the LicenseAddition's identifier is deprecated, it may briefly explain the\n reason for deprecation.\n* It may include the date of release, if identified, for LicenseAdditions with\n multiple versions.\n* It may include links to other official language translations for the\n LicenseAddition.\n* It may include a reference to the License(s) with which this LicenseAddition\n is typically used.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:additionId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An additionId contains a human-readable, short-form identifier for a\nLicenseAddition. It may only include letters, numbers, period (\".\") and\nhyphen (\"-\") characters.\n\nFor a ListedLicenseException, the licenseId will be as specified on the\n[SPDX Exceptions List](https://spdx.org/licenses/exceptions-index.html) for the\nparticular exception.\n\nFor a CustomLicenseAddition, the short-form identifier must begin with the\nprefix `AdditionRef-` and must be unique within the applicable SPDX namespace.\nThe short-form identifier may be preceded by an SPDX namespace or a\nfully-qualified URI prefix.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:additionName", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An additionName contains the full name of a LicenseAddition, preferably using\nthe title found in the applicable license addition text or file, or as\notherwise specified by the LicenseAddition's author or steward.\n\nWhen no such title is specified, using a name from another well-known source or list\nof licenses additions (such as OSI or Fedora) is suggested.\n\nIf no official or common name is known, any name may be used to aid in\ndistinguishing the LicenseAddition from other LicenseAdditions.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:additionText", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An additionText contains the plain text of the LicenseAddition, without\ntemplating or other similar markup.\n\nUsers of the additionText for a License can apply the SPDX Matching Guidelines\nwhen comparing it to another text for matching purposes.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:isDeprecatedAdditionId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The isDeprecatedAdditionId property specifies whether an identifier for a\nLicenseAddition has been marked as deprecated. If the property is not defined,\nthen it is presumed to be false (i.e., not deprecated).\n\nIf the LicenseAddition is included on the SPDX Exceptions List, then\nthe `deprecatedVersion` property indicates on which version release of the\nExceptions List it was first marked as deprecated.\n\n\"Deprecated\" in this context refers to deprecating the use of the\n_identifier_, not the underlying license addition. In other words, even if a\nLicenseAddition's author or steward has stated that a particular\nLicenseAddition generally should not be used, that would _not_ mean that the\nLicenseAddition's identifier is \"deprecated.\" Rather, a LicenseAddition\noperator is typically marked as \"deprecated\" when it is determined that use of\nanother identifier is preferable.", + "rdfs:range": { + "@id": "xsd:boolean" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:isDeprecatedLicenseId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The isDeprecatedLicenseId property specifies whether an identifier for a\nLicense or LicenseAddition has been marked as deprecated. If the property\nis not defined, then it is presumed to be false (i.e., not deprecated).\n\nIf the License or LicenseAddition is included on the SPDX License List, then\nthe `deprecatedVersion` property indicates on which version release of the\nLicense List it was first marked as deprecated.\n\n\"Deprecated\" in this context refers to deprecating the use of the\n_identifier_, not the underlying license. In other words, even if a License's\nauthor or steward has stated that a particular License generally should not be\nused, that would _not_ mean that the License's identifier is \"deprecated.\"\nRather, a License or LicenseAddition operator is typically marked as\n\"deprecated\" when it is determined that use of another identifier is\npreferable.", + "rdfs:range": { + "@id": "xsd:boolean" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:isFsfLibre", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "isFsfLibre specifies whether the [Free Software Foundation FSF](https://fsf.org)\nhas listed this License as \"free\" in their commentary on licenses, located at\nthe time of this writing at https://www.gnu.org/licenses/license-list.en.html.\n\nA value of \"true\" indicates that the FSF has listed this License as _free_.\n\nA value of \"false\" indicates that the FSF has listed this License as _not free_.\n\nIf the isFsfLibre field is not specified, the SPDX data creator makes no\nassertions about whether the License is listed in the FSF's commentary.", + "rdfs:range": { + "@id": "xsd:boolean" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:isOsiApproved", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "isOsiApproved specifies whether the [Open Source Initiative (OSI)](https://opensource.org)\nhas listed this License as \"approved\" in their list of OSI Approved Licenses,\nlocated at the time of this writing at https://opensource.org/licenses/.\n\nA value of \"true\" indicates that the OSI has listed this License as approved.\n\nA value of \"false\" indicates that the OSI has not listed this License as\napproved.\n\nIf the isOsiApproved field is not specified, the SPDX data creator makes no\nassertions about whether the License is approved by the OSI.", + "rdfs:range": { + "@id": "xsd:boolean" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:licenseComment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A licenseComment describes general factual information about the License. It\nshould not contain information (or links to information) that includes any kind\nof interpretation about the meaning or effect of the License, even if written\nby the license's author.\n\nExamples of information for a licenseComment may include the following:\n\n* If the License's identifier is deprecated, it may briefly explain the reason\n for deprecation.\n* It may include the date of release, if identified, for Licenses with multiple\n versions.\n* It may include links to other official language translations for the License.\n* For LicenseAdditions, it may include a reference to the License(s) with\n which this additional text is typically used.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:licenseId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A licenseId contains a human-readable, short-form license identifier for a\nLicense. It may only include letters, numbers, period (\".\") and hyphen (\"-\")\ncharacters.\n\nFor a ListedLicense, the licenseId will be as specified on the\n[SPDX License List](https://spdx.org/licenses) for the particular license.\n\nFor a CustomLicense, the short-form license identifer must begin with the\nprefix `LicenseRef-` and must be unique within the applicable SPDX namespace.\nThe short-form license ID may be preceded by an SPDX namespace or a\nfully-qualified URI prefix.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:licenseName", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A licenseName contains the full name of a License, preferably using the title found\nin the applicable license text or file, or as otherwise specified by the\nLicense's author or steward.\n\nWhen no such title is specified, using a name from another well-known source or list\nof licenses (such as OSI or Fedora) is suggested.\n\nIf no official or common name is known, any name may be used to aid in\ndistinguishing the License from other Licenses.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:licenseText", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A licenseText contains the plain text of the License, without templating\nor other similar markup.\n\nUsers of the licenseText for a License can apply the SPDX Matching Guidelines\nwhen comparing it to another text for matching purposes.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:standardAdditionTemplate", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A standardAdditionTemplate contains a license addition template which describes\nsections of the LicenseAddition text which can be varied. See the Legacy Text\nTemplate format section of the SPDX specification for format information.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:standardLicenseHeader", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A standardLicenseHeader contains the plain text of the License author's\npreferred wording to be used, typically in a source code file's header\ncomments or similar location, to indicate that the file is subject to\nthe specified License.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:standardLicenseTemplate", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A standardLicenseTemplate contains a license template which describes\nsections of the License text which can be varied. See the Legacy Text Template\nformat section of the SPDX specification for format information.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:subjectAddition", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A subjectAddition is a LicenseAddition which is subject to a 'with additional\ntext' effect (WithAdditionOperator).", + "rdfs:range": { + "@id": "licensing:LicenseAddition" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:actionStatement", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "When an element is referenced with a VexAffectedVulnAssessmentRelationship,\nthe relationship MUST include one actionStatement that SHOULD describe actions\nto remediate or mitigate the vulnerability.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:actionStatementTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TODO", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:assessedElement", + "@type": "owl:ObjectProperty", + "rdfs:comment": "Specifies subpackages, files or snippets referenced by a security assessment\nto specify the precise location where a vulnerability was found.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:catalogType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A catalogType is a mandatory value and must select one of the two entries in the `ExploitCatalogType.md` vocabulary.", + "rdfs:range": { + "@id": "security:ExploitCatalogType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:decisionType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A decisionType is a mandatory value and must select one of the four entries in the `SsvcDecisionType.md` vocabulary.", + "rdfs:range": { + "@id": "security:SsvcDecisionType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:exploited", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field is set when a CVE is listed in an exploit catalog.", + "rdfs:range": { + "@id": "xsd:boolean" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:impactStatement", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "When a VEX product element is related with a VexNotAffectedVulnAssessmentRelationship\nand a machine readable justification label is not provided, then an impactStatement\nthat further explains how or why the prouct(s) are not affected by the vulnerability\nmust be provided.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:impactStatementTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TODO", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:justificationType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "When stating that an element is not affected by a vulnerability, the\nVexNotAffectedVulnAssessmentRelationship must include a justification from the\nmachine-readable labels catalog informing the reason the element is not impacted.\n\nimpactStatement which is a string with English prose can be used instead or as\ncomplementary to the justification label, but one of both MUST be defined.", + "rdfs:range": { + "@id": "security:VexJustificationType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:locator", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A locator provides the location of an exploit catalog.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:probability", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The probability score between 0 and 1 (0 and 100%) estimating the likelihood\nthat a vulnerability will be exploited in the next 12 months.", + "rdfs:range": { + "@id": "xsd:decimal" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:statusNotes", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TODO", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:suppliedBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "Identify the actual distribution source for the vulnerability assessment relationship being referenced.", + "rdfs:range": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:vexVersion", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TODO", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:additionalPurpose", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Additional purpose provides information about the additional purposes of the software artifact in addition to the primaryPurpose.", + "rdfs:range": { + "@id": "software:SoftwarePurpose" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:attributionText", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An attributionText for a software Package, File or Snippet provides a consumer\nof SPDX data with acknowledgement content, to assist redistributors of the\nPackage, File or Snippet with reproducing those acknowledgements.\n\nFor example, this field may include a statement that is required by a\nparticular license to be reproduced in end-user documentation, advertising\nmaterials, or another form.\n\nThis field may describe where, or in which contexts, the acknowledgements\nneed to be reproduced, but it is not required to do so. The SPDX data creator\nmay also explain elsewhere (such as in a licenseComment field) how they intend\nfor data in this field to be used.\n\nAn attributionText is is not meant to include the software Package, File or\nSnippet’s actual complete license text (see concludedLicense to identify the\ncorresponding license).", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:byteRange", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field defines the byte range in the original host file that the snippet information applies to.\nA range of bytes is independent of various formatting concerns, and the most accurate way \nof referring to the differences. The choice was made to start the numbering of \nthe byte range at 1 to be consistent with the W3C pointer method vocabulary.", + "rdfs:range": { + "@id": "core:PositiveIntegerRange" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:concludedLicense", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A concludedLicense is the license identified by the SPDX data creator,\nbased on analyzing the license information in the software Package, File\nor Snippet and other information to arrive at a reasonably objective\nconclusion as to what license governs it.\n\nIf a concludedLicense has a NONE value (NoneLicense), this indicates that the\nSPDX data creator has looked and did not find any license information for this\nsoftware Package, File or Snippet.\n\nIf a concludedLicense has a NOASSERTION value (NoAssertionLicense), this\nindicates that one of the following applies:\n* the SPDX data creator has attempted to but cannot reach a reasonable\n objective determination;\n* the SPDX data creator has made no attempt to determine this field; or\n* the SPDX data creator has intentionally provided no information (no\n meaning should be implied by doing so).\n\nA written explanation of a NOASSERTION value (NoAssertionLicense) MAY be\nprovided in the licenseComment field.\n\nIf the concludedLicense for a software Package, File or Snippet is not the\nsame as its declaredLicense, a written explanation SHOULD be provided in\nthe licenseComment field.\n\nIf the declaredLicense for a software Package, File or Snippet is a choice\nof more than one license (e.g. a license expression combining two licenses\nthrough use of the `OR` operator), then the concludedLicense may either\nretain the license choice or identify which license was chosen.", + "rdfs:range": { + "@id": "licensing:LicenseField" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:conditionality", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A conditionality is TODO", + "rdfs:range": { + "@id": "software:DependencyConditionalityType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:contentIdentifier", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A contentIdentifier is TODO", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:contentType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field is a reasonable estimation of the content type of the Element, from a creator perspective.\nContent type is intrinsic to the Element, independent of how the Element is being used.", + "rdfs:range": { + "@id": "core:MediaType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:copyrightText", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A copyrightText consists of the text(s) of the copyright notice(s) found\nfor a software Package, File or Snippet, if any.\n\nIf a copyrightText contains text, then it may contain any text related to\none or more copyright notices (even if not complete) for that software\nPackage, File or Snippet.\n\nIf a copyrightText has a \"NONE\" value, this indicates that the software\nPackage, File or Snippet contains no copyright notice whatsoever.\n\nIf a copyrightText has a \"NOASSERTION\" value, this indicates that one of the\nfollowing applies:\n* the SPDX data creator has attempted to but cannot reach a reasonable\n objective determination;\n* the SPDX data creator has made no attempt to determine this field; or\n* the SPDX data creator has intentionally provided no information (no\n meaning should be implied by doing so).", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:declaredLicense", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A declaredLicense is the license identified in text in the software package,\nfile or snippet as the license declared by its authors.\n\nThis field is not intended to capture license information obtained from an\nexternal source, such as a package's website. Such information can be\nincluded, as needed, in a concludedLicense field.\n\nA declaredLicense may be expressed differently in practice for different\ntypes of artifacts. For example:\n\n* for Packages:\n * would include license info describing the license of the Package as a\n whole, when it is found in the Package itself (e.g., LICENSE file,\n README file, metadata in the repository, etc.)\n * would not include any license information that is not in the Package\n itself (e.g., license information from the project’s website or from a\n third party repository or website)\n* for Files:\n * would include license info found in the File itself (e.g., license\n header or notice, comments, SPDX-License-Identifier expression)\n * would not include license info found in a different file (e.g., LICENSE\n file in the top directory of a repository)\n* for Snippets:\n * would include license info found in the Snippet itself (e.g., license\n notice, comments, SPDX-License-Identifier expression)\n * would not include license info found elsewhere in the File or in a\n different File (e.g., comment at top of File if it is not within the\n Snippet, LICENSE file in the top directory of a repository)\n\nIf a declaredLicense has a NONE value (NoneLicense), this indicates that the\ncorresponding Package, File or Snippet contains no license information\nwhatsoever.\n\nIf a declaredLicense has a NOASSERTION value (NoAssertionLicense), this\nindicates that one of the following applies:\n* the SPDX data creator has attempted to but cannot reach a reasonable\n objective determination;\n* the SPDX data creator has made no attempt to determine this field; or\n* the SPDX data creator has intentionally provided no information (no meaning\n should be implied by doing so).", + "rdfs:range": { + "@id": "licensing:LicenseField" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:downloadLocation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DownloadLocation identifies the download Uniform Resource Identifier \nfor the package at the time that the document was created.\nWhere and how to download the exact package being referenced \nis critical for verification and tracking data.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:homePage", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "HomePage is a place for the SPDX document creator to record a website that serves as the package's home page.\nThis saves the recipient of the SPDX document who is looking for more info from\nhaving to search for and verify a match between the package and the associated project home page.\nThis link can also be used to reference further information about the package\nreferenced by the SPDX document creator.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:lineRange", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field defines the line range in the original host file that the snippet information applies to.\nIf there is a disagreement between the byte range and line range, the byte range values will take precedence.\nA range of lines is a convenient reference for those files where there is a known line delimiter. \nThe choice was made to start the numbering of the lines at 1 to be consistent with the W3C pointer method vocabulary.", + "rdfs:range": { + "@id": "core:PositiveIntegerRange" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:packageUrl", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A packageUrl is TODO", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:packageVersion", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A packageVersion is useful for identification purposes and for indicating later changes of the package version.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:primaryPurpose", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "primaryPurpose provides information about the primary purpose of the software artifact.", + "rdfs:range": { + "@id": "software:SoftwarePurpose" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:sbomType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field is a reasonable estimation of the type of SBOM created from a creator perspective.\nIt is intended to be used to give guidance on the elements that may be contained within it.\nAligning with the guidance produced in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf).", + "rdfs:range": { + "@id": "software:SBOMType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:softwareLinkage", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A softwareLinkage is TODO", + "rdfs:range": { + "@id": "software:SoftwareDependencyLinkType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:sourceInfo", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SourceInfo records any relevant background information or additional comments\nabout the origin of the package. For example, this field might include comments \nindicating whether the package was pulled from a source code management system \nor has been repackaged. The creator can provide additional information to describe\nany anomalies or discoveries in the determination of the origin of the package.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Bundle", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A bundle is a collection of Elements that have a shared context.", + "rdfs:subClassOf": { + "@id": "core:ElementCollection" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "context", + "sh:path": { + "@id": "core:context" + } + } + }, + { + "@id": "core:ExternalIdentifier", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An ExternalIdentifier is a reference to a resource outside the scope of SPDX-3.0 content\nthat uniquely identifies an Element.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "identifier", + "sh:path": { + "@id": "core:identifier" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "identifierLocator", + "sh:path": { + "@id": "core:identifierLocator" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "issuingAuthority", + "sh:path": { + "@id": "core:issuingAuthority" + } + }, + { + "sh:class": { + "@id": "core:ExternalIdentifierType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "externalIdentifierType", + "sh:path": { + "@id": "core:externalIdentifierType" + } + } + ] + }, + { + "@id": "core:ExternalReference", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An External Reference points to a resource outside the scope of the SPDX-3.0 content\nthat provides additional characteristics of an Element.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "core:ExternalReferenceType" + }, + "sh:maxCount": 1, + "sh:name": "externalReferenceType", + "sh:path": { + "@id": "core:externalReferenceType" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "locator", + "sh:path": { + "@id": "core:locator" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + }, + { + "sh:datatype": { + "@id": "core:MediaType" + }, + "sh:maxCount": 1, + "sh:name": "contentType", + "sh:path": { + "@id": "core:contentType" + } + } + ] + }, + { + "@id": "core:Hash", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A hash is a grouping of characteristics unique to the result\nof applying a mathematical algorithm\nthat maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is,\na function which is practically infeasible to invert.\nThis is commonly used for integrity checking of data.", + "rdfs:subClassOf": { + "@id": "core:IntegrityMethod" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "core:HashAlgorithm" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "algorithm", + "sh:path": { + "@id": "core:algorithm" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "hashValue", + "sh:path": { + "@id": "core:hashValue" + } + } + ] + }, + { + "@id": "core:Payload", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "TODO", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "core:NamespaceMap" + }, + "sh:name": "namespaces", + "sh:path": { + "@id": "core:namespaces" + } + }, + { + "sh:class": { + "@id": "core:ExternalMap" + }, + "sh:name": "imports", + "sh:path": { + "@id": "core:imports" + } + }, + { + "sh:class": { + "@id": "core:CreationInfo" + }, + "sh:maxCount": 1, + "sh:name": "creationInfo", + "sh:path": { + "@id": "core:creationInfo" + } + } + ] + }, + { + "@id": "core:Relationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Relationship is a grouping of characteristics unique to an assertion\nthat one Element is related to one or more other Elements in some way.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "endTime", + "sh:path": { + "@id": "core:endTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "startTime", + "sh:path": { + "@id": "core:startTime" + } + }, + { + "sh:class": { + "@id": "core:Element" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "from", + "sh:path": { + "@id": "core:from" + } + }, + { + "sh:class": { + "@id": "core:Element" + }, + "sh:name": "to", + "sh:path": { + "@id": "core:to" + } + }, + { + "sh:class": { + "@id": "core:RelationshipCompleteness" + }, + "sh:maxCount": 1, + "sh:name": "completeness", + "sh:path": { + "@id": "core:completeness" + } + }, + { + "sh:class": { + "@id": "core:RelationshipType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "relationshipType", + "sh:path": { + "@id": "core:relationshipType" + } + } + ] + }, + { + "@id": "core:SemVer", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "The semantic version is a string\nthat is following the specification of [Semantic Versioning 2.0.0](https://semver.org/).\nFormat restriction: pattern: ^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", + "rdfs:subClassOf": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Tool", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Tool is an element of hardware and/or software utilized to carry out a particular function.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:contentType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ContentType specifies the media type of an Element.", + "rdfs:range": { + "@id": "core:MediaType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:name", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field identifies the name of an Element as designated by the creator. \nThe name of an Element is an important convention and easier to refer to than the URI.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:verifiedUsing", + "@type": "owl:ObjectProperty", + "rdfs:comment": "VerifiedUsing provides an IntegrityMethod with which the integrity of an Element can be asserted.", + "rdfs:range": { + "@id": "core:IntegrityMethod" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:deprecatedVersion", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A deprecatedVersion for a ListedLicense or ListedLicenseException on the SPDX\nLicense List specifies which version release of the License List was the first\none in which it was marked as deprecated.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:listVersionAdded", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A listVersionAdded for a ListedLicense or ListedLicenseException on the SPDX\nLicense List specifies which version release of the License List was the first\none in which it was included.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:member", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A member is a license expression participating in a conjuctive (of type\nConjunctiveLicenseSet) or a disjunctive (of type DisjunctiveLicenseSet)\nlicense set.", + "rdfs:range": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:obsoletedBy", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An obsoletedBy value for a deprecated License or LicenseAddition specifies\nthe licenseId of the replacement License or LicenseAddition that is preferred\nto be used in its place. It should use the same format as specified for a\nlicenseId.\n\nThe License's or LicenseAddition's comment value may include more information\nabout the reason why the licenseId specified in the obsoletedBy value is\npreferred.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:seeAlso", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A seeAlso defines a cross-reference with a URL where the License or\nLicenseAddition can be found in use by one or a few projects.\n\nIf applicable, it should include a URL where the license text is posted by\nthe license steward, particularly if the license steward has made available a\n\"canonical\" primary URL for the license text.\n\nIf the license is OSI approved, a seeAlso should be included with the URL for\nthe license's listing on the OSI website.\n\nThe seeAlso URL may refer to a previously-available URL for the License or\nLicenseAddition which is no longer active.\n\nWhere applicable, the seeAlso URL should include the license text in its\nnative language. seeAlso URLs to English or other translations may be included\nwhere multiple, equivalent official translations exist.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:subjectLicense", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A subjectLicense is a License which is subject to either an 'or later' effect\n(OrLaterOperator) or a 'with additional text' effect (WithAdditionOperator).", + "rdfs:range": { + "@id": "licensing:License" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:modifiedTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Specifies a time when a vulnerability assessment was last modified.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:publishedTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Specifies the time when a vulnerability was first published.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:score", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The score provides information on the severity of a vulnerability per the\nCommon Vulnerability Scoring System as defined on [https://www.first.org/cvss](https://www.first.org/cvss/).", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:vector", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Sepcifies the vector string of a vulnerability, a string combining metrics\nfrom an assessment of its severity.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:withdrawnTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Specified the time and date when a vulnerability was withdrawn.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:Package", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A package refers to any unit of content that can be associated with a distribution of software.\nTypically, a package is composed of one or more files. \nAny of the following non-limiting examples may be (but are not required to be) represented in SPDX as a package:\n\n - a tarball, zip file or other archive\n - a directory or sub-directory\n - a separately distributed piece of software which another Package or File uses or depends upon (e.g., a Python package, a Go module, ...)\n - a container image, and/or each image layer within a container image\n - a collection of one or more sub-packages\n - a Git repository snapshot from a particular point in time\n\nNote that some of these could be represented in SPDX as a file as well.\nExternal property restriction on /Core/Element/name: minCount: 1", + "rdfs:subClassOf": { + "@id": "software:SoftwareArtifact" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "homePage", + "sh:path": { + "@id": "software:homePage" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "packageVersion", + "sh:path": { + "@id": "software:packageVersion" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "packageUrl", + "sh:path": { + "@id": "software:packageUrl" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "sourceInfo", + "sh:path": { + "@id": "software:sourceInfo" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "downloadLocation", + "sh:path": { + "@id": "software:downloadLocation" + } + } + ] + }, + { + "@id": "core:creationInfo", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "CreationInfo provides information about the creation of the Element.", + "rdfs:range": { + "@id": "core:CreationInfo" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:imports", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Imports provides an ExternalMap of Element identifiers that are used within a document\nbut defined external to that document.", + "rdfs:range": { + "@id": "core:ExternalMap" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:namespaces", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field provides a NamespaceMap applicable to an ElementCollection.", + "rdfs:range": { + "@id": "core:NamespaceMap" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:severity", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The severity field provides a human readable string, a label that can be used\nas an English adjective that qualifies its numerical score.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:SoftwareArtifact", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A software artifact is a distinct article or unit related to software\nsuch as a package, a file, or a snippet.", + "rdfs:subClassOf": { + "@id": "core:Artifact" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "contentIdentifier", + "sh:path": { + "@id": "software:contentIdentifier" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "attributionText", + "sh:path": { + "@id": "software:attributionText" + } + }, + { + "sh:class": { + "@id": "licensing:LicenseField" + }, + "sh:maxCount": 1, + "sh:name": "declaredLicense", + "sh:path": { + "@id": "software:declaredLicense" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "copyrightText", + "sh:path": { + "@id": "software:copyrightText" + } + }, + { + "sh:class": { + "@id": "software:SoftwarePurpose" + }, + "sh:maxCount": 1, + "sh:name": "primaryPurpose", + "sh:path": { + "@id": "software:primaryPurpose" + } + }, + { + "sh:class": { + "@id": "licensing:LicenseField" + }, + "sh:maxCount": 1, + "sh:name": "concludedLicense", + "sh:path": { + "@id": "software:concludedLicense" + } + }, + { + "sh:class": { + "@id": "software:SoftwarePurpose" + }, + "sh:name": "additionalPurpose", + "sh:path": { + "@id": "software:additionalPurpose" + } + } + ] + }, + { + "@id": "core:AnnotationType", + "@type": "owl:Class", + "rdfs:comment": "AnnotationType specifies the type of an annotation.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:CreationInfo", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "The CreationInfo provides information about who created the Element, and when and how it was created. \n\nThe dateTime created is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + }, + { + "sh:class": { + "@id": "core:Tool" + }, + "sh:name": "createdUsing", + "sh:path": { + "@id": "core:createdUsing" + } + }, + { + "sh:class": { + "@id": "core:Agent" + }, + "sh:minCount": 1, + "sh:name": "createdBy", + "sh:path": { + "@id": "core:createdBy" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:name": "created", + "sh:path": { + "@id": "core:created" + } + }, + { + "sh:datatype": { + "@id": "core:SemVer" + }, + "sh:name": "specVersion", + "sh:path": { + "@id": "core:specVersion" + } + }, + { + "sh:class": { + "@id": "core:ProfileIdentifierType" + }, + "sh:minCount": 1, + "sh:name": "profile", + "sh:path": { + "@id": "core:profile" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "dataLicense", + "sh:path": { + "@id": "core:dataLicense" + } + } + ] + }, + { + "@id": "core:ExternalMap", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An External Map is a map of Element identifiers that are used within a Document\nbut defined external to that Document.\nThe external map provides details about the externally-defined Element\nsuch as its provenance, where to retrieve it, and how to verify its integrity.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "core:IntegrityMethod" + }, + "sh:name": "verifiedUsing", + "sh:path": { + "@id": "core:verifiedUsing" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "locationHint", + "sh:path": { + "@id": "core:locationHint" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "definingDocument", + "sh:path": { + "@id": "core:definingDocument" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "externalId", + "sh:path": { + "@id": "core:externalId" + } + } + ] + }, + { + "@id": "core:IntegrityMethod", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An IntegrityMethod provides an independently reproducible mechanism that permits verification\nof a specific Element that correlates to the data in this SPDX document. This identifier enables\na recipient to determine if anything in the original Element has been changed and eliminates\nconfusion over which version or modification of a specific Element is referenced.", + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + } + }, + { + "@id": "core:NamespaceMap", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A namespace map allows the creator of a collection of Elements to use\nshorter identifiers (\"prefixes\") instead of URIs to provide a more\nhuman-readable and smaller serialized representation of the Elements.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "prefix", + "sh:path": { + "@id": "core:prefix" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "namespace", + "sh:path": { + "@id": "core:namespace" + } + } + ] + }, + { + "@id": "core:PositiveIntegerRange", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "PositiveIntegerRange is a tuple of two positive integers that define a range.\n\"begin\" must be less than or equal to \"end\".", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:positiveInteger" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "begin", + "sh:path": { + "@id": "core:begin" + } + }, + { + "sh:datatype": { + "@id": "xsd:positiveInteger" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "end", + "sh:path": { + "@id": "core:end" + } + } + ] + }, + { + "@id": "licensing:LicenseAddition", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A LicenseAddition represents text which is intended to be added to a License\nas additional text, but which is not itself intended to be a standalone\nLicense.\n\nIt may be an exception which is listed on the SPDX Exceptions List\n(ListedLicenseException), or may be any other additional text (as an exception\nor otherwise) which is defined by an SPDX data creator (CustomLicenseAddition).", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:name": "isDeprecatedAdditionId", + "sh:path": { + "@id": "licensing:isDeprecatedAdditionId" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "additionText", + "sh:path": { + "@id": "licensing:additionText" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "additionId", + "sh:path": { + "@id": "licensing:additionId" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "seeAlso", + "sh:path": { + "@id": "licensing:seeAlso" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "obsoletedBy", + "sh:path": { + "@id": "licensing:obsoletedBy" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "standardAdditionTemplate", + "sh:path": { + "@id": "licensing:standardAdditionTemplate" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "additionName", + "sh:path": { + "@id": "licensing:additionName" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "additionComment", + "sh:path": { + "@id": "licensing:additionComment" + } + } + ] + }, + { + "@id": "security:ExploitCatalogType", + "@type": "owl:Class", + "rdfs:comment": "ExploitCatalogType specifies the type of exploit catalog that a vulnerability is listed in.", + "ns0:term_status": "Stable" + }, + { + "@id": "security:VexVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexVulnAssessmentRelationship is an abstract subclass that defined the common\nproperties shared by all the SPDX-VEX status relationships. \n\n**Constraints**\n\nWhen linking elements using a VexVulnAssessmentRelationship, the following\nrequirements must be observed:\n\n- The from: end must be a /Security/Vulnerability classed element\n- The to: end must point to elements representing the VEX _products_. To\nspecify a different element where the vulnerability was detected, the VEX\nrelationship can optionally specify _subcomponents_ using the assessedElement\nproperty.\n\nVEX inherits information from the document level down to its statements. When a\nstatement is missing information it can be completed by reading the equivalent \nfield from the containing document. For example, if a VEX relationship is\nmissing data in its createdBy property, tools must consider the entity\nlisted in the CreationInfo section of the document as the VEX author.\nIn the same way, when a VEX relationship does not have a created property,\nthe document's date must be considered as authoritative.", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "vexVersion", + "sh:path": { + "@id": "security:vexVersion" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "statusNotes", + "sh:path": { + "@id": "security:statusNotes" + } + } + ] + }, + { + "@id": "core:MediaType", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "The MediaType is a String constrained to the RFC 2046 specification. It provides a standardized\nway of indicating the type of content of an Element.\nA list of all possible media types is available at https://www.iana.org/assignments/media-types/media-types.xhtml.", + "rdfs:subClassOf": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:RelationshipCompleteness", + "@type": "owl:Class", + "rdfs:comment": "RelationshipCompleteness indicates whether a relationship is complete or \nknown to be incomplete or if there is made no assertion either way.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:comment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A comment is an optional field for creators of the Element to provide comments\nto the readers/reviewers of the document.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:License", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A License represents a license text, whether listed on the SPDX License List\n(ListedLicense) or defined by an SPDX data creator (CustomLicense).", + "rdfs:subClassOf": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "obsoletedBy", + "sh:path": { + "@id": "licensing:obsoletedBy" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "standardLicenseTemplate", + "sh:path": { + "@id": "licensing:standardLicenseTemplate" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "licenseText", + "sh:path": { + "@id": "licensing:licenseText" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:name": "isDeprecatedLicenseId", + "sh:path": { + "@id": "licensing:isDeprecatedLicenseId" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:name": "isFsfLibre", + "sh:path": { + "@id": "licensing:isFsfLibre" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "standardLicenseHeader", + "sh:path": { + "@id": "licensing:standardLicenseHeader" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "licenseId", + "sh:path": { + "@id": "licensing:licenseId" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "licenseName", + "sh:path": { + "@id": "licensing:licenseName" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:name": "isOsiApproved", + "sh:path": { + "@id": "licensing:isOsiApproved" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "licenseComment", + "sh:path": { + "@id": "licensing:licenseComment" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "seeAlso", + "sh:path": { + "@id": "licensing:seeAlso" + } + } + ] + }, + { + "@id": "ai:SafetyRiskAssessmentType", + "@type": "owl:Class", + "rdfs:comment": "Lists the different safety risk type values that can be used to describe the safety risk of AI software\naccording to [Article 20 of Regulation 765/2008/EC](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).", + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:ConfidentialityLevelType", + "@type": "owl:Class", + "rdfs:comment": "Describes the different confidentiality levels as given by the [Traffic Light Protocol](https://en.wikipedia.org/wiki/Traffic_Light_Protocol).", + "ns0:term_status": "Stable" + }, + { + "@id": "security:SsvcDecisionType", + "@type": "owl:Class", + "rdfs:comment": "SsvcDecisionType specifies the type of decision that's been made according to the Stakeholder-Specific Vulnerability Categorization (SSVC) system [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc)", + "ns0:term_status": "Stable" + }, + { + "@id": "security:VulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VulnAssessmentRelationship is the ancestor class common to all vulnerability\nassessment relationships. It factors out the common properties shared by them.\nExternal property restriction on /Core/Relationship/to: minCount: 1", + "rdfs:subClassOf": { + "@id": "core:Relationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "withdrawnTime", + "sh:path": { + "@id": "security:withdrawnTime" + } + }, + { + "sh:class": { + "@id": "core:Element" + }, + "sh:maxCount": 1, + "sh:name": "assessedElement", + "sh:path": { + "@id": "security:assessedElement" + } + }, + { + "sh:class": { + "@id": "core:Agent" + }, + "sh:maxCount": 1, + "sh:name": "suppliedBy", + "sh:path": { + "@id": "security:suppliedBy" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "publishedTime", + "sh:path": { + "@id": "security:publishedTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "modifiedTime", + "sh:path": { + "@id": "security:modifiedTime" + } + } + ] + }, + { + "@id": "software:SoftwareDependencyLinkType", + "@type": "owl:Class", + "rdfs:comment": "TODO", + "ns0:term_status": "Stable" + }, + { + "@id": "ai:PresenceType", + "@type": "owl:Class", + "rdfs:comment": "This type is used to indicate if a given field is present or absent or unknown.", + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:DatasetAvailabilityType", + "@type": "owl:Class", + "rdfs:comment": "Describes the possible types of availability of a dataset, indicating whether the dataset can be directly downloaded, can be assembled using a script for scraping the data, is only available after a clickthrough or a registration form.", + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:LicenseField", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A LicenseField is the primary value that is used by a licensing field for a\nsoftware Package, File or Snippet. It represents either a license expression,\nor the values NOASSERTION or NONE. The specific meanings of NOASSERTION or\nNONE for the particular licensing field are defined in the corresponding\nproperty description.", + "ns0:term_status": "Stable" + }, + { + "@id": "security:VexJustificationType", + "@type": "owl:Class", + "rdfs:comment": "VexJustificationType specifies the type of Vulnerability Exploitability eXchange (VEX) justification.", + "ns0:term_status": "Stable" + }, + { + "@id": "software:DependencyConditionalityType", + "@type": "owl:Class", + "rdfs:comment": "TODO", + "ns0:term_status": "Stable" + }, + { + "@id": "core:LifecycleScopeType", + "@type": "owl:Class", + "rdfs:comment": "TODO", + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:AnyLicenseInfo", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An AnyLicenseInfo is used by a licensing field for a software package,\nfile or snippet when its value is not NOASSERTION or NONE. It can be a\nsingle license (either on the SPDX License List or a custom-defined license);\na single license with an \"or later\" operator applied; the foregoing with\nadditional text applied; or a set of licenses combined by applying \"AND\" and\n\"OR\" operators recursively.", + "rdfs:subClassOf": { + "@id": "licensing:LicenseField" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:SBOMType", + "@type": "owl:Class", + "rdfs:comment": "The set of SBOM types with definitions as defined in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf), published on April 21, 2023. \nAn SBOM type describes the most likely type of an SBOM from the producer perspective, so that consumers can draw conclusions about the data inside an SBOM. A single SBOM can have multiple SBOM document types associated with it.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:Agent", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "The Agent class represents anything that has the potential to act on a system. This could be a person, organization, software agent, etc. This is not to be confused with tools that are used to perform tasks.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:ProfileIdentifierType", + "@type": "owl:Class", + "rdfs:comment": "There are a set of profiles that have been defined to be valid for a specific release This file enumerates the values that have been agreed on, and may be applied to the creation information for an an element.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:DictionaryEntry", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "The class used for implementing a generic string mapping (also known as associative array, dictionary, or hash map) in SPDX. Each DictionaryEntry contains a key-value pair which maps the key to its associated value. To implement a dictionary, this class is to be used in a collection with unique keys.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "key", + "sh:path": { + "@id": "core:key" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "value", + "sh:path": { + "@id": "core:value" + } + } + ] + }, + { + "@id": "core:ExternalIdentifierType", + "@type": "owl:Class", + "rdfs:comment": "ExteralIdentifierType specifies the type of an external identifier.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:Element", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An Element is a representation of a fundamental concept either directly inherent\nto the Bill of Materials (BOM) domain or indirectly related to the BOM domain\nand necessary for contextually characterizing BOM concepts and relationships.\nWithin SPDX-3.0 structure this is the base class acting as a consistent,\nunifying, and interoperable foundation for all explicit\nand inter-relatable content objects.", + "rdfs:subClassOf": { + "@id": "core:Payload" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "summary", + "sh:path": { + "@id": "core:summary" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "description", + "sh:path": { + "@id": "core:description" + } + }, + { + "sh:datatype": { + "@id": "core:Extension" + }, + "sh:name": "extension", + "sh:path": { + "@id": "core:extension" + } + }, + { + "sh:class": { + "@id": "core:ExternalIdentifier" + }, + "sh:name": "externalIdentifier", + "sh:path": { + "@id": "core:externalIdentifier" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "name", + "sh:path": { + "@id": "core:name" + } + }, + { + "sh:class": { + "@id": "core:ExternalReference" + }, + "sh:name": "externalReference", + "sh:path": { + "@id": "core:externalReference" + } + }, + { + "sh:class": { + "@id": "core:IntegrityMethod" + }, + "sh:name": "verifiedUsing", + "sh:path": { + "@id": "core:verifiedUsing" + } + }, + { + "sh:class": { + "@id": "core:CreationInfo" + }, + "sh:maxCount": 1, + "sh:name": "creationInfo", + "sh:path": { + "@id": "core:creationInfo" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + } + ] + }, + { + "@id": "core:ExternalReferenceType", + "@type": "owl:Class", + "rdfs:comment": "ExteralReferenceType specifies the type of an external reference.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:HashAlgorithm", + "@type": "owl:Class", + "rdfs:comment": "A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is, a function which is practically infeasible to invert.", + "ns0:term_status": "Stable" + }, + { + "@id": "software:SoftwarePurpose", + "@type": "owl:Class", + "rdfs:comment": "This field provides information about the primary purpose of an Element.\nSoftware Purpose is intrinsic to how the Element is being used rather than the content of the Element.\nThis field is a reasonable estimate of the most likely usage of the Element\nfrom the producer and consumer perspective from which both parties can draw conclusions\nabout the context in which the Element exists.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:DateTime", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Datetime is a string representation of a specific date and time.\nIt has resolution of seconds and is always expressed in UTC timezone.\nThe specific format is one of the most commonly used ISO-8601 formats.\nFormat restriction: pattern: ^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$", + "rdfs:subClassOf": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:RelationshipType", + "@type": "owl:Class", + "rdfs:comment": "Provides information about the relationship between two Elements.\nFor example, you can represent a relationship between two different Files,\nbetween a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument.\n\nBuild Profile specific RelationshipType descriptions can be found [here](https://github.com/spdx/spdx-3-build-profile/blob/main/model/relationships.md)", + "ns0:term_status": "Stable" + } + ] +} diff --git a/src/spdx_tools/spdx3/writer/json_ld/__init__.py b/src/spdx_tools/spdx3/writer/json_ld/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/json_ld/context.json b/src/spdx_tools/spdx3/writer/json_ld/context.json new file mode 100644 index 000000000..94cb2b5e6 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/context.json @@ -0,0 +1,742 @@ +{ + "ai": "https://spdx.org/rdf/AI/", + "build": "https://spdx.org/rdf/Build/", + "core": "https://spdx.org/rdf/Core/", + "dataset": "https://spdx.org/rdf/Dataset/", + "licensing": "https://spdx.org/rdf/Licensing/", + "ns0": "http://www.w3.org/2003/06/sw-vocab-status/ns#", + "owl": "http://www.w3.org/2002/07/owl#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "security": "https://spdx.org/rdf/Security/", + "sh": "http://www.w3.org/ns/shacl#", + "software": "https://spdx.org/rdf/Software/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "AIPackage": "ai:AIPackage", + "Build": "build:Build", + "Annotation": "core:Annotation", + "AnonymousPayload": "core:AnonymousPayload", + "Organization": "core:Organization", + "Person": "core:Person", + "SoftwareAgent": "core:SoftwareAgent", + "SpdxDocument": "core:SpdxDocument", + "Dataset": "dataset:Dataset", + "ConjunctiveLicenseSet": "licensing:ConjunctiveLicenseSet", + "CustomLicense": "licensing:CustomLicense", + "CustomLicenseAddition": "licensing:CustomLicenseAddition", + "DisjunctiveLicenseSet": "licensing:DisjunctiveLicenseSet", + "ListedLicense": "licensing:ListedLicense", + "ListedLicenseException": "licensing:ListedLicenseException", + "NoAssertionLicense": "licensing:NoAssertionLicense", + "NoneLicense": "licensing:NoneLicense", + "OrLaterOperator": "licensing:OrLaterOperator", + "WithAdditionOperator": "licensing:WithAdditionOperator", + "CvssV2VulnAssessmentRelationship": "security:CvssV2VulnAssessmentRelationship", + "CvssV3VulnAssessmentRelationship": "security:CvssV3VulnAssessmentRelationship", + "EpssVulnAssessmentRelationship": "security:EpssVulnAssessmentRelationship", + "ExploitCatalogVulnAssessmentRelationship": "security:ExploitCatalogVulnAssessmentRelationship", + "SsvcVulnAssessmentRelationship": "security:SsvcVulnAssessmentRelationship", + "VexAffectedVulnAssessmentRelationship": "security:VexAffectedVulnAssessmentRelationship", + "VexFixedVulnAssessmentRelationship": "security:VexFixedVulnAssessmentRelationship", + "VexNotAffectedVulnAssessmentRelationship": "security:VexNotAffectedVulnAssessmentRelationship", + "VexUnderInvestigationVulnAssessmentRelationship": "security:VexUnderInvestigationVulnAssessmentRelationship", + "Vulnerability": "security:Vulnerability", + "File": "software:File", + "Sbom": "software:Sbom", + "Snippet": "software:Snippet", + "SoftwareDependencyRelationship": "software:SoftwareDependencyRelationship", + "autonomyType": { + "@id": "ai:autonomyType", + "@type": "ai:PresenceType" + }, + "domain": { + "@id": "ai:domain", + "@type": "xsd:string" + }, + "energyConsumption": { + "@id": "ai:energyConsumption", + "@type": "xsd:string" + }, + "hyperparameter": { + "@id": "ai:hyperparameter", + "@type": "core:DictionaryEntry" + }, + "informationAboutApplication": { + "@id": "ai:informationAboutApplication", + "@type": "xsd:string" + }, + "informationAboutTraining": { + "@id": "ai:informationAboutTraining", + "@type": "xsd:string" + }, + "limitation": { + "@id": "ai:limitation", + "@type": "xsd:string" + }, + "metric": { + "@id": "ai:metric", + "@type": "core:DictionaryEntry" + }, + "metricDecisionThreshold": { + "@id": "ai:metricDecisionThreshold", + "@type": "core:DictionaryEntry" + }, + "modelDataPreprocessing": { + "@id": "ai:modelDataPreprocessing", + "@type": "xsd:string" + }, + "modelExplainability": { + "@id": "ai:modelExplainability", + "@type": "xsd:string" + }, + "safetyRiskAssessment": { + "@id": "ai:safetyRiskAssessment", + "@type": "@vocab", + "@context": { + "@vocab": "ai:SafetyRiskAssessmentType/" + } + }, + "sensitivePersonalInformation": { + "@id": "dataset:sensitivePersonalInformation", + "@type": "@vocab", + "@context": { + "@vocab": "dataset:PresenceType/" + } + }, + "standardCompliance": { + "@id": "ai:standardCompliance", + "@type": "xsd:string" + }, + "typeOfModel": { + "@id": "ai:typeOfModel", + "@type": "xsd:string" + }, + "buildEndTime": { + "@id": "build:buildEndTime", + "@type": "core:DateTime" + }, + "buildId": { + "@id": "build:buildId", + "@type": "xsd:string" + }, + "buildStartTime": { + "@id": "build:buildStartTime", + "@type": "core:DateTime" + }, + "buildType": { + "@id": "build:buildType", + "@type": "xsd:anyURI" + }, + "configSourceDigest": { + "@id": "build:configSourceDigest", + "@type": "core:Hash" + }, + "configSourceEntrypoint": { + "@id": "build:configSourceEntrypoint", + "@type": "xsd:string" + }, + "configSourceUri": { + "@id": "build:configSourceUri", + "@type": "xsd:anyURI" + }, + "environment": { + "@id": "build:environment", + "@type": "core:DictionaryEntry" + }, + "parameters": { + "@id": "build:parameters", + "@type": "core:DictionaryEntry" + }, + "Artifact": "core:Artifact", + "Bom": "core:Bom", + "ElementCollection": "core:ElementCollection", + "LifecycleScopedRelationship": "core:LifecycleScopedRelationship", + "algorithm": { + "@id": "core:algorithm", + "@type": "@vocab", + "@context": { + "@vocab": "core:HashAlgorithm/" + } + }, + "annotationType": { + "@id": "core:annotationType", + "@type": "@vocab", + "@context": { + "@vocab": "core:AnnotationType/" + } + }, + "begin": { + "@id": "core:begin", + "@type": "xsd:positiveInteger" + }, + "builtTime": { + "@id": "core:builtTime", + "@type": "core:DateTime" + }, + "completeness": { + "@id": "core:completeness", + "@type": "@vocab", + "@context": { + "@vocab": "core:RelationshipCompleteness/" + } + }, + "context": { + "@id": "core:context", + "@type": "xsd:string" + }, + "created": { + "@id": "core:created", + "@type": "core:DateTime" + }, + "createdBy": { + "@id": "core:createdBy", + "@type": "@id" + }, + "createdUsing": { + "@id": "core:createdUsing", + "@type": "core:Tool" + }, + "dataLicense": { + "@id": "core:dataLicense", + "@type": "xsd:string" + }, + "definingDocument": { + "@id": "core:definingDocument", + "@type": "xsd:anyURI" + }, + "description": { + "@id": "core:description", + "@type": "xsd:string" + }, + "element": { + "@id": "core:element", + "@type": "@id" + }, + "end": { + "@id": "core:end", + "@type": "xsd:positiveInteger" + }, + "endTime": { + "@id": "core:endTime", + "@type": "core:DateTime" + }, + "externalId": { + "@id": "core:externalId", + "@type": "xsd:anyURI" + }, + "externalIdentifier": { + "@id": "core:externalIdentifier", + "@type": "core:ExternalIdentifier" + }, + "externalIdentifierType": { + "@id": "core:externalIdentifierType", + "@type": "@vocab", + "@context": { + "@vocab": "core:ExternalIdentifierType/" + } + }, + "externalReference": { + "@id": "core:externalReference", + "@type": "core:ExternalReference" + }, + "externalReferenceType": { + "@id": "core:externalReferenceType", + "@type": "@vocab", + "@context": { + "@vocab": "core:ExternalReferenceType/" + } + }, + "from": { + "@id": "core:from", + "@type": "@id" + }, + "hashValue": { + "@id": "core:hashValue", + "@type": "xsd:string" + }, + "identifier": { + "@id": "core:identifier", + "@type": "xsd:string" + }, + "identifierLocator": { + "@id": "core:identifierLocator", + "@type": "xsd:anyURI" + }, + "issuingAuthority": { + "@id": "core:issuingAuthority", + "@type": "xsd:anyURI" + }, + "key": { + "@id": "core:key", + "@type": "xsd:string" + }, + "locationHint": { + "@id": "core:locationHint", + "@type": "xsd:anyURI" + }, + "locator": { + "@id": "core:locator", + "@type": "xsd:anyURI" + }, + "namespace": { + "@id": "core:namespace", + "@type": "xsd:anyURI" + }, + "originatedBy": { + "@id": "core:originatedBy", + "@type": "@id" + }, + "prefix": { + "@id": "core:prefix", + "@type": "xsd:string" + }, + "profile": { + "@id": "core:profile", + "@type": "@vocab", + "@context": { + "core": "https://spdx.org/rdf/Core/ProfileIdentifierType/core", + "software": "https://spdx.org/rdf/Core/ProfileIdentifierType/software", + "licensing": "https://spdx.org/rdf/Core/ProfileIdentifierType/licensing", + "security": "https://spdx.org/rdf/Core/ProfileIdentifierType/security", + "build": "https://spdx.org/rdf/Core/ProfileIdentifierType/build", + "ai": "https://spdx.org/rdf/Core/ProfileIdentifierType/ai", + "dataset": "https://spdx.org/rdf/Core/ProfileIdentifierType/dataset", + "usage": "https://spdx.org/rdf/Core/ProfileIdentifierType/usage", + "extension": "https://spdx.org/rdf/Core/ProfileIdentifierType/extension" + } + }, + "relationshipType": { + "@id": "core:relationshipType", + "@type": "@vocab", + "@context": { + "@vocab": "core:RelationshipType/" + } + }, + "releaseTime": { + "@id": "core:releaseTime", + "@type": "core:DateTime" + }, + "rootElement": { + "@id": "core:rootElement", + "@type": "@id" + }, + "scope": { + "@id": "core:scope", + "@type": "@vocab", + "@context": { + "@vocab": "core:LifecycleScopeType/" + } + }, + "specVersion": { + "@id": "core:specVersion", + "@type": "core:SemVer" + }, + "standard": { + "@id": "core:standard", + "@type": "xsd:string" + }, + "startTime": { + "@id": "core:startTime", + "@type": "core:DateTime" + }, + "statement": { + "@id": "core:statement", + "@type": "xsd:string" + }, + "subject": { + "@id": "core:subject", + "@type": "@id" + }, + "summary": { + "@id": "core:summary", + "@type": "xsd:string" + }, + "suppliedBy": { + "@id": "core:suppliedBy", + "@type": "@id" + }, + "to": { + "@id": "core:to", + "@type": "@id" + }, + "validUntilTime": { + "@id": "core:validUntilTime", + "@type": "core:DateTime" + }, + "value": { + "@id": "core:value", + "@type": "xsd:string" + }, + "anonymizationMethodUsed": { + "@id": "dataset:anonymizationMethodUsed", + "@type": "xsd:string" + }, + "confidentialityLevel": { + "@id": "dataset:confidentialityLevel", + "@type": "@vocab", + "@context": { + "@vocab": "dataset:ConfidentialityLevelType/" + } + }, + "dataCollectionProcess": { + "@id": "dataset:dataCollectionProcess", + "@type": "xsd:string" + }, + "dataPreprocessing": { + "@id": "dataset:dataPreprocessing", + "@type": "xsd:string" + }, + "datasetAvailability": { + "@id": "dataset:datasetAvailability", + "@type": "@vocab", + "@context": { + "@vocab": "dataset:DatasetAvailabilityType/" + } + }, + "datasetNoise": { + "@id": "dataset:datasetNoise", + "@type": "xsd:string" + }, + "datasetSize": { + "@id": "dataset:datasetSize", + "@type": "xsd:nonNegativeInteger" + }, + "datasetType": { + "@id": "dataset:datasetType", + "@type": "xsd:string" + }, + "datasetUpdateMechanism": { + "@id": "dataset:datasetUpdateMechanism", + "@type": "xsd:string" + }, + "intendedUse": { + "@id": "dataset:intendedUse", + "@type": "xsd:string" + }, + "knownBias": { + "@id": "dataset:knownBias", + "@type": "xsd:string" + }, + "sensor": { + "@id": "dataset:sensor", + "@type": "core:DictionaryEntry" + }, + "additionComment": { + "@id": "licensing:additionComment", + "@type": "xsd:string" + }, + "additionId": { + "@id": "licensing:additionId", + "@type": "xsd:string" + }, + "additionName": { + "@id": "licensing:additionName", + "@type": "xsd:string" + }, + "additionText": { + "@id": "licensing:additionText", + "@type": "xsd:string" + }, + "isDeprecatedAdditionId": { + "@id": "licensing:isDeprecatedAdditionId", + "@type": "xsd:boolean" + }, + "isDeprecatedLicenseId": { + "@id": "licensing:isDeprecatedLicenseId", + "@type": "xsd:boolean" + }, + "isFsfLibre": { + "@id": "licensing:isFsfLibre", + "@type": "xsd:boolean" + }, + "isOsiApproved": { + "@id": "licensing:isOsiApproved", + "@type": "xsd:boolean" + }, + "licenseComment": { + "@id": "licensing:licenseComment", + "@type": "xsd:string" + }, + "licenseId": { + "@id": "licensing:licenseId", + "@type": "xsd:string" + }, + "licenseName": { + "@id": "licensing:licenseName", + "@type": "xsd:string" + }, + "licenseText": { + "@id": "licensing:licenseText", + "@type": "xsd:string" + }, + "standardAdditionTemplate": { + "@id": "licensing:standardAdditionTemplate", + "@type": "xsd:string" + }, + "standardLicenseHeader": { + "@id": "licensing:standardLicenseHeader", + "@type": "xsd:string" + }, + "standardLicenseTemplate": { + "@id": "licensing:standardLicenseTemplate", + "@type": "xsd:string" + }, + "subjectAddition": { + "@id": "licensing:subjectAddition", + "@type": "licensing:LicenseAddition" + }, + "actionStatement": { + "@id": "security:actionStatement", + "@type": "xsd:string" + }, + "actionStatementTime": { + "@id": "security:actionStatementTime", + "@type": "core:DateTime" + }, + "assessedElement": { + "@id": "security:assessedElement", + "@type": "@id" + }, + "catalogType": { + "@id": "security:catalogType", + "@type": "@vocab", + "@context": { + "@vocab": "security:ExploitCatalogType/" + } + }, + "decisionType": { + "@id": "security:decisionType", + "@type": "@vocab", + "@context": { + "@vocab": "security:SsvcDecisionType/" + } + }, + "exploited": { + "@id": "security:exploited", + "@type": "xsd:boolean" + }, + "impactStatement": { + "@id": "security:impactStatement", + "@type": "xsd:string" + }, + "impactStatementTime": { + "@id": "security:impactStatementTime", + "@type": "core:DateTime" + }, + "justificationType": { + "@id": "security:justificationType", + "@type": "@vocab", + "@context": { + "@vocab": "security:VexJustificationType/" + } + }, + "probability": { + "@id": "security:probability", + "@type": "xsd:decimal" + }, + "statusNotes": { + "@id": "security:statusNotes", + "@type": "xsd:string" + }, + "vexVersion": { + "@id": "security:vexVersion", + "@type": "xsd:string" + }, + "additionalPurpose": { + "@id": "software:additionalPurpose", + "@type": "software:SoftwarePurpose" + }, + "attributionText": { + "@id": "software:attributionText", + "@type": "xsd:string" + }, + "byteRange": { + "@id": "software:byteRange", + "@type": "core:PositiveIntegerRange" + }, + "concludedLicense": { + "@id": "software:concludedLicense", + "@type": "licensing:LicenseField" + }, + "conditionality": { + "@id": "software:conditionality", + "@type": "@vocab", + "@context": { + "@vocab": "software:DependencyConditionalityType/" + } + }, + "contentIdentifier": { + "@id": "software:contentIdentifier", + "@type": "xsd:anyURI" + }, + "contentType": { + "@id": "core:contentType", + "@type": "core:MediaType" + }, + "copyrightText": { + "@id": "software:copyrightText", + "@type": "xsd:string" + }, + "declaredLicense": { + "@id": "software:declaredLicense", + "@type": "licensing:LicenseField" + }, + "downloadLocation": { + "@id": "software:downloadLocation", + "@type": "xsd:anyURI" + }, + "homePage": { + "@id": "software:homePage", + "@type": "xsd:anyURI" + }, + "lineRange": { + "@id": "software:lineRange", + "@type": "core:PositiveIntegerRange" + }, + "packageUrl": { + "@id": "software:packageUrl", + "@type": "xsd:anyURI" + }, + "packageVersion": { + "@id": "software:packageVersion", + "@type": "xsd:string" + }, + "primaryPurpose": { + "@id": "software:primaryPurpose", + "@type": "software:SoftwarePurpose" + }, + "sbomType": { + "@id": "software:sbomType", + "@type": "@vocab", + "@context": { + "@vocab": "software:SBOMType/" + } + }, + "softwareLinkage": { + "@id": "software:softwareLinkage", + "@type": "@vocab", + "@context": { + "@vocab": "software:SoftwareDependencyLinkType/" + } + }, + "sourceInfo": { + "@id": "software:sourceInfo", + "@type": "xsd:string" + }, + "Bundle": "core:Bundle", + "ExternalIdentifier": "core:ExternalIdentifier", + "ExternalReference": "core:ExternalReference", + "Hash": "core:Hash", + "Payload": "core:Payload", + "Relationship": "core:Relationship", + "SemVer": "core:SemVer", + "Tool": "core:Tool", + "name": { + "@id": "core:name", + "@type": "xsd:string" + }, + "verifiedUsing": { + "@id": "core:verifiedUsing", + "@type": "core:IntegrityMethod" + }, + "deprecatedVersion": { + "@id": "licensing:deprecatedVersion", + "@type": "xsd:string" + }, + "listVersionAdded": { + "@id": "licensing:listVersionAdded", + "@type": "xsd:string" + }, + "member": { + "@id": "licensing:member", + "@type": "licensing:AnyLicenseInfo" + }, + "obsoletedBy": { + "@id": "licensing:obsoletedBy", + "@type": "xsd:string" + }, + "seeAlso": { + "@id": "licensing:seeAlso", + "@type": "xsd:anyURI" + }, + "subjectLicense": { + "@id": "licensing:subjectLicense", + "@type": "licensing:License" + }, + "modifiedTime": { + "@id": "security:modifiedTime", + "@type": "core:DateTime" + }, + "publishedTime": { + "@id": "security:publishedTime", + "@type": "core:DateTime" + }, + "score": { + "@id": "security:score", + "@type": "xsd:string" + }, + "vector": { + "@id": "security:vector", + "@type": "xsd:string" + }, + "withdrawnTime": { + "@id": "security:withdrawnTime", + "@type": "core:DateTime" + }, + "Package": "software:Package", + "creationInfo": { + "@id": "core:creationInfo", + "@type": "core:CreationInfo" + }, + "imports": { + "@id": "core:imports", + "@type": "core:ExternalMap" + }, + "namespaces": { + "@id": "core:namespaces", + "@type": "core:NamespaceMap" + }, + "severity": { + "@id": "security:severity", + "@type": "xsd:string" + }, + "SoftwareArtifact": "software:SoftwareArtifact", + "AnnotationType": "core:AnnotationType", + "CreationInfo": "core:CreationInfo", + "ExternalMap": "core:ExternalMap", + "IntegrityMethod": "core:IntegrityMethod", + "NamespaceMap": "core:NamespaceMap", + "PositiveIntegerRange": "core:PositiveIntegerRange", + "LicenseAddition": "licensing:LicenseAddition", + "ExploitCatalogType": "security:ExploitCatalogType", + "VexVulnAssessmentRelationship": "security:VexVulnAssessmentRelationship", + "MediaType": "core:MediaType", + "RelationshipCompleteness": "core:RelationshipCompleteness", + "comment": { + "@id": "core:comment", + "@type": "xsd:string" + }, + "License": "licensing:License", + "SafetyRiskAssessmentType": "ai:SafetyRiskAssessmentType", + "ConfidentialityLevelType": "dataset:ConfidentialityLevelType", + "SsvcDecisionType": "security:SsvcDecisionType", + "VulnAssessmentRelationship": "security:VulnAssessmentRelationship", + "SoftwareDependencyLinkType": "software:SoftwareDependencyLinkType", + "PresenceType": "ai:PresenceType", + "DatasetAvailabilityType": "dataset:DatasetAvailabilityType", + "LicenseField": "licensing:LicenseField", + "VexJustificationType": "security:VexJustificationType", + "DependencyConditionalityType": "software:DependencyConditionalityType", + "LifecycleScopeType": "core:LifecycleScopeType", + "AnyLicenseInfo": "licensing:AnyLicenseInfo", + "SBOMType": "software:SBOMType", + "Agent": "core:Agent", + "ProfileIdentifierType": "core:ProfileIdentifierType", + "DictionaryEntry": "core:DictionaryEntry", + "ExternalIdentifierType": "core:ExternalIdentifierType", + "Element": "core:Element", + "ExternalReferenceType": "core:ExternalReferenceType", + "HashAlgorithm": "core:HashAlgorithm", + "SoftwarePurpose": "software:SoftwarePurpose", + "DateTime": "core:DateTime", + "RelationshipType": "core:RelationshipType" +} diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py new file mode 100644 index 000000000..865053b71 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py @@ -0,0 +1,79 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import Enum + +from beartype.typing import Any, List +from semantic_version import Version + +from spdx_tools.spdx3.model.creation_info import CreationInfo +from spdx_tools.spdx3.model.hash import Hash +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string + + +def convert_payload_to_json_ld_list_of_elements(payload: Payload) -> List: + element_list = [] + + for element in payload.get_full_map().values(): + element_dict = _convert_to_json_ld_dict(element) + element_list.append(element_dict) + + return element_list + + +def _convert_to_json_ld_dict(element: Any, alt_creation_info=False, alt_hash=False): + if not element: + return None + + if isinstance(element, (str, int, tuple)): + return element + + if isinstance(element, Version): + return str(element) + + if isinstance(element, datetime): + return datetime_to_iso_string(element) + + if isinstance(element, Enum): + return snake_case_to_camel_case(element.name) + + if isinstance(element, list): + return [_convert_to_json_ld_dict(item) for item in element if item] + + if alt_hash and isinstance(element, Hash): + hash_dict = {element.algorithm.name: element.hash_value} + if element.comment: + hash_dict["comment"] = element.comment + return hash_dict + + # if issubclass(element.__class__, Element): + # element_dict = {"@type": element.__class__.__name__} + # else: + # element_dict = {} # typing of non-Element classes should be handled by the @context, I think + + element_dict = {"@type": element.__class__.__name__} + + for attribute_name in vars(element): + attribute_value = getattr(element, attribute_name) + + if alt_creation_info and isinstance(attribute_value, CreationInfo): + for creation_info_attr_name in vars(attribute_value): + creation_info_attr_value = getattr(attribute_value, creation_info_attr_name) + element_dict[snake_case_to_camel_case(creation_info_attr_name)] = _convert_to_json_ld_dict( + creation_info_attr_value + ) + + elif attribute_value: + if attribute_name == "_spdx_id": + attribute_name = "@id" + elif attribute_name == "_from_element": + attribute_name = "from" + else: + attribute_name = snake_case_to_camel_case(attribute_name) + + element_dict[attribute_name] = _convert_to_json_ld_dict(attribute_value) + + return element_dict diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py new file mode 100644 index 000000000..69a4d763c --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import json +import os + +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.json_ld.json_ld_converter import convert_payload_to_json_ld_list_of_elements + + +def write_payload(payload: Payload, file_name: str): + element_list = convert_payload_to_json_ld_list_of_elements(payload) + + # this will be obsolete as soon as the context is publicly available under some URI + with open(os.path.join(os.path.dirname(__file__), "context.json"), "r") as infile: + context = json.load(infile) + + complete_dict = {"@context": context, "@graph": element_list} + + with open(file_name + ".jsonld", "w") as out: + json.dump(complete_dict, out, indent=2) diff --git a/src/spdx_tools/spdx3/writer/json_ld/model.ttl b/src/spdx_tools/spdx3/writer/json_ld/model.ttl new file mode 100644 index 000000000..04b407217 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/model.ttl @@ -0,0 +1,3441 @@ +@prefix ai: . +@prefix build: . +@prefix core: . +@prefix dataset: . +@prefix licensing: . +@prefix ns0: . +@prefix owl: . +@prefix rdfs: . +@prefix security: . +@prefix sh: . +@prefix software: . +@prefix xsd: . + +ai:AIPackage a owl:Class, + sh:NodeShape ; + rdfs:comment """Metadata information that can be added to a package to describe an AI application or trained AI model. +External property restriction on /Core/Artifact/suppliedBy: minCount: 1 +External property restriction on /Software/Package/downloadLocation: minCount: 1 +External property restriction on /Software/Package/packageVersion: minCount: 1 +External property restriction on /Software/SoftwareArtifact/purpose: minCount: 1 +External property restriction on /Core/Artifact/releaseTime: minCount: 1""" ; + rdfs:subClassOf software:Package ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:DictionaryEntry ; + sh:name "metric" ; + sh:path ai:metric ], + [ sh:datatype xsd:string ; + sh:name "modelExplainability" ; + sh:path ai:modelExplainability ], + [ sh:datatype xsd:string ; + sh:name "domain" ; + sh:path ai:domain ], + [ sh:datatype xsd:string ; + sh:name "standardCompliance" ; + sh:path ai:standardCompliance ], + [ sh:class core:DictionaryEntry ; + sh:name "hyperparameter" ; + sh:path ai:hyperparameter ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "energyConsumption" ; + sh:path ai:energyConsumption ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "limitation" ; + sh:path ai:limitation ], + [ sh:class ai:SafetyRiskAssessmentType ; + sh:maxCount 1 ; + sh:name "safetyRiskAssessment" ; + sh:path ai:safetyRiskAssessment ], + [ sh:datatype xsd:string ; + sh:name "modelDataPreprocessing" ; + sh:path ai:modelDataPreprocessing ], + [ sh:class ai:PresenceType ; + sh:maxCount 1 ; + sh:name "sensitivePersonalInformation" ; + sh:path ai:sensitivePersonalInformation ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "informationAboutTraining" ; + sh:path ai:informationAboutTraining ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "informationAboutApplication" ; + sh:path ai:informationAboutApplication ], + [ sh:datatype xsd:string ; + sh:name "typeOfModel" ; + sh:path ai:typeOfModel ], + [ sh:class ai:PresenceType ; + sh:maxCount 1 ; + sh:name "autonomyType" ; + sh:path ai:autonomyType ], + [ sh:class core:DictionaryEntry ; + sh:name "metricDecisionThreshold" ; + sh:path ai:metricDecisionThreshold ] . + + a owl:NamedIndividual, + ai:PresenceType . + + a owl:NamedIndividual, + ai:PresenceType . + + a owl:NamedIndividual, + ai:PresenceType . + + a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + + a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + + a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + + a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + +build:Build a owl:Class, + sh:NodeShape ; + rdfs:comment """A build is a representation of the process in which a piece of software or artifact is built. It encapsulates information related to a build process and +provides an element from which relationships can be created to describe the build's inputs, outputs, and related entities (e.g. builders, identities, etc.). + +Definitions of "BuildType", "ConfigSource", "Parameters" and "Environment" follow +those defined in [SLSA provenance](https://slsa.dev/provenance/v0.2). + +ExternalIdentifier of type "urlScheme" may be used to identify build logs. In this case, the comment of the ExternalIdentifier should be "LogReference". + +Note that buildStart and buildEnd are optional, and may be omitted to simplify creating reproducible builds.""" ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:Hash ; + sh:name "configSourceDigest" ; + sh:path build:configSourceDigest ], + [ sh:datatype xsd:anyURI ; + sh:name "configSourceUri" ; + sh:path build:configSourceUri ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "buildId" ; + sh:path build:buildId ], + [ sh:class core:DictionaryEntry ; + sh:name "parameters" ; + sh:path build:parameters ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "buildEndTime" ; + sh:path build:buildEndTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "buildStartTime" ; + sh:path build:buildStartTime ], + [ sh:class core:DictionaryEntry ; + sh:name "environment" ; + sh:path build:environment ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "buildType" ; + sh:path build:buildType ], + [ sh:datatype xsd:string ; + sh:name "configSourceEntrypoint" ; + sh:path build:configSourceEntrypoint ] . + +core:Annotation a owl:Class, + sh:NodeShape ; + rdfs:comment "An Annotation is an assertion made in relation to one or more elements." ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "statement" ; + sh:path core:statement ], + [ sh:class core:Element ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "subject" ; + sh:path core:subject ], + [ sh:datatype core:MediaType ; + sh:name "contentType" ; + sh:path core:contentType ], + [ sh:class core:AnnotationType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "annotationType" ; + sh:path core:annotationType ] . + + a owl:NamedIndividual, + core:AnnotationType . + + a owl:NamedIndividual, + core:AnnotationType . + +core:AnonymousPayload a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO" ; + rdfs:subClassOf core:Payload ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:CreationInfo ; + sh:maxCount 1 ; + sh:name "creationInfo" ; + sh:path core:creationInfo ], + [ sh:class core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ], + [ sh:class core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ] . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:ExternalReferenceType . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:LifecycleScopeType . + + a owl:NamedIndividual, + core:LifecycleScopeType . + + a owl:NamedIndividual, + core:LifecycleScopeType . + + a owl:NamedIndividual, + core:LifecycleScopeType . + + a owl:NamedIndividual, + core:LifecycleScopeType . + + a owl:NamedIndividual, + core:LifecycleScopeType . + +core:Organization a owl:Class, + sh:NodeShape ; + rdfs:comment "An Organization is a group of people who work together in an organized way for a shared purpose." ; + rdfs:subClassOf core:Agent ; + ns0:term_status "Stable" . + +core:Person a owl:Class, + sh:NodeShape ; + rdfs:comment "A Person is an individual human being." ; + rdfs:subClassOf core:Agent ; + ns0:term_status "Stable" . + + a owl:NamedIndividual, + core:ProfileIdentifierType . + + a owl:NamedIndividual, + core:ProfileIdentifierType . + + a owl:NamedIndividual, + core:ProfileIdentifierType . + + a owl:NamedIndividual, + core:ProfileIdentifierType . + + a owl:NamedIndividual, + core:ProfileIdentifierType . + + a owl:NamedIndividual, + core:ProfileIdentifierType . + + a owl:NamedIndividual, + core:ProfileIdentifierType . + + a owl:NamedIndividual, + core:ProfileIdentifierType . + + a owl:NamedIndividual, + core:ProfileIdentifierType . + + a owl:NamedIndividual, + core:RelationshipCompleteness . + + a owl:NamedIndividual, + core:RelationshipCompleteness . + + a owl:NamedIndividual, + core:RelationshipCompleteness . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + + a owl:NamedIndividual, + core:RelationshipType . + +core:SoftwareAgent a owl:Class, + sh:NodeShape ; + rdfs:comment "A SoftwareAgent is a software program that is given the authority (similar to a user's authority) to act on a system." ; + rdfs:subClassOf core:Agent ; + ns0:term_status "Stable" . + +core:SpdxDocument a owl:Class, + sh:NodeShape ; + rdfs:comment """An SpdxDocument assembles a collection of Elements under a common string, the name of the document. +Commonly used when representing a unit of transfer of SPDX Elements. +External property restriction on /Core/Element/name: minCount: 1""" ; + rdfs:subClassOf core:Bundle ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "name" ; + sh:path core:name ] . + + a owl:NamedIndividual, + dataset:ConfidentialityLevelType . + + a owl:NamedIndividual, + dataset:ConfidentialityLevelType . + + a owl:NamedIndividual, + dataset:ConfidentialityLevelType . + + a owl:NamedIndividual, + dataset:ConfidentialityLevelType . + +dataset:Dataset a owl:Class, + sh:NodeShape ; + rdfs:comment """Metadata information that can be added to a dataset that may be used in a software or to train/test an AI package. +External property restriction on /Core/Artifact/originatedBy: minCount: 1 +External property restriction on /Software/Package/downloadLocation: minCount: 1 +External property restriction on /Software/SoftwareArtifact/purpose: minCount: 1 +External property restriction on /Core/Artifact/releaseTime: minCount: 1 +External property restriction on /Core/Artifact/builtTime: minCount: 1""" ; + rdfs:subClassOf software:Package ; + ns0:term_status "Stable" ; + sh:property [ sh:class dataset:DatasetAvailabilityType ; + sh:maxCount 1 ; + sh:name "datasetAvailability" ; + sh:path dataset:datasetAvailability ], + [ sh:class dataset:ConfidentialityLevelType ; + sh:maxCount 1 ; + sh:name "confidentialityLevel" ; + sh:path dataset:confidentialityLevel ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "dataCollectionProcess" ; + sh:path dataset:dataCollectionProcess ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "datasetUpdateMechanism" ; + sh:path dataset:datasetUpdateMechanism ], + [ sh:datatype xsd:string ; + sh:name "knownBias" ; + sh:path dataset:knownBias ], + [ sh:datatype xsd:nonNegativeInteger ; + sh:maxCount 1 ; + sh:name "datasetSize" ; + sh:path dataset:datasetSize ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "intendedUse" ; + sh:path dataset:intendedUse ], + [ sh:datatype dataset:PresenceType ; + sh:maxCount 1 ; + sh:name "sensitivePersonalInformation" ; + sh:path dataset:sensitivePersonalInformation ], + [ sh:datatype xsd:string ; + sh:name "dataPreprocessing" ; + sh:path dataset:dataPreprocessing ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "datasetNoise" ; + sh:path dataset:datasetNoise ], + [ sh:class core:DictionaryEntry ; + sh:name "sensor" ; + sh:path dataset:sensor ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "datasetType" ; + sh:path dataset:datasetType ], + [ sh:datatype xsd:string ; + sh:name "anonymizationMethodUsed" ; + sh:path dataset:anonymizationMethodUsed ] . + + a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + + a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + + a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + + a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + + a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + +licensing:ConjunctiveLicenseSet a owl:Class, + sh:NodeShape ; + rdfs:comment """A ConjunctiveLicenseSet indicates that _each_ of its subsidiary +AnyLicenseInfos apply. In other words, a ConjunctiveLicenseSet of two or +more licenses represents a licensing situation where _all_ of the specified +licenses are to be complied with. It is represented in the SPDX License +Expression Syntax by the `AND` operator. + +It is syntactically correct to specify a ConjunctiveLicenseSet where the +subsidiary AnyLicenseInfos may be "incompatible" according to a particular +interpretation of the corresponding Licenses. The SPDX License Expression +Syntax does not take into account interpretation of license texts, which is +left to the consumer of SPDX data to determine for themselves.""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; + ns0:term_status "Stable" ; + sh:property [ sh:class licensing:AnyLicenseInfo ; + sh:minCount 2 ; + sh:name "member" ; + sh:path licensing:member ] . + +licensing:CustomLicense a owl:Class, + sh:NodeShape ; + rdfs:comment """A CustomLicense represents a License that is not listed on the SPDX License +List at https://spdx.org/licenses, and is therefore defined by an SPDX data +creator.""" ; + rdfs:subClassOf licensing:License ; + ns0:term_status "Stable" . + +licensing:CustomLicenseAddition a owl:Class, + sh:NodeShape ; + rdfs:comment """A CustomLicenseAddition represents an addition to a License that is not listed +on the SPDX Exceptions List at https://spdx.org/licenses/exceptions-index.html, +and is therefore defined by an SPDX data creator. + +It is intended to represent additional language which is meant to be added to +a License, but which is not itself a standalone License.""" ; + rdfs:subClassOf licensing:LicenseAddition ; + ns0:term_status "Stable" . + +licensing:DisjunctiveLicenseSet a owl:Class, + sh:NodeShape ; + rdfs:comment """A DisjunctiveLicenseSet indicates that _only one_ of its subsidiary +AnyLicenseInfos is required to apply. In other words, a +DisjunctiveLicenseSet of two or more licenses represents a licensing +situation where _only one_ of the specified licenses are to be complied with. +A consumer of SPDX data would typically understand this to permit the recipient +of the licensed content to choose which of the corresponding license they +would prefer to use. It is represented in the SPDX License Expression Syntax +by the `OR` operator.""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; + ns0:term_status "Stable" ; + sh:property [ sh:class licensing:AnyLicenseInfo ; + sh:minCount 2 ; + sh:name "member" ; + sh:path licensing:member ] . + +licensing:ListedLicense a owl:Class, + sh:NodeShape ; + rdfs:comment """A ListedLicense represents a License that is listed on the SPDX License List +at https://spdx.org/licenses.""" ; + rdfs:subClassOf licensing:License ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "deprecatedVersion" ; + sh:path licensing:deprecatedVersion ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "listVersionAdded" ; + sh:path licensing:listVersionAdded ] . + +licensing:ListedLicenseException a owl:Class, + sh:NodeShape ; + rdfs:comment """A ListedLicenseException represents an exception to a License (in other words, +an exception to a license condition or an additional permission beyond those +granted in a License) which is listed on the SPDX Exceptions List at +https://spdx.org/licenses/exceptions-index.html.""" ; + rdfs:subClassOf licensing:LicenseAddition ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "deprecatedVersion" ; + sh:path licensing:deprecatedVersion ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "listVersionAdded" ; + sh:path licensing:listVersionAdded ] . + +licensing:NoAssertionLicense a owl:Class, + sh:NodeShape ; + rdfs:comment """A NoAssertionLicense is the primary value that is used by a concludedLicense +or declaredLicense field that indicates that the SPDX data creator is making +no assertion about the license information for the corresponding software +Package, File or Snippet. + +The specific meaning of NoAssertionLicense in the context of a +concludedLicense or declaredLicense field is more fully set forth in the +Property definitions for those fields.""" ; + rdfs:subClassOf licensing:LicenseField ; + ns0:term_status "Stable" . + +licensing:NoneLicense a owl:Class, + sh:NodeShape ; + rdfs:comment """A NoneLicense is the primary value that is used by a concludedLicense or +declaredLicense field that indicates the absence of license information from +the corresponding software Package, File or Snippet. + +The specific meaning of NoneLicense in the context of a concludedLicense or +declaredLicense field is more fully set forth in the Property definitions for +those fields.""" ; + rdfs:subClassOf licensing:LicenseField ; + ns0:term_status "Stable" . + +licensing:OrLaterOperator a owl:Class, + sh:NodeShape ; + rdfs:comment """An OrLaterOperator indicates that this portion of the AnyLicenseInfo +represents either (1) the specified version of the corresponding License, or +(2) any later version of that License. It is represented in the SPDX License +Expression Syntax by the `+` operator. + +It is context-dependent, and unspecified by SPDX, as to what constitutes a +"later version" of any particular License. Some Licenses may not be versioned, +or may not have clearly-defined ordering for versions. The consumer of SPDX +data will need to determine for themselves what meaning to attribute to a +"later version" operator for a particular License.""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; + ns0:term_status "Stable" ; + sh:property [ sh:class licensing:License ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "subjectLicense" ; + sh:path licensing:subjectLicense ] . + +licensing:WithAdditionOperator a owl:Class, + sh:NodeShape ; + rdfs:comment """A WithAdditionOperator indicates that the designated License is subject to the +designated LicenseAddition, which might be a license exception on the SPDX +Exceptions List (ListedLicenseException) or may be other additional text +(CustomLicenseAddition). It is represented in the SPDX License Expression +Syntax by the `WITH` operator.""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; + ns0:term_status "Stable" ; + sh:property [ sh:class licensing:License ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "subjectLicense" ; + sh:path licensing:subjectLicense ], + [ sh:class licensing:LicenseAddition ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "subjectAddition" ; + sh:path licensing:subjectAddition ] . + +security:CvssV2VulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """A CvssV2VulnAssessmentRelationship relationship describes the determined score and vector of a vulnerability using version 2.0 of the Common Vulnerability Scoring System +(CVSS) as defined on [https://www.first.org/cvss/v2/guide](https://www.first.org/cvss/v2/guide). It is intented to communicate the results of using a CVSS calculator. + +**Constraints** + +- The value of severity must be one of 'low', 'medium' or 'high' +- The relationship type must be set to hasAssessmentFor. + +**Syntax** + +```json +{ + "@type": "CvssV2VulnAssessmentRelationship", + "@id": "urn:spdx.dev:cvssv2-cve-2020-28498", + "relationshipType": "hasAssessmentFor", + "score": 4.3, + "vector": "(AV:N/AC:M/Au:N/C:P/I:N/A:N)", + "severity": "low", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "externalReferences": [ + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://nvd.nist.gov/vuln/detail/CVE-2020-28498" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityFix", + "locator": "https://github.com/indutny/elliptic/commit/441b742" + } + ], + "suppliedBy": ["urn:spdx.dev:agent-my-security-vendor"], + "publishedTime": "2023-05-06T10:06:13Z" +}, +{ + "@type": "Relationship", + "@id": "urn:spdx.dev:vulnAgentRel-1", + "relationshipType": "publishedBy", + "from": "urn:spdx.dev:cvssv2-cve-2020-28498", + "to": ["urn:spdx.dev:agent-snyk"], + "startTime": "2021-03-08T16:06:50Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:decimal ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "score" ; + sh:path security:score ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "severity" ; + sh:path security:severity ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "vector" ; + sh:path security:vector ] . + +security:CvssV3VulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """A CvssV3VulnAssessmentRelationship relationship describes the determined score, +severity, and vector of a vulnerability using version 3.1 of the Common +Vulnerability Scoring System (CVSS) as defined on +[https://www.first.org/cvss/v3.1/specification-document](https://www.first.org/cvss/v3.1/specification-document). It is intented to communicate the results of using a CVSS calculator. + +**Constraints** + +- The value of severity must be one of 'none', 'low', 'medium', 'high' or 'critical'. +- Absence of the property shall be interpreted as 'none'. +- The relationship type must be set to hasAssessmentFor. + +**Syntax** + +```json +{ + "@type": "CvssV3VulnAssessmentRelationship", + "@id": "urn:spdx.dev:cvssv3-cve-2020-28498", + "relationshipType": "hasAssessmentFor", + "severity": "medium", + "score": 6.8, + "vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "externalReferences": [ + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://nvd.nist.gov/vuln/detail/CVE-2020-28498" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityFix", + "locator": "https://github.com/indutny/elliptic/commit/441b742" + } + ], + "suppliedBy": ["urn:spdx.dev:agent-my-security-vendor"], + "publishedTime": "2023-05-06T10:06:13Z" +}, +{ + "@type": "Relationship", + "@id": "urn:spdx.dev:vulnAgentRel-1", + "relationshipType": "publishedBy", + "from": "urn:spdx.dev:cvssv3-cve-2020-28498", + "to": "urn:spdx.dev:agent-snyk", + "startTime": "2021-03-08T16:06:50Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:decimal ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "score" ; + sh:path security:score ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "vector" ; + sh:path security:vector ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "severity" ; + sh:path security:severity ] . + +security:EpssVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """An EpssVulnAssessmentRelationship relationship describes the likelihood or +probability that a vulnerability will be exploited in the wild using the Exploit +Prediction Scoring System (EPSS) as defined on +[https://www.first.org/epss/model](https://www.first.org/epss/model). + +**Constraints** + +- The relationship type must be set to hasAssessmentFor. + +**Syntax** + +```json +{ + "@type": "EpssVulnAssessmentRelationship", + "@id": "urn:spdx.dev:epss-1", + "relationshipType": "hasAssessmentFor", + "probability": 80, + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:nonNegativeInteger ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "probability" ; + sh:path security:probability ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "severity" ; + sh:path security:severity ] . + + a owl:NamedIndividual, + security:ExploitCatalogType . + + a owl:NamedIndividual, + security:ExploitCatalogType . + +security:ExploitCatalogVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """An ExploitCatalogVulnAssessmentRelationship describes if a vulnerability is +listed in any exploit catalog such as the CISA Known Exploited Vulnerabilities +Catalog (KEV) +[https://www.cisa.gov/known-exploited-vulnerabilities-catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog). + +**Constraints** + +- The relationship type must be set to hasAssessmentFor. + +**Syntax** + +```json +{ + "@type": "ExploitCatalogVulnAssessmentRelationship", + "@id": "urn:spdx.dev:exploit-catalog-1", + "relationshipType": "hasAssessmentFor", + "catalogType": "kev", + "locator": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", + "exploited": "true", + "from": "urn:spdx.dev:vuln-cve-2023-2136", + "to": ["urn:product-google-chrome-112.0.5615.136"], + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "locator" ; + sh:path security:locator ], + [ sh:class security:ExploitCatalogType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "catalogType" ; + sh:path security:catalogType ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "exploited" ; + sh:path security:exploited ] . + + a owl:NamedIndividual, + security:SsvcDecisionType . + + a owl:NamedIndividual, + security:SsvcDecisionType . + + a owl:NamedIndividual, + security:SsvcDecisionType . + + a owl:NamedIndividual, + security:SsvcDecisionType . + +security:SsvcVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """An SsvcVulnAssessmentRelationship describes the decision made using the +Stakeholder-Specific Vulnerability Categorization (SSVC) decision tree as +defined on [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc). +It is intended to communicate the results of using the CISA SSVC Calculator. + +**Constraints** + +- The relationship type must be set to hasAssessmentFor. + +**Syntax** + +```json +{ + "@type": "SsvcVulnAssessmentRelationship", + "@id": "urn:spdx.dev:ssvc-1", + "relationshipType": "hasAssessmentFor", + "decisionType": "act", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:class security:SsvcDecisionType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "decisionType" ; + sh:path security:decisionType ] . + +security:VexAffectedVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexAffectedVulnAssessmentRelationship connects a vulnerability and a number +of elements. The relationship marks these elements as products affected by the +vulnerability. This relationship corresponds to the VEX affected status. + +**Constraints** + +When linking elements using a VexAffectedVulnAssessmentRelationship, the +following requirements must be observed: + +- Elements linked with a VulnVexAffectedAssessmentRelationship are constrained +to the affects relationship type. + +**Syntax** + +```json +{ + "@type": "VexAffectedVulnAssessmentRelationship", + "@id": "urn:spdx.dev:vex-affected-1", + "relationshipType": "affects", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "actionStatement": "Upgrade to version 1.4 of ACME application.", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VexVulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:DateTime ; + sh:name "actionStatementTime" ; + sh:path security:actionStatementTime ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "actionStatement" ; + sh:path security:actionStatement ] . + +security:VexFixedVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexFixedVulnAssessmentRelationship links a vulnerability to a number of elements +representing VEX products where a vulnerability has been fixed and are no longer +affected. It represents the VEX fixed status. + +**Constraints** + +When linking elements using a VexFixedVulnAssessmentRelationship, the following +requirements must be observed: + +- Elements linked with a VulnVexFixedAssessmentRelationship are constrained to +using the fixedIn relationship type. +- The from: end of the relationship must ve a /Security/Vulnerability classed +element. + +**Syntax** + +```json +{ + "@type": "VexFixedVulnAssessmentRelationship", + "@id": "urn:spdx.dev:vex-fixed-in-1", + "relationshipType": "fixedIn", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.4", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VexVulnAssessmentRelationship ; + ns0:term_status "Stable" . + + a owl:NamedIndividual, + security:VexJustificationType . + + a owl:NamedIndividual, + security:VexJustificationType . + + a owl:NamedIndividual, + security:VexJustificationType . + + a owl:NamedIndividual, + security:VexJustificationType . + + a owl:NamedIndividual, + security:VexJustificationType . + +security:VexNotAffectedVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexNotAffectedVulnAssessmentRelationship connects a vulnerability and a number +of elements designating them as products not affected by the vulnerability. +This relationship corresponds to the VEX not_affected status. + +**Constraints** + +When linking elements using a VexNotVulnAffectedAssessmentRelationship, the +following requirements must be observed: + +* Relating elements with a VexNotAffectedVulnAssessmentRelationship is restricted +to the doesNotAffect relationship type. +* The from: end of the relationship must be a /Security/Vulnerability classed +element. +* Both impactStatement and justificationType properties have a cardinality of +0..1 making them optional. Nevertheless, to produce a valid VEX not_affected +statement, one of them MUST be defined. This is specified in the Minimum Elements +for VEX. + +**Syntax** + +```json +{ + "@type": "VexNotAffectedVulnAssessmentRelationship", + "@id": "urn:spdx.dev:vex-not-affected-1", + "relationshipType": "doesNotAffect", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "justificationType": "componentNotPresent", + "impactStatement": "Not using this vulnerable part of this library.", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VexVulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "impactStatementTime" ; + sh:path security:impactStatementTime ], + [ sh:class security:VexJustificationType ; + sh:maxCount 1 ; + sh:name "justificationType" ; + sh:path security:justificationType ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "impactStatement" ; + sh:path security:impactStatement ] . + +security:VexUnderInvestigationVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexUnderInvestigationVulnAssessmentRelationship links a vulnerability to a +number of products stating the vulnerability's impact on them is being +investigated. It represents the VEX under_investigation status. + +**Constraints** + +When linking elements using a VexUnderInvestigationVulnAssessmentRelationship +the following requirements must be observed: + +- Elements linked with a VexUnderInvestigationVulnAssessmentRelationship are +constrained to using the underInvestigationFor relationship type. +- The from: end of the relationship must ve a /Security/Vulnerability classed +element. + +**Syntax** + +```json +{ + "@type": "VexUnderInvestigationVulnAssessmentRelationship", + "@id": "urn:spdx.dev:vex-underInvestigation-1", + "relationshipType": "underInvestigationFor", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VexVulnAssessmentRelationship ; + ns0:term_status "Stable" . + +security:Vulnerability a owl:Class, + sh:NodeShape ; + rdfs:comment """Specifies a vulnerability and its associated information. + +**Syntax** + +```json +{ + "@type": "Vulnerability", + "@id": "urn:spdx.dev:vuln-1", + "summary": "Use of a Broken or Risky Cryptographic Algorithm", + "description": "The npm package `elliptic` before version 6.5.4 are vulnerable to Cryptographic Issues via the secp256k1 implementation in elliptic/ec/key.js. There is no check to confirm that the public key point passed into the derive function actually exists on the secp256k1 curve. This results in the potential for the private key used in this implementation to be revealed after a number of ECDH operations are performed.", + "modified": "2021-03-08T16:02:43Z", + "published": "2021-03-08T16:06:50Z", + "externalIdentifiers": [ + { + "@type": "ExternalIdentifier", + "externalIdentifierType": "cve", + "identifier": "CVE-2020-2849", + "identifierLocator": [ + "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-28498", + "https://www.cve.org/CVERecord?id=CVE-2020-28498" + ], + "issuingAuthority": "urn:spdx.dev:agent-cve.org" + }, + { + "type": "ExternalIdentifier", + "externalIdentifierType": "securityOther", + "identifier": "GHSA-r9p9-mrjm-926w", + "identifierLocator": "https://github.com/advisories/GHSA-r9p9-mrjm-926w" + }, + { + "type": "ExternalIdentifier", + "externalIdentifierType": "securityOther", + "identifier": "SNYK-JS-ELLIPTIC-1064899", + "identifierLocator": "https://security.snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899" + } + ], + "externalReferences": [ + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://nvd.nist.gov/vuln/detail/CVE-2020-28498" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://ubuntu.com/security/CVE-2020-28498" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityOther", + "locator": "https://github.com/indutny/elliptic/pull/244/commits" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityOther", + "locator": "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md" + } + ] +}, +{ + "@type": "Relationship", + "@id": "urn:spdx.dev:vulnRelationship-1", + "relationshipType": "hasAssociatedVulnerability", + "from": "urn:npm-elliptic-6.5.2", + "to": ["urn:spdx.dev:vuln-1"], + "startTime": "2021-03-08T16:06:50Z" +}, +{ + "@type": "Relationship", + "@id": "urn:spdx.dev:vulnAgentRel-1", + "relationshipType": "publishedBy", + "from": "urn:spdx.dev:vuln-1", + "to": ["urn:spdx.dev:agent-snyk"], + "startTime": "2021-03-08T16:06:50Z" +} +```""" ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "publishedTime" ; + sh:path security:publishedTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "modifiedTime" ; + sh:path security:modifiedTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "withdrawnTime" ; + sh:path security:withdrawnTime ] . + + a owl:NamedIndividual, + software:DependencyConditionalityType . + + a owl:NamedIndividual, + software:DependencyConditionalityType . + + a owl:NamedIndividual, + software:DependencyConditionalityType . + + a owl:NamedIndividual, + software:DependencyConditionalityType . + + a owl:NamedIndividual, + software:DependencyConditionalityType . + +software:File a owl:Class, + sh:NodeShape ; + rdfs:comment """Refers to any object that stores content on a computer. +The type of content can optionally be provided in the contentType property. +External property restriction on /Core/Element/name: minCount: 1""" ; + rdfs:subClassOf software:SoftwareArtifact ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:MediaType ; + sh:maxCount 1 ; + sh:name "contentType" ; + sh:path software:contentType ] . + + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + +software:Sbom a owl:Class, + sh:NodeShape ; + rdfs:comment """A Software Bill of Materials (SBOM) is a collection of SPDX Elements describing a single package. +This could include details of the content and composition of the product, +provenance details of the product and/or +its composition, licensing information, known quality or security issues, etc.""" ; + rdfs:subClassOf core:Bom ; + ns0:term_status "Stable" ; + sh:property [ sh:class software:SBOMType ; + sh:name "sbomType" ; + sh:path software:sbomType ] . + +software:Snippet a owl:Class, + sh:NodeShape ; + rdfs:comment """A Snippet describes a certain part of a file and can be used when the file is known to have some content +that has been included from another original source. Snippets are useful for denoting when part of a file +may have been originally created under another license or copied from a place with a known vulnerability.""" ; + rdfs:subClassOf software:SoftwareArtifact ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:PositiveIntegerRange ; + sh:maxCount 1 ; + sh:name "byteRange" ; + sh:path software:byteRange ], + [ sh:class core:PositiveIntegerRange ; + sh:maxCount 1 ; + sh:name "lineRange" ; + sh:path software:lineRange ] . + + a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + + a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + + a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + + a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + +software:SoftwareDependencyRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO" ; + rdfs:subClassOf core:LifecycleScopedRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:class software:SoftwareDependencyLinkType ; + sh:maxCount 1 ; + sh:name "softwareLinkage" ; + sh:path software:softwareLinkage ], + [ sh:class software:DependencyConditionalityType ; + sh:maxCount 1 ; + sh:name "conditionality" ; + sh:path software:conditionality ] . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + + a owl:NamedIndividual, + software:SoftwarePurpose . + +ai:autonomyType a owl:DatatypeProperty ; + rdfs:comment """AutonomyType indicates if a human is involved in any of the decisions of the AI software +or if that software is fully automatic.""" ; + rdfs:range ai:PresenceType ; + ns0:term_status "Stable" . + +ai:domain a owl:DatatypeProperty ; + rdfs:comment """Domain describes the domain in which the AI model contained in the AI software +can be expected to operate successfully. Examples include computer vision, natural language etc.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:energyConsumption a owl:DatatypeProperty ; + rdfs:comment """EnergyConsumption captures the amount of energy needed to train and operate the AI model. +This value is also known as training energy consumption or inference energy consumption.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:hyperparameter a owl:DatatypeProperty ; + rdfs:comment """This field records a hyperparameter value. +Hyperparameters are parameters of the machine learning model that are used to control the learning process, +for example the optimization and learning rate used during the training of the model.""" ; + rdfs:range core:DictionaryEntry ; + ns0:term_status "Stable" . + +ai:informationAboutApplication a owl:DatatypeProperty ; + rdfs:comment """InformationAboutApplication describes any relevant information in free form text about +how the AI model is used inside the software, as well as any relevant pre-processing steps, third party APIs etc.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:informationAboutTraining a owl:DatatypeProperty ; + rdfs:comment """InformationAboutTraining describes the specific steps involved in the training of the AI model. +For example, it can be specified whether supervised fine-tuning +or active learning is used as part of training the model.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:limitation a owl:DatatypeProperty ; + rdfs:comment """Limitation captures a limitation of the AI Package (or of the AI models present in the AI package), +expressed as free form text. Note that this is not guaranteed to be exhaustive. +For instance, a limitation might be that the AI package cannot be used on datasets from a certain demography.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:metric a owl:DatatypeProperty ; + rdfs:comment """Metric records the measurement with which the AI model was evaluated. +This makes statements about the prediction quality including uncertainty, +accuracy, characteristics of the tested population, quality, fairness, explainability, robustness etc.""" ; + rdfs:range core:DictionaryEntry ; + ns0:term_status "Stable" . + +ai:metricDecisionThreshold a owl:DatatypeProperty ; + rdfs:comment """Each metric might be computed based on a decision threshold. +For instance, precision or recall is typically computed by checking +if the probability of the outcome is larger than 0.5. +Each decision threshold should match with a metric field defined in the AI Package.""" ; + rdfs:range core:DictionaryEntry ; + ns0:term_status "Stable" . + +ai:modelDataPreprocessing a owl:DatatypeProperty ; + rdfs:comment """ModelDataPreprocessing is a free form text that describes the preprocessing steps +applied to the training data before training of the model(s) contained in the AI software.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:modelExplainability a owl:DatatypeProperty ; + rdfs:comment """ModelExplainability is a free form text that lists the different explainability mechanisms +(such as SHAP, or other model specific explainability mechanisms) that can be used to explain the model.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:safetyRiskAssessment a owl:DatatypeProperty ; + rdfs:comment """SafetyRiskAssessment categorizes the safety risk impact of the AI software +in accordance with Article 20 of [EC Regulation No 765/2008](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).""" ; + rdfs:range ai:SafetyRiskAssessmentType ; + ns0:term_status "Stable" . + +ai:sensitivePersonalInformation a owl:DatatypeProperty ; + rdfs:comment """SensitivePersonalInformation notes if sensitive personal information +is used in the training or inference of the AI models. +This might include biometric data, addresses or other data that can be used to infer a person's identity.""" ; + rdfs:range ai:PresenceType ; + ns0:term_status "Stable" . + +ai:standardCompliance a owl:DatatypeProperty ; + rdfs:comment """StandardCompliance captures a standard that the AI software complies with. +This includes both published and unpublished standards, for example ISO, IEEE, ETSI etc. +The standard could (but not necessarily have to) be used to satisfy a legal or regulatory requirement.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:typeOfModel a owl:DatatypeProperty ; + rdfs:comment """TypeOfModel records the type of the AI model(s) used in the software. +For instance, if it is a supervised model, unsupervised model, reinforcement learning model or a combination of those.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +build:buildEndTime a owl:DatatypeProperty ; + rdfs:comment "buildEndTime describes the time at which a build stops or finishes. This value is typically recorded by the builder." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +build:buildId a owl:DatatypeProperty ; + rdfs:comment "A buildId is a locally unique identifier to identify a unique instance of a build. This identifier differs based on build toolchain, platform, or naming convention used by an organization or standard." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +build:buildStartTime a owl:DatatypeProperty ; + rdfs:comment "buildStartTime is the time at which a build is triggered. The builder typically records this value." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +build:buildType a owl:DatatypeProperty ; + rdfs:comment "A buildType is a URI expressing the toolchain, platform, or infrastructure that the build was invoked on. For example, if the build was invoked on GitHub's CI platform using github actions, the buildType can be expressed as `https://github.com/actions`. In contrast, if the build was invoked on a local machine, the buildType can be expressed as `file://username@host/path/to/build`." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +build:configSourceDigest a owl:DatatypeProperty ; + rdfs:comment "configSourceDigest is the checksum of the build configuration file used by a builder to execute a build. This Property uses the Core model's [Hash](../../Core/Classes/Hash.md) class." ; + rdfs:range core:Hash ; + ns0:term_status "Stable" . + +build:configSourceEntrypoint a owl:DatatypeProperty ; + rdfs:comment """A build entrypoint is the invoked executable of a build which always runs when the build is triggered. For example, when a build is triggered by running a shell script, the entrypoint is `script.sh`. In terms of a declared build, the entrypoint is the position in a configuration file or a build declaration which is always run when the build is triggered. For example, in the following configuration file, the entrypoint of the build is `publish`. + +``` +name: Publish packages to PyPI + +on: +create: +tags: "*" + +jobs: +publish: +runs-on: ubuntu-latest +if: startsWith(github.ref, 'refs/tags/') +steps: + +... +```""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +build:configSourceUri a owl:DatatypeProperty ; + rdfs:comment """If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. +m""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +build:environment a owl:DatatypeProperty ; + rdfs:comment "environment is a map of environment variables and values that are set during a build session. This is different from the [parameters](parameters.md) property in that it describes the environment variables set before a build is invoked rather than the variables provided to the builder." ; + rdfs:range core:DictionaryEntry ; + ns0:term_status "Stable" . + +build:parameters a owl:DatatypeProperty ; + rdfs:comment "parameters is a key-value map of all build parameters and their values that were provided to the builder for a build instance. This is different from the [environment](environment.md) property in that the keys and values are provided as command line arguments or a configuration file to the builder." ; + rdfs:range core:DictionaryEntry ; + ns0:term_status "Stable" . + +core:Artifact a owl:Class, + sh:NodeShape ; + rdfs:comment """An artifact is a distinct article or unit within the digital domain, +such as an electronic file, a software package, a device or an element of data.""" ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "validUntilTime" ; + sh:path core:validUntilTime ], + [ sh:class core:Agent ; + sh:name "originatedBy" ; + sh:path core:originatedBy ], + [ sh:class core:Agent ; + sh:name "suppliedBy" ; + sh:path core:suppliedBy ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "builtTime" ; + sh:path core:builtTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "releaseTime" ; + sh:path core:releaseTime ], + [ sh:datatype xsd:string ; + sh:name "standard" ; + sh:path core:standard ] . + +core:Bom a owl:Class, + sh:NodeShape ; + rdfs:comment """A Bill Of Materials (BOM) is a container for a grouping of SPDX-3.0 content +characterizing details about a product. +This could include details of the content and composition of the product, +provenence details of the product and/or +its composition, licensing information, known quality or security issues, etc.""" ; + rdfs:subClassOf core:Bundle ; + ns0:term_status "Stable" . + +core:ElementCollection a owl:Class, + sh:NodeShape ; + rdfs:comment "An SpdxCollection is a collection of Elements, not necessarily with unifying context." ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ], + [ sh:class core:Element ; + sh:minCount 1 ; + sh:name "rootElement" ; + sh:path core:rootElement ], + [ sh:class core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ], + [ sh:class core:Element ; + sh:minCount 1 ; + sh:name "element" ; + sh:path core:element ] . + +core:LifecycleScopedRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO" ; + rdfs:subClassOf core:Relationship ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:LifecycleScopeType ; + sh:maxCount 1 ; + sh:name "scope" ; + sh:path core:scope ] . + +core:algorithm a owl:DatatypeProperty ; + rdfs:comment "An algorithm specifies the algorithm that was used for calculating the hash value." ; + rdfs:range core:HashAlgorithm ; + ns0:term_status "Stable" . + +core:annotationType a owl:DatatypeProperty ; + rdfs:comment "An annotationType describes the type of an annotation." ; + rdfs:range core:AnnotationType ; + ns0:term_status "Stable" . + +core:begin a owl:DatatypeProperty ; + rdfs:comment "begin is a positive integer that defines the beginning of a range." ; + rdfs:range xsd:positiveInteger ; + ns0:term_status "Stable" . + +core:builtTime a owl:DatatypeProperty ; + rdfs:comment "A builtTime specifies the time an artifact was built." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +core:completeness a owl:DatatypeProperty ; + rdfs:comment """Completeness gives information about whether the provided relationships are +complete, known to be incomplete or if no assertion is made either way.""" ; + rdfs:range core:RelationshipCompleteness ; + ns0:term_status "Stable" . + +core:context a owl:DatatypeProperty ; + rdfs:comment """A context gives information about the circumstances or unifying properties +that Elements of the bundle have been assembled under.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:created a owl:DatatypeProperty ; + rdfs:comment """Created is a date that identifies when the Element was originally created. +The time stamp can serve as an indication as to whether the analysis needs to be updated. This is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.""" ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +core:createdBy a owl:ObjectProperty ; + rdfs:comment """CreatedBy identifies who or what created the Element. +The generation method will assist the recipient of the Element in assessing +the general reliability/accuracy of the analysis information.""" ; + rdfs:range core:Agent ; + ns0:term_status "Stable" . + +core:createdUsing a owl:ObjectProperty ; + rdfs:comment """CreatedUsing identifies the tooling that was used during the creation of the Element. +The generation method will assist the recipient of the Element in assessing +the general reliability/accuracy of the analysis information.""" ; + rdfs:range core:Tool ; + ns0:term_status "Stable" . + +core:dataLicense a owl:DatatypeProperty ; + rdfs:comment """The data license provides the license under which the SPDX documentation of the Element can be used. +This is to alleviate any concern that content (the data or database) in an SPDX file +is subject to any form of intellectual property right that could restrict the re-use +of the information or the creation of another SPDX file for the same project(s). +This approach avoids intellectual property and related restrictions over the SPDX file, +however individuals can still contract with each other to restrict release +of specific collections of SPDX files (which map to software bill of materials) +and the identification of the supplier of SPDX files. +Compliance with this document includes populating the SPDX fields therein +with data related to such fields ("SPDX-Metadata"). +This document contains numerous fields where an SPDX file creator may provide +relevant explanatory text in SPDX-Metadata. Without opining on the lawfulness +of "database rights" (in jurisdictions where applicable), +such explanatory text is copyrightable subject matter in most Berne Convention countries. +By using the SPDX specification, or any portion hereof, +you hereby agree that any copyright rights (as determined by your jurisdiction) +in any SPDX-Metadata, including without limitation explanatory text, +shall be subject to the terms of the Creative Commons CC0 1.0 Universal license. +For SPDX-Metadata not containing any copyright rights, +you hereby agree and acknowledge that the SPDX-Metadata is provided to you “as-is” +and without any representations or warranties of any kind concerning the SPDX-Metadata, +express, implied, statutory or otherwise, including without limitation warranties +of title, merchantability, fitness for a particular purpose, non-infringement, +or the absence of latent or other defects, accuracy, or the presence or absence of errors, +whether or not discoverable, all to the greatest extent permissible under applicable law.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:definingDocument a owl:DatatypeProperty ; + rdfs:comment "A definingDocument property is used to link an Element identifier to an SpdxDocument which contains the definition for the Element." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:description a owl:DatatypeProperty ; + rdfs:comment """This field is a detailed description of the Element. It may also be extracted from the Element itself. +The intent is to provide recipients of the SPDX file with a detailed technical explanation +of the functionality, anticipated use, and anticipated implementation of the Element. +This field may also include a description of improvements over prior versions of the Element.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:element a owl:ObjectProperty ; + rdfs:comment "This field refers to one or more Elements that are part of an ElementCollection." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:end a owl:DatatypeProperty ; + rdfs:comment "end is a positive integer that defines the end of a range." ; + rdfs:range xsd:positiveInteger ; + ns0:term_status "Stable" . + +core:endTime a owl:DatatypeProperty ; + rdfs:comment "A endTime specifies the time from which element is no applicable / valid." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +core:extension rdfs:comment "TODO" ; + ns0:term_status "Stable" . + +core:externalId a owl:DatatypeProperty ; + rdfs:comment "ExternalId identifies an external Element used within a Document but defined external to that Document." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:externalIdentifier a owl:ObjectProperty ; + rdfs:comment """ExternalIdentifier points to a resource outside the scope of SPDX-3.0 content +that uniquely identifies an Element.""" ; + rdfs:range core:ExternalIdentifier ; + ns0:term_status "Stable" . + +core:externalIdentifierType a owl:DatatypeProperty ; + rdfs:comment "An externalIdentifierType specifies the type of the external identifier." ; + rdfs:range core:ExternalIdentifierType ; + ns0:term_status "Stable" . + +core:externalReference a owl:ObjectProperty ; + rdfs:comment """This field points to a resource outside the scope of the SPDX-3.0 content +that provides additional characteristics of an Element.""" ; + rdfs:range core:ExternalReference ; + ns0:term_status "Stable" . + +core:externalReferenceType a owl:DatatypeProperty ; + rdfs:comment "An externalReferenceType specifies the type of the external reference." ; + rdfs:range core:ExternalReferenceType ; + ns0:term_status "Stable" . + +core:from a owl:ObjectProperty ; + rdfs:comment "This field references the Element on the left-hand side of a relationship." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:hashValue a owl:DatatypeProperty ; + rdfs:comment "HashValue is the result of applying a hash algorithm to an Element." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:identifier a owl:DatatypeProperty ; + rdfs:comment "An identifier uniquely identifies an external element." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:identifierLocator a owl:DatatypeProperty ; + rdfs:comment "A identifierLocator is TODO" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:issuingAuthority a owl:DatatypeProperty ; + rdfs:comment "A issuingAuthority is TODO" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:key a owl:DatatypeProperty ; + rdfs:comment """A key used in generic a key-value pair. +A key-value pair can be used to implement a dictionary which associates a key with a value.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:locationHint a owl:DatatypeProperty ; + rdfs:comment "A locationHint provides an indication of where to retrieve an external Element." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:locator a owl:DatatypeProperty ; + rdfs:comment "A locator provides the location of an external reference." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:namespace a owl:DatatypeProperty ; + rdfs:comment "A namespace provides an unambiguous mechanism for other documents to reference Elements within this document." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:originatedBy a owl:ObjectProperty ; + rdfs:comment "OriginatedBy identifies from where or whom the Element originally came." ; + rdfs:range core:Agent ; + ns0:term_status "Stable" . + +core:prefix a owl:DatatypeProperty ; + rdfs:comment "A prefix is a substitute for a URI." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:profile a owl:DatatypeProperty ; + rdfs:comment "This field provides information about which profiles the Element belongs to." ; + rdfs:range core:ProfileIdentifierType ; + ns0:term_status "Stable" . + +core:relationshipType a owl:DatatypeProperty ; + rdfs:comment """This field provides information about the relationship between two Elements. +For example, you can represent a relationship between two different Files, +between a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument.""" ; + rdfs:range core:RelationshipType ; + ns0:term_status "Stable" . + +core:releaseTime a owl:DatatypeProperty ; + rdfs:comment "A releaseTime specifies the time an artifact was released." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +core:rootElement a owl:ObjectProperty ; + rdfs:comment "A rootElement of a collection is the top level Element from which all other Elements are reached via relationships." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:scope a owl:DatatypeProperty ; + rdfs:comment "A scope is TODO" ; + rdfs:range core:LifecycleScopeType ; + ns0:term_status "Stable" . + +core:specVersion a owl:DatatypeProperty ; + rdfs:comment """The specVersion provides a reference number that can be used to understand how to parse and interpret an Element. +It will enable both future changes to the specification and to support backward compatibility. +The major version number shall be incremented when incompatible changes between versions are made +(one or more sections are created, modified or deleted). +The minor version number shall be incremented when backwards compatible changes are made. + +Here, parties exchanging information in accordance with the SPDX specification need to provide +100% transparency as to which SPDX specification version such information is conforming to.""" ; + rdfs:range core:SemVer ; + ns0:term_status "Stable" . + +core:standard a owl:DatatypeProperty ; + rdfs:comment "Various standards may be relevant to useful to capture for specific artifacts." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:startTime a owl:DatatypeProperty ; + rdfs:comment "A startTime specifies the time from which element is applicable / valid." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +core:statement a owl:DatatypeProperty ; + rdfs:comment "A statement is a commentary on an assertion that an annotator has made." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:subject a owl:ObjectProperty ; + rdfs:comment "A subject is an Element an annotator has made an assertion about." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:summary a owl:DatatypeProperty ; + rdfs:comment """A summary is a short description of an Element. Here, the intent is to allow the Element creator to +provide concise information about the function or use of the Element.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:suppliedBy a owl:ObjectProperty ; + rdfs:comment """Identify the actual distribution source for the Artifact being referenced. +This might or might not be different from the originating distribution source for the artifact.""" ; + rdfs:range core:Agent ; + ns0:term_status "Stable" . + +core:to a owl:ObjectProperty ; + rdfs:comment "This field references an Element on the right-hand side of a relationship." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:validUntilTime a owl:DatatypeProperty ; + rdfs:comment "A validUntilTime specifies until when the artifact can be used before its usage needs to be reassessed." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +core:value a owl:DatatypeProperty ; + rdfs:comment """A value used in a generic key-value pair. +A key-value pair can be used to implement a dictionary which associates a key with a value.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:anonymizationMethodUsed a owl:DatatypeProperty ; + rdfs:comment "AnonymizationMethodUsed describes the methods used to anonymize the dataset (of fields in the dataset)." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:confidentialityLevel a owl:DatatypeProperty ; + rdfs:comment "ConfidentialityLevel describes the levels of confidentiality of the data points contained in the dataset." ; + rdfs:range dataset:ConfidentialityLevelType ; + ns0:term_status "Stable" . + +dataset:dataCollectionProcess a owl:DatatypeProperty ; + rdfs:comment """DataCollectionProcess describes how a dataset was collected. +Examples include the sources from which a dataset was scrapped or +the interview protocol that was used for data collection.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:dataPreprocessing a owl:DatatypeProperty ; + rdfs:comment """DataPreprocessing describes the various preprocessing steps +that were applied to the raw data to create the dataset.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:datasetAvailability a owl:DatatypeProperty ; + rdfs:comment "Some datasets are publicly available and can be downloaded directly. Others are only accessible behind a clickthrough, or after filling a registration form. This field will describe the dataset availability from that perspective." ; + rdfs:range dataset:DatasetAvailabilityType ; + ns0:term_status "Stable" . + +dataset:datasetNoise a owl:DatatypeProperty ; + rdfs:comment """DatasetNoise describes what kinds of noises a dataset might encompass. +The field uses free form text to specify the fields or the samples that might be noisy. +Alternatively, it can also be used to describe various noises that could impact the whole dataset.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:datasetSize a owl:DatatypeProperty ; + rdfs:comment """DatasetSize Captures how large a dataset is. +The size is to be measured in bytes.""" ; + rdfs:range xsd:nonNegativeInteger ; + ns0:term_status "Stable" . + +dataset:datasetType a owl:DatatypeProperty ; + rdfs:comment "Type describes the datatype contained in the dataset. For example a dataset can be a image dataset or a text dataset or sometimes a multimodal dataset that contains multiple types of data" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:datasetUpdateMechanism a owl:DatatypeProperty ; + rdfs:comment "DatasetUpdateMechanism describes a mechanism to update the dataset." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:intendedUse a owl:DatatypeProperty ; + rdfs:comment """IntendedUse describes what the given dataset should be used for. +Some datasets are collected to be used only for particular purposes. +For example, medical data collected from a specific demography might only be applicable +for training machine learning models to make predictions for that demography. +In such a case, the intendedUse field would capture this information. +Similarly, if a dataset is collected for building a facial recognition model, +the intendedUse field would specify that.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:knownBias a owl:DatatypeProperty ; + rdfs:comment "KnownBias is a free form text field that describes the different biases that the dataset encompasses." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:sensitivePersonalInformation a owl:DatatypeProperty ; + rdfs:comment """SensitivePersonalInformation indicates the presence of sensitive personal data +or information that allows drawing conclusions about a person's identity.""" ; + rdfs:range dataset:PresenceType ; + ns0:term_status "Stable" . + +dataset:sensor a owl:DatatypeProperty ; + rdfs:comment """Sensor describes a sensor that was used for collecting the data +and its calibration value as a key-value pair.""" ; + rdfs:range core:DictionaryEntry ; + ns0:term_status "Stable" . + +licensing:additionComment a owl:DatatypeProperty ; + rdfs:comment """An additionComment for a LicenseAddition describes general factual information +about the LicenseAddition. It should not contain information (or links to +information) that includes any kind of interpretation about the meaning or +effect of the License, even if written by the license addition's author. + +Examples of information for an additionComment may include the following: + +* If the LicenseAddition's identifier is deprecated, it may briefly explain the + reason for deprecation. +* It may include the date of release, if identified, for LicenseAdditions with + multiple versions. +* It may include links to other official language translations for the + LicenseAddition. +* It may include a reference to the License(s) with which this LicenseAddition + is typically used.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:additionId a owl:DatatypeProperty ; + rdfs:comment """An additionId contains a human-readable, short-form identifier for a +LicenseAddition. It may only include letters, numbers, period (".") and +hyphen ("-") characters. + +For a ListedLicenseException, the licenseId will be as specified on the +[SPDX Exceptions List](https://spdx.org/licenses/exceptions-index.html) for the +particular exception. + +For a CustomLicenseAddition, the short-form identifier must begin with the +prefix `AdditionRef-` and must be unique within the applicable SPDX namespace. +The short-form identifier may be preceded by an SPDX namespace or a +fully-qualified URI prefix.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:additionName a owl:DatatypeProperty ; + rdfs:comment """An additionName contains the full name of a LicenseAddition, preferably using +the title found in the applicable license addition text or file, or as +otherwise specified by the LicenseAddition's author or steward. + +When no such title is specified, using a name from another well-known source or list +of licenses additions (such as OSI or Fedora) is suggested. + +If no official or common name is known, any name may be used to aid in +distinguishing the LicenseAddition from other LicenseAdditions.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:additionText a owl:DatatypeProperty ; + rdfs:comment """An additionText contains the plain text of the LicenseAddition, without +templating or other similar markup. + +Users of the additionText for a License can apply the SPDX Matching Guidelines +when comparing it to another text for matching purposes.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:isDeprecatedAdditionId a owl:DatatypeProperty ; + rdfs:comment """The isDeprecatedAdditionId property specifies whether an identifier for a +LicenseAddition has been marked as deprecated. If the property is not defined, +then it is presumed to be false (i.e., not deprecated). + +If the LicenseAddition is included on the SPDX Exceptions List, then +the `deprecatedVersion` property indicates on which version release of the +Exceptions List it was first marked as deprecated. + +"Deprecated" in this context refers to deprecating the use of the +_identifier_, not the underlying license addition. In other words, even if a +LicenseAddition's author or steward has stated that a particular +LicenseAddition generally should not be used, that would _not_ mean that the +LicenseAddition's identifier is "deprecated." Rather, a LicenseAddition +operator is typically marked as "deprecated" when it is determined that use of +another identifier is preferable.""" ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +licensing:isDeprecatedLicenseId a owl:DatatypeProperty ; + rdfs:comment """The isDeprecatedLicenseId property specifies whether an identifier for a +License or LicenseAddition has been marked as deprecated. If the property +is not defined, then it is presumed to be false (i.e., not deprecated). + +If the License or LicenseAddition is included on the SPDX License List, then +the `deprecatedVersion` property indicates on which version release of the +License List it was first marked as deprecated. + +"Deprecated" in this context refers to deprecating the use of the +_identifier_, not the underlying license. In other words, even if a License's +author or steward has stated that a particular License generally should not be +used, that would _not_ mean that the License's identifier is "deprecated." +Rather, a License or LicenseAddition operator is typically marked as +"deprecated" when it is determined that use of another identifier is +preferable.""" ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +licensing:isFsfLibre a owl:DatatypeProperty ; + rdfs:comment """isFsfLibre specifies whether the [Free Software Foundation FSF](https://fsf.org) +has listed this License as "free" in their commentary on licenses, located at +the time of this writing at https://www.gnu.org/licenses/license-list.en.html. + +A value of "true" indicates that the FSF has listed this License as _free_. + +A value of "false" indicates that the FSF has listed this License as _not free_. + +If the isFsfLibre field is not specified, the SPDX data creator makes no +assertions about whether the License is listed in the FSF's commentary.""" ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +licensing:isOsiApproved a owl:DatatypeProperty ; + rdfs:comment """isOsiApproved specifies whether the [Open Source Initiative (OSI)](https://opensource.org) +has listed this License as "approved" in their list of OSI Approved Licenses, +located at the time of this writing at https://opensource.org/licenses/. + +A value of "true" indicates that the OSI has listed this License as approved. + +A value of "false" indicates that the OSI has not listed this License as +approved. + +If the isOsiApproved field is not specified, the SPDX data creator makes no +assertions about whether the License is approved by the OSI.""" ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +licensing:licenseComment a owl:DatatypeProperty ; + rdfs:comment """A licenseComment describes general factual information about the License. It +should not contain information (or links to information) that includes any kind +of interpretation about the meaning or effect of the License, even if written +by the license's author. + +Examples of information for a licenseComment may include the following: + +* If the License's identifier is deprecated, it may briefly explain the reason + for deprecation. +* It may include the date of release, if identified, for Licenses with multiple + versions. +* It may include links to other official language translations for the License. +* For LicenseAdditions, it may include a reference to the License(s) with + which this additional text is typically used.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:licenseId a owl:DatatypeProperty ; + rdfs:comment """A licenseId contains a human-readable, short-form license identifier for a +License. It may only include letters, numbers, period (".") and hyphen ("-") +characters. + +For a ListedLicense, the licenseId will be as specified on the +[SPDX License List](https://spdx.org/licenses) for the particular license. + +For a CustomLicense, the short-form license identifer must begin with the +prefix `LicenseRef-` and must be unique within the applicable SPDX namespace. +The short-form license ID may be preceded by an SPDX namespace or a +fully-qualified URI prefix.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:licenseName a owl:DatatypeProperty ; + rdfs:comment """A licenseName contains the full name of a License, preferably using the title found +in the applicable license text or file, or as otherwise specified by the +License's author or steward. + +When no such title is specified, using a name from another well-known source or list +of licenses (such as OSI or Fedora) is suggested. + +If no official or common name is known, any name may be used to aid in +distinguishing the License from other Licenses.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:licenseText a owl:DatatypeProperty ; + rdfs:comment """A licenseText contains the plain text of the License, without templating +or other similar markup. + +Users of the licenseText for a License can apply the SPDX Matching Guidelines +when comparing it to another text for matching purposes.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:standardAdditionTemplate a owl:DatatypeProperty ; + rdfs:comment """A standardAdditionTemplate contains a license addition template which describes +sections of the LicenseAddition text which can be varied. See the Legacy Text +Template format section of the SPDX specification for format information.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:standardLicenseHeader a owl:DatatypeProperty ; + rdfs:comment """A standardLicenseHeader contains the plain text of the License author's +preferred wording to be used, typically in a source code file's header +comments or similar location, to indicate that the file is subject to +the specified License.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:standardLicenseTemplate a owl:DatatypeProperty ; + rdfs:comment """A standardLicenseTemplate contains a license template which describes +sections of the License text which can be varied. See the Legacy Text Template +format section of the SPDX specification for format information.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:subjectAddition a owl:ObjectProperty ; + rdfs:comment """A subjectAddition is a LicenseAddition which is subject to a 'with additional +text' effect (WithAdditionOperator).""" ; + rdfs:range licensing:LicenseAddition ; + ns0:term_status "Stable" . + +security:actionStatement a owl:DatatypeProperty ; + rdfs:comment """When an element is referenced with a VexAffectedVulnAssessmentRelationship, +the relationship MUST include one actionStatement that SHOULD describe actions +to remediate or mitigate the vulnerability.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +security:actionStatementTime a owl:DatatypeProperty ; + rdfs:comment "TODO" ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +security:assessedElement a owl:ObjectProperty ; + rdfs:comment """Specifies subpackages, files or snippets referenced by a security assessment +to specify the precise location where a vulnerability was found.""" ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +security:catalogType a owl:DatatypeProperty ; + rdfs:comment "A catalogType is a mandatory value and must select one of the two entries in the `ExploitCatalogType.md` vocabulary." ; + rdfs:range security:ExploitCatalogType ; + ns0:term_status "Stable" . + +security:decisionType a owl:DatatypeProperty ; + rdfs:comment "A decisionType is a mandatory value and must select one of the four entries in the `SsvcDecisionType.md` vocabulary." ; + rdfs:range security:SsvcDecisionType ; + ns0:term_status "Stable" . + +security:exploited a owl:DatatypeProperty ; + rdfs:comment "This field is set when a CVE is listed in an exploit catalog." ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +security:impactStatement a owl:DatatypeProperty ; + rdfs:comment """When a VEX product element is related with a VexNotAffectedVulnAssessmentRelationship +and a machine readable justification label is not provided, then an impactStatement +that further explains how or why the prouct(s) are not affected by the vulnerability +must be provided.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +security:impactStatementTime a owl:DatatypeProperty ; + rdfs:comment "TODO" ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +security:justificationType a owl:DatatypeProperty ; + rdfs:comment """When stating that an element is not affected by a vulnerability, the +VexNotAffectedVulnAssessmentRelationship must include a justification from the +machine-readable labels catalog informing the reason the element is not impacted. + +impactStatement which is a string with English prose can be used instead or as +complementary to the justification label, but one of both MUST be defined.""" ; + rdfs:range security:VexJustificationType ; + ns0:term_status "Stable" . + +security:locator a owl:DatatypeProperty ; + rdfs:comment "A locator provides the location of an exploit catalog." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +security:probability a owl:DatatypeProperty ; + rdfs:comment """The probability score between 0 and 1 (0 and 100%) estimating the likelihood +that a vulnerability will be exploited in the next 12 months.""" ; + rdfs:range xsd:decimal ; + ns0:term_status "Stable" . + +security:statusNotes a owl:DatatypeProperty ; + rdfs:comment "TODO" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +security:suppliedBy a owl:ObjectProperty ; + rdfs:comment "Identify the actual distribution source for the vulnerability assessment relationship being referenced." ; + rdfs:range core:Agent ; + ns0:term_status "Stable" . + +security:vexVersion a owl:DatatypeProperty ; + rdfs:comment "TODO" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +software:additionalPurpose a owl:DatatypeProperty ; + rdfs:comment "Additional purpose provides information about the additional purposes of the software artifact in addition to the primaryPurpose." ; + rdfs:range software:SoftwarePurpose ; + ns0:term_status "Stable" . + +software:attributionText a owl:DatatypeProperty ; + rdfs:comment """An attributionText for a software Package, File or Snippet provides a consumer +of SPDX data with acknowledgement content, to assist redistributors of the +Package, File or Snippet with reproducing those acknowledgements. + +For example, this field may include a statement that is required by a +particular license to be reproduced in end-user documentation, advertising +materials, or another form. + +This field may describe where, or in which contexts, the acknowledgements +need to be reproduced, but it is not required to do so. The SPDX data creator +may also explain elsewhere (such as in a licenseComment field) how they intend +for data in this field to be used. + +An attributionText is is not meant to include the software Package, File or +Snippet’s actual complete license text (see concludedLicense to identify the +corresponding license).""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +software:byteRange a owl:DatatypeProperty ; + rdfs:comment """This field defines the byte range in the original host file that the snippet information applies to. +A range of bytes is independent of various formatting concerns, and the most accurate way +of referring to the differences. The choice was made to start the numbering of +the byte range at 1 to be consistent with the W3C pointer method vocabulary.""" ; + rdfs:range core:PositiveIntegerRange ; + ns0:term_status "Stable" . + +software:concludedLicense a owl:ObjectProperty ; + rdfs:comment """A concludedLicense is the license identified by the SPDX data creator, +based on analyzing the license information in the software Package, File +or Snippet and other information to arrive at a reasonably objective +conclusion as to what license governs it. + +If a concludedLicense has a NONE value (NoneLicense), this indicates that the +SPDX data creator has looked and did not find any license information for this +software Package, File or Snippet. + +If a concludedLicense has a NOASSERTION value (NoAssertionLicense), this +indicates that one of the following applies: +* the SPDX data creator has attempted to but cannot reach a reasonable + objective determination; +* the SPDX data creator has made no attempt to determine this field; or +* the SPDX data creator has intentionally provided no information (no + meaning should be implied by doing so). + +A written explanation of a NOASSERTION value (NoAssertionLicense) MAY be +provided in the licenseComment field. + +If the concludedLicense for a software Package, File or Snippet is not the +same as its declaredLicense, a written explanation SHOULD be provided in +the licenseComment field. + +If the declaredLicense for a software Package, File or Snippet is a choice +of more than one license (e.g. a license expression combining two licenses +through use of the `OR` operator), then the concludedLicense may either +retain the license choice or identify which license was chosen.""" ; + rdfs:range licensing:LicenseField ; + ns0:term_status "Stable" . + +software:conditionality a owl:DatatypeProperty ; + rdfs:comment "A conditionality is TODO" ; + rdfs:range software:DependencyConditionalityType ; + ns0:term_status "Stable" . + +software:contentIdentifier a owl:DatatypeProperty ; + rdfs:comment "A contentIdentifier is TODO" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +software:contentType a owl:DatatypeProperty ; + rdfs:comment """This field is a reasonable estimation of the content type of the Element, from a creator perspective. +Content type is intrinsic to the Element, independent of how the Element is being used.""" ; + rdfs:range core:MediaType ; + ns0:term_status "Stable" . + +software:copyrightText a owl:ObjectProperty ; + rdfs:comment """A copyrightText consists of the text(s) of the copyright notice(s) found +for a software Package, File or Snippet, if any. + +If a copyrightText contains text, then it may contain any text related to +one or more copyright notices (even if not complete) for that software +Package, File or Snippet. + +If a copyrightText has a "NONE" value, this indicates that the software +Package, File or Snippet contains no copyright notice whatsoever. + +If a copyrightText has a "NOASSERTION" value, this indicates that one of the +following applies: +* the SPDX data creator has attempted to but cannot reach a reasonable + objective determination; +* the SPDX data creator has made no attempt to determine this field; or +* the SPDX data creator has intentionally provided no information (no + meaning should be implied by doing so).""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +software:declaredLicense a owl:ObjectProperty ; + rdfs:comment """A declaredLicense is the license identified in text in the software package, +file or snippet as the license declared by its authors. + +This field is not intended to capture license information obtained from an +external source, such as a package's website. Such information can be +included, as needed, in a concludedLicense field. + +A declaredLicense may be expressed differently in practice for different +types of artifacts. For example: + +* for Packages: + * would include license info describing the license of the Package as a + whole, when it is found in the Package itself (e.g., LICENSE file, + README file, metadata in the repository, etc.) + * would not include any license information that is not in the Package + itself (e.g., license information from the project’s website or from a + third party repository or website) +* for Files: + * would include license info found in the File itself (e.g., license + header or notice, comments, SPDX-License-Identifier expression) + * would not include license info found in a different file (e.g., LICENSE + file in the top directory of a repository) +* for Snippets: + * would include license info found in the Snippet itself (e.g., license + notice, comments, SPDX-License-Identifier expression) + * would not include license info found elsewhere in the File or in a + different File (e.g., comment at top of File if it is not within the + Snippet, LICENSE file in the top directory of a repository) + +If a declaredLicense has a NONE value (NoneLicense), this indicates that the +corresponding Package, File or Snippet contains no license information +whatsoever. + +If a declaredLicense has a NOASSERTION value (NoAssertionLicense), this +indicates that one of the following applies: +* the SPDX data creator has attempted to but cannot reach a reasonable + objective determination; +* the SPDX data creator has made no attempt to determine this field; or +* the SPDX data creator has intentionally provided no information (no meaning + should be implied by doing so).""" ; + rdfs:range licensing:LicenseField ; + ns0:term_status "Stable" . + +software:downloadLocation a owl:DatatypeProperty ; + rdfs:comment """DownloadLocation identifies the download Uniform Resource Identifier +for the package at the time that the document was created. +Where and how to download the exact package being referenced +is critical for verification and tracking data.""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +software:homePage a owl:DatatypeProperty ; + rdfs:comment """HomePage is a place for the SPDX document creator to record a website that serves as the package's home page. +This saves the recipient of the SPDX document who is looking for more info from +having to search for and verify a match between the package and the associated project home page. +This link can also be used to reference further information about the package +referenced by the SPDX document creator.""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +software:lineRange a owl:DatatypeProperty ; + rdfs:comment """This field defines the line range in the original host file that the snippet information applies to. +If there is a disagreement between the byte range and line range, the byte range values will take precedence. +A range of lines is a convenient reference for those files where there is a known line delimiter. +The choice was made to start the numbering of the lines at 1 to be consistent with the W3C pointer method vocabulary.""" ; + rdfs:range core:PositiveIntegerRange ; + ns0:term_status "Stable" . + +software:packageUrl a owl:DatatypeProperty ; + rdfs:comment "A packageUrl is TODO" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +software:packageVersion a owl:DatatypeProperty ; + rdfs:comment "A packageVersion is useful for identification purposes and for indicating later changes of the package version." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +software:primaryPurpose a owl:DatatypeProperty ; + rdfs:comment "primaryPurpose provides information about the primary purpose of the software artifact." ; + rdfs:range software:SoftwarePurpose ; + ns0:term_status "Stable" . + +software:sbomType a owl:DatatypeProperty ; + rdfs:comment """This field is a reasonable estimation of the type of SBOM created from a creator perspective. +It is intended to be used to give guidance on the elements that may be contained within it. +Aligning with the guidance produced in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf).""" ; + rdfs:range software:SBOMType ; + ns0:term_status "Stable" . + +software:softwareLinkage a owl:DatatypeProperty ; + rdfs:comment "A softwareLinkage is TODO" ; + rdfs:range software:SoftwareDependencyLinkType ; + ns0:term_status "Stable" . + +software:sourceInfo a owl:DatatypeProperty ; + rdfs:comment """SourceInfo records any relevant background information or additional comments +about the origin of the package. For example, this field might include comments +indicating whether the package was pulled from a source code management system +or has been repackaged. The creator can provide additional information to describe +any anomalies or discoveries in the determination of the origin of the package.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:Bundle a owl:Class, + sh:NodeShape ; + rdfs:comment "A bundle is a collection of Elements that have a shared context." ; + rdfs:subClassOf core:ElementCollection ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "context" ; + sh:path core:context ] . + +core:ExternalIdentifier a owl:Class, + sh:NodeShape ; + rdfs:comment """An ExternalIdentifier is a reference to a resource outside the scope of SPDX-3.0 content +that uniquely identifies an Element.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "identifier" ; + sh:path core:identifier ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ], + [ sh:datatype xsd:anyURI ; + sh:name "identifierLocator" ; + sh:path core:identifierLocator ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "issuingAuthority" ; + sh:path core:issuingAuthority ], + [ sh:class core:ExternalIdentifierType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "externalIdentifierType" ; + sh:path core:externalIdentifierType ] . + +core:ExternalReference a owl:Class, + sh:NodeShape ; + rdfs:comment """An External Reference points to a resource outside the scope of the SPDX-3.0 content +that provides additional characteristics of an Element.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:ExternalReferenceType ; + sh:maxCount 1 ; + sh:name "externalReferenceType" ; + sh:path core:externalReferenceType ], + [ sh:datatype xsd:anyURI ; + sh:name "locator" ; + sh:path core:locator ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ], + [ sh:datatype core:MediaType ; + sh:maxCount 1 ; + sh:name "contentType" ; + sh:path core:contentType ] . + +core:Hash a owl:Class, + sh:NodeShape ; + rdfs:comment """A hash is a grouping of characteristics unique to the result +of applying a mathematical algorithm +that maps data of arbitrary size to a bit string (the hash) +and is a one-way function, that is, +a function which is practically infeasible to invert. +This is commonly used for integrity checking of data.""" ; + rdfs:subClassOf core:IntegrityMethod ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:HashAlgorithm ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "algorithm" ; + sh:path core:algorithm ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "hashValue" ; + sh:path core:hashValue ] . + +core:Payload a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO" ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ], + [ sh:class core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ], + [ sh:class core:CreationInfo ; + sh:maxCount 1 ; + sh:name "creationInfo" ; + sh:path core:creationInfo ] . + +core:Relationship a owl:Class, + sh:NodeShape ; + rdfs:comment """A Relationship is a grouping of characteristics unique to an assertion +that one Element is related to one or more other Elements in some way.""" ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "endTime" ; + sh:path core:endTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "startTime" ; + sh:path core:startTime ], + [ sh:class core:Element ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "from" ; + sh:path core:from ], + [ sh:class core:Element ; + sh:name "to" ; + sh:path core:to ], + [ sh:class core:RelationshipCompleteness ; + sh:maxCount 1 ; + sh:name "completeness" ; + sh:path core:completeness ], + [ sh:class core:RelationshipType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "relationshipType" ; + sh:path core:relationshipType ] . + +core:SemVer a owl:Class, + sh:NodeShape ; + rdfs:comment """The semantic version is a string +that is following the specification of [Semantic Versioning 2.0.0](https://semver.org/). +Format restriction: pattern: ^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$""" ; + rdfs:subClassOf xsd:string ; + ns0:term_status "Stable" . + +core:Tool a owl:Class, + sh:NodeShape ; + rdfs:comment "A Tool is an element of hardware and/or software utilized to carry out a particular function." ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" . + +core:contentType a owl:DatatypeProperty ; + rdfs:comment "ContentType specifies the media type of an Element." ; + rdfs:range core:MediaType ; + ns0:term_status "Stable" . + +core:name a owl:DatatypeProperty ; + rdfs:comment """This field identifies the name of an Element as designated by the creator. +The name of an Element is an important convention and easier to refer to than the URI.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:verifiedUsing a owl:ObjectProperty ; + rdfs:comment "VerifiedUsing provides an IntegrityMethod with which the integrity of an Element can be asserted." ; + rdfs:range core:IntegrityMethod ; + ns0:term_status "Stable" . + +licensing:deprecatedVersion a owl:DatatypeProperty ; + rdfs:comment """A deprecatedVersion for a ListedLicense or ListedLicenseException on the SPDX +License List specifies which version release of the License List was the first +one in which it was marked as deprecated.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:listVersionAdded a owl:DatatypeProperty ; + rdfs:comment """A listVersionAdded for a ListedLicense or ListedLicenseException on the SPDX +License List specifies which version release of the License List was the first +one in which it was included.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:member a owl:ObjectProperty ; + rdfs:comment """A member is a license expression participating in a conjuctive (of type +ConjunctiveLicenseSet) or a disjunctive (of type DisjunctiveLicenseSet) +license set.""" ; + rdfs:range licensing:AnyLicenseInfo ; + ns0:term_status "Stable" . + +licensing:obsoletedBy a owl:DatatypeProperty ; + rdfs:comment """An obsoletedBy value for a deprecated License or LicenseAddition specifies +the licenseId of the replacement License or LicenseAddition that is preferred +to be used in its place. It should use the same format as specified for a +licenseId. + +The License's or LicenseAddition's comment value may include more information +about the reason why the licenseId specified in the obsoletedBy value is +preferred.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:seeAlso a owl:DatatypeProperty ; + rdfs:comment """A seeAlso defines a cross-reference with a URL where the License or +LicenseAddition can be found in use by one or a few projects. + +If applicable, it should include a URL where the license text is posted by +the license steward, particularly if the license steward has made available a +"canonical" primary URL for the license text. + +If the license is OSI approved, a seeAlso should be included with the URL for +the license's listing on the OSI website. + +The seeAlso URL may refer to a previously-available URL for the License or +LicenseAddition which is no longer active. + +Where applicable, the seeAlso URL should include the license text in its +native language. seeAlso URLs to English or other translations may be included +where multiple, equivalent official translations exist.""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +licensing:subjectLicense a owl:ObjectProperty ; + rdfs:comment """A subjectLicense is a License which is subject to either an 'or later' effect +(OrLaterOperator) or a 'with additional text' effect (WithAdditionOperator).""" ; + rdfs:range licensing:License ; + ns0:term_status "Stable" . + +security:modifiedTime a owl:DatatypeProperty ; + rdfs:comment "Specifies a time when a vulnerability assessment was last modified." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +security:publishedTime a owl:DatatypeProperty ; + rdfs:comment "Specifies the time when a vulnerability was first published." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +security:score a owl:DatatypeProperty ; + rdfs:comment """The score provides information on the severity of a vulnerability per the +Common Vulnerability Scoring System as defined on [https://www.first.org/cvss](https://www.first.org/cvss/).""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +security:vector a owl:DatatypeProperty ; + rdfs:comment """Sepcifies the vector string of a vulnerability, a string combining metrics +from an assessment of its severity.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +security:withdrawnTime a owl:DatatypeProperty ; + rdfs:comment "Specified the time and date when a vulnerability was withdrawn." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +software:Package a owl:Class, + sh:NodeShape ; + rdfs:comment """A package refers to any unit of content that can be associated with a distribution of software. +Typically, a package is composed of one or more files. +Any of the following non-limiting examples may be (but are not required to be) represented in SPDX as a package: + + - a tarball, zip file or other archive + - a directory or sub-directory + - a separately distributed piece of software which another Package or File uses or depends upon (e.g., a Python package, a Go module, ...) + - a container image, and/or each image layer within a container image + - a collection of one or more sub-packages + - a Git repository snapshot from a particular point in time + +Note that some of these could be represented in SPDX as a file as well. +External property restriction on /Core/Element/name: minCount: 1""" ; + rdfs:subClassOf software:SoftwareArtifact ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "homePage" ; + sh:path software:homePage ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "packageVersion" ; + sh:path software:packageVersion ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "packageUrl" ; + sh:path software:packageUrl ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "sourceInfo" ; + sh:path software:sourceInfo ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "downloadLocation" ; + sh:path software:downloadLocation ] . + +core:creationInfo a owl:DatatypeProperty ; + rdfs:comment "CreationInfo provides information about the creation of the Element." ; + rdfs:range core:CreationInfo ; + ns0:term_status "Stable" . + +core:imports a owl:DatatypeProperty ; + rdfs:comment """Imports provides an ExternalMap of Element identifiers that are used within a document +but defined external to that document.""" ; + rdfs:range core:ExternalMap ; + ns0:term_status "Stable" . + +core:namespaces a owl:DatatypeProperty ; + rdfs:comment "This field provides a NamespaceMap applicable to an ElementCollection." ; + rdfs:range core:NamespaceMap ; + ns0:term_status "Stable" . + +security:severity a owl:DatatypeProperty ; + rdfs:comment """The severity field provides a human readable string, a label that can be used +as an English adjective that qualifies its numerical score.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +software:SoftwareArtifact a owl:Class, + sh:NodeShape ; + rdfs:comment """A software artifact is a distinct article or unit related to software +such as a package, a file, or a snippet.""" ; + rdfs:subClassOf core:Artifact ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "contentIdentifier" ; + sh:path software:contentIdentifier ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "attributionText" ; + sh:path software:attributionText ], + [ sh:class licensing:LicenseField ; + sh:maxCount 1 ; + sh:name "declaredLicense" ; + sh:path software:declaredLicense ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "copyrightText" ; + sh:path software:copyrightText ], + [ sh:class software:SoftwarePurpose ; + sh:maxCount 1 ; + sh:name "primaryPurpose" ; + sh:path software:primaryPurpose ], + [ sh:class licensing:LicenseField ; + sh:maxCount 1 ; + sh:name "concludedLicense" ; + sh:path software:concludedLicense ], + [ sh:class software:SoftwarePurpose ; + sh:name "additionalPurpose" ; + sh:path software:additionalPurpose ] . + +core:AnnotationType a owl:Class ; + rdfs:comment "AnnotationType specifies the type of an annotation." ; + ns0:term_status "Stable" . + +core:CreationInfo a owl:Class, + sh:NodeShape ; + rdfs:comment """The CreationInfo provides information about who created the Element, and when and how it was created. + +The dateTime created is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ], + [ sh:class core:Tool ; + sh:name "createdUsing" ; + sh:path core:createdUsing ], + [ sh:class core:Agent ; + sh:minCount 1 ; + sh:name "createdBy" ; + sh:path core:createdBy ], + [ sh:datatype core:DateTime ; + sh:name "created" ; + sh:path core:created ], + [ sh:datatype core:SemVer ; + sh:name "specVersion" ; + sh:path core:specVersion ], + [ sh:class core:ProfileIdentifierType ; + sh:minCount 1 ; + sh:name "profile" ; + sh:path core:profile ], + [ sh:datatype xsd:string ; + sh:name "dataLicense" ; + sh:path core:dataLicense ] . + +core:ExternalMap a owl:Class, + sh:NodeShape ; + rdfs:comment """An External Map is a map of Element identifiers that are used within a Document +but defined external to that Document. +The external map provides details about the externally-defined Element +such as its provenance, where to retrieve it, and how to verify its integrity.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:class core:IntegrityMethod ; + sh:name "verifiedUsing" ; + sh:path core:verifiedUsing ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "locationHint" ; + sh:path core:locationHint ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "definingDocument" ; + sh:path core:definingDocument ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "externalId" ; + sh:path core:externalId ] . + +core:IntegrityMethod a owl:Class, + sh:NodeShape ; + rdfs:comment """An IntegrityMethod provides an independently reproducible mechanism that permits verification +of a specific Element that correlates to the data in this SPDX document. This identifier enables +a recipient to determine if anything in the original Element has been changed and eliminates +confusion over which version or modification of a specific Element is referenced.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ] . + +core:NamespaceMap a owl:Class, + sh:NodeShape ; + rdfs:comment """A namespace map allows the creator of a collection of Elements to use +shorter identifiers ("prefixes") instead of URIs to provide a more +human-readable and smaller serialized representation of the Elements.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "prefix" ; + sh:path core:prefix ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "namespace" ; + sh:path core:namespace ] . + +core:PositiveIntegerRange a owl:Class, + sh:NodeShape ; + rdfs:comment """PositiveIntegerRange is a tuple of two positive integers that define a range. +"begin" must be less than or equal to "end".""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:positiveInteger ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "begin" ; + sh:path core:begin ], + [ sh:datatype xsd:positiveInteger ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "end" ; + sh:path core:end ] . + +licensing:LicenseAddition a owl:Class, + sh:NodeShape ; + rdfs:comment """A LicenseAddition represents text which is intended to be added to a License +as additional text, but which is not itself intended to be a standalone +License. + +It may be an exception which is listed on the SPDX Exceptions List +(ListedLicenseException), or may be any other additional text (as an exception +or otherwise) which is defined by an SPDX data creator (CustomLicenseAddition).""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isDeprecatedAdditionId" ; + sh:path licensing:isDeprecatedAdditionId ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "additionText" ; + sh:path licensing:additionText ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "additionId" ; + sh:path licensing:additionId ], + [ sh:datatype xsd:anyURI ; + sh:name "seeAlso" ; + sh:path licensing:seeAlso ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "obsoletedBy" ; + sh:path licensing:obsoletedBy ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "standardAdditionTemplate" ; + sh:path licensing:standardAdditionTemplate ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "additionName" ; + sh:path licensing:additionName ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "additionComment" ; + sh:path licensing:additionComment ] . + +security:ExploitCatalogType a owl:Class ; + rdfs:comment "ExploitCatalogType specifies the type of exploit catalog that a vulnerability is listed in." ; + ns0:term_status "Stable" . + +security:VexVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexVulnAssessmentRelationship is an abstract subclass that defined the common +properties shared by all the SPDX-VEX status relationships. + +**Constraints** + +When linking elements using a VexVulnAssessmentRelationship, the following +requirements must be observed: + +- The from: end must be a /Security/Vulnerability classed element +- The to: end must point to elements representing the VEX _products_. To +specify a different element where the vulnerability was detected, the VEX +relationship can optionally specify _subcomponents_ using the assessedElement +property. + +VEX inherits information from the document level down to its statements. When a +statement is missing information it can be completed by reading the equivalent +field from the containing document. For example, if a VEX relationship is +missing data in its createdBy property, tools must consider the entity +listed in the CreationInfo section of the document as the VEX author. +In the same way, when a VEX relationship does not have a created property, +the document's date must be considered as authoritative.""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "vexVersion" ; + sh:path security:vexVersion ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "statusNotes" ; + sh:path security:statusNotes ] . + +core:MediaType a owl:Class, + sh:NodeShape ; + rdfs:comment """The MediaType is a String constrained to the RFC 2046 specification. It provides a standardized +way of indicating the type of content of an Element. +A list of all possible media types is available at https://www.iana.org/assignments/media-types/media-types.xhtml.""" ; + rdfs:subClassOf xsd:string ; + ns0:term_status "Stable" . + +core:RelationshipCompleteness a owl:Class ; + rdfs:comment """RelationshipCompleteness indicates whether a relationship is complete or +known to be incomplete or if there is made no assertion either way.""" ; + ns0:term_status "Stable" . + +core:comment a owl:DatatypeProperty ; + rdfs:comment """A comment is an optional field for creators of the Element to provide comments +to the readers/reviewers of the document.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:License a owl:Class, + sh:NodeShape ; + rdfs:comment """A License represents a license text, whether listed on the SPDX License List +(ListedLicense) or defined by an SPDX data creator (CustomLicense).""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "obsoletedBy" ; + sh:path licensing:obsoletedBy ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "standardLicenseTemplate" ; + sh:path licensing:standardLicenseTemplate ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "licenseText" ; + sh:path licensing:licenseText ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isDeprecatedLicenseId" ; + sh:path licensing:isDeprecatedLicenseId ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isFsfLibre" ; + sh:path licensing:isFsfLibre ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "standardLicenseHeader" ; + sh:path licensing:standardLicenseHeader ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "licenseId" ; + sh:path licensing:licenseId ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "licenseName" ; + sh:path licensing:licenseName ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isOsiApproved" ; + sh:path licensing:isOsiApproved ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "licenseComment" ; + sh:path licensing:licenseComment ], + [ sh:datatype xsd:anyURI ; + sh:name "seeAlso" ; + sh:path licensing:seeAlso ] . + +ai:SafetyRiskAssessmentType a owl:Class ; + rdfs:comment """Lists the different safety risk type values that can be used to describe the safety risk of AI software +according to [Article 20 of Regulation 765/2008/EC](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).""" ; + ns0:term_status "Stable" . + +dataset:ConfidentialityLevelType a owl:Class ; + rdfs:comment "Describes the different confidentiality levels as given by the [Traffic Light Protocol](https://en.wikipedia.org/wiki/Traffic_Light_Protocol)." ; + ns0:term_status "Stable" . + +security:SsvcDecisionType a owl:Class ; + rdfs:comment "SsvcDecisionType specifies the type of decision that's been made according to the Stakeholder-Specific Vulnerability Categorization (SSVC) system [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc)" ; + ns0:term_status "Stable" . + +security:VulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VulnAssessmentRelationship is the ancestor class common to all vulnerability +assessment relationships. It factors out the common properties shared by them. +External property restriction on /Core/Relationship/to: minCount: 1""" ; + rdfs:subClassOf core:Relationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "withdrawnTime" ; + sh:path security:withdrawnTime ], + [ sh:class core:Element ; + sh:maxCount 1 ; + sh:name "assessedElement" ; + sh:path security:assessedElement ], + [ sh:class core:Agent ; + sh:maxCount 1 ; + sh:name "suppliedBy" ; + sh:path security:suppliedBy ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "publishedTime" ; + sh:path security:publishedTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "modifiedTime" ; + sh:path security:modifiedTime ] . + +software:SoftwareDependencyLinkType a owl:Class ; + rdfs:comment "TODO" ; + ns0:term_status "Stable" . + +ai:PresenceType a owl:Class ; + rdfs:comment "This type is used to indicate if a given field is present or absent or unknown." ; + ns0:term_status "Stable" . + +dataset:DatasetAvailabilityType a owl:Class ; + rdfs:comment "Describes the possible types of availability of a dataset, indicating whether the dataset can be directly downloaded, can be assembled using a script for scraping the data, is only available after a clickthrough or a registration form." ; + ns0:term_status "Stable" . + +licensing:LicenseField a owl:Class, + sh:NodeShape ; + rdfs:comment """A LicenseField is the primary value that is used by a licensing field for a +software Package, File or Snippet. It represents either a license expression, +or the values NOASSERTION or NONE. The specific meanings of NOASSERTION or +NONE for the particular licensing field are defined in the corresponding +property description.""" ; + ns0:term_status "Stable" . + +security:VexJustificationType a owl:Class ; + rdfs:comment "VexJustificationType specifies the type of Vulnerability Exploitability eXchange (VEX) justification." ; + ns0:term_status "Stable" . + +software:DependencyConditionalityType a owl:Class ; + rdfs:comment "TODO" ; + ns0:term_status "Stable" . + +core:LifecycleScopeType a owl:Class ; + rdfs:comment "TODO" ; + ns0:term_status "Stable" . + +licensing:AnyLicenseInfo a owl:Class, + sh:NodeShape ; + rdfs:comment """An AnyLicenseInfo is used by a licensing field for a software package, +file or snippet when its value is not NOASSERTION or NONE. It can be a +single license (either on the SPDX License List or a custom-defined license); +a single license with an "or later" operator applied; the foregoing with +additional text applied; or a set of licenses combined by applying "AND" and +"OR" operators recursively.""" ; + rdfs:subClassOf licensing:LicenseField ; + ns0:term_status "Stable" . + +software:SBOMType a owl:Class ; + rdfs:comment """The set of SBOM types with definitions as defined in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf), published on April 21, 2023. +An SBOM type describes the most likely type of an SBOM from the producer perspective, so that consumers can draw conclusions about the data inside an SBOM. A single SBOM can have multiple SBOM document types associated with it.""" ; + ns0:term_status "Stable" . + +core:Agent a owl:Class, + sh:NodeShape ; + rdfs:comment "The Agent class represents anything that has the potential to act on a system. This could be a person, organization, software agent, etc. This is not to be confused with tools that are used to perform tasks." ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" . + +core:ProfileIdentifierType a owl:Class ; + rdfs:comment "There are a set of profiles that have been defined to be valid for a specific release This file enumerates the values that have been agreed on, and may be applied to the creation information for an an element." ; + ns0:term_status "Stable" . + +core:DictionaryEntry a owl:Class, + sh:NodeShape ; + rdfs:comment "The class used for implementing a generic string mapping (also known as associative array, dictionary, or hash map) in SPDX. Each DictionaryEntry contains a key-value pair which maps the key to its associated value. To implement a dictionary, this class is to be used in a collection with unique keys." ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "key" ; + sh:path core:key ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "value" ; + sh:path core:value ] . + +core:ExternalIdentifierType a owl:Class ; + rdfs:comment "ExteralIdentifierType specifies the type of an external identifier." ; + ns0:term_status "Stable" . + +core:Element a owl:Class, + sh:NodeShape ; + rdfs:comment """An Element is a representation of a fundamental concept either directly inherent +to the Bill of Materials (BOM) domain or indirectly related to the BOM domain +and necessary for contextually characterizing BOM concepts and relationships. +Within SPDX-3.0 structure this is the base class acting as a consistent, +unifying, and interoperable foundation for all explicit +and inter-relatable content objects.""" ; + rdfs:subClassOf core:Payload ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "summary" ; + sh:path core:summary ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "description" ; + sh:path core:description ], + [ sh:datatype core:Extension ; + sh:name "extension" ; + sh:path core:extension ], + [ sh:class core:ExternalIdentifier ; + sh:name "externalIdentifier" ; + sh:path core:externalIdentifier ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "name" ; + sh:path core:name ], + [ sh:class core:ExternalReference ; + sh:name "externalReference" ; + sh:path core:externalReference ], + [ sh:class core:IntegrityMethod ; + sh:name "verifiedUsing" ; + sh:path core:verifiedUsing ], + [ sh:class core:CreationInfo ; + sh:maxCount 1 ; + sh:name "creationInfo" ; + sh:path core:creationInfo ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ] . + +core:ExternalReferenceType a owl:Class ; + rdfs:comment "ExteralReferenceType specifies the type of an external reference." ; + ns0:term_status "Stable" . + +core:HashAlgorithm a owl:Class ; + rdfs:comment """A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash) +and is a one-way function, that is, a function which is practically infeasible to invert.""" ; + ns0:term_status "Stable" . + +software:SoftwarePurpose a owl:Class ; + rdfs:comment """This field provides information about the primary purpose of an Element. +Software Purpose is intrinsic to how the Element is being used rather than the content of the Element. +This field is a reasonable estimate of the most likely usage of the Element +from the producer and consumer perspective from which both parties can draw conclusions +about the context in which the Element exists.""" ; + ns0:term_status "Stable" . + +core:DateTime a owl:Class, + sh:NodeShape ; + rdfs:comment """A Datetime is a string representation of a specific date and time. +It has resolution of seconds and is always expressed in UTC timezone. +The specific format is one of the most commonly used ISO-8601 formats. +Format restriction: pattern: ^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$""" ; + rdfs:subClassOf xsd:string ; + ns0:term_status "Stable" . + +core:RelationshipType a owl:Class ; + rdfs:comment """Provides information about the relationship between two Elements. +For example, you can represent a relationship between two different Files, +between a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument. + +Build Profile specific RelationshipType descriptions can be found [here](https://github.com/spdx/spdx-3-build-profile/blob/main/model/relationships.md)""" ; + ns0:term_status "Stable" . + diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py new file mode 100644 index 000000000..f6bc7c35a --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -0,0 +1,116 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import json +import os.path + +# current workflow: markdown files + spec_parser -> model.ttl -> convert to json_ld: SPDX_OWL.json -> +# use the function below to generate context.json +# properties with Enum range should look like this (probably), so that their values are automatically appended +# with the Enum URI: +# "annotationType": { +# "@id": "core:annotationType", +# "@type": "@vocab", +# "@context": { +# "@vocab": "core:AnnotationType/" +# } +# }, + +PROPERTIES_WITH_ENUM_RANGE = [ + "safetyRiskAssessment", + "sensitivePersonalInformation", + "annotationType", + "externalIdentifierType", + "externalReferenceType", + "algorithm", + "scope", + "profile", + "completeness", + "relationshipType", + "confidentialityLevel", + "datasetAvailability", + "decisionType", + "justificationType", + "catalogType", + "conditionality", + "sbomType", + "softwareLinkage", + "purpose", +] + +REFERENCE_PROPERTY_TYPES = [ + "core:Element", + "core:Agent", +] + + +def convert_spdx_owl_to_jsonld_context(spdx_owl: str = "SPDX_OWL.json"): + with open(spdx_owl, "r") as infile: + owl_dict = json.load(infile) + + context_dict = owl_dict["@context"] + + for node in owl_dict["@graph"]: + # print(node) + node_type = node.get("@type") + if not node_type: + # print(node) + continue + + if "owl:NamedIndividual" in node_type: + continue + elif node_type in ["owl:DatatypeProperty", "owl:ObjectProperty"]: + name = node["@id"].split(":")[-1] + type_id = node["rdfs:range"]["@id"] + + if name in context_dict and context_dict[name]["@id"].startswith("core"): + # if in doubt, prioritize core properties + continue + + if name in PROPERTIES_WITH_ENUM_RANGE: + if name == "profile": + # FIXME: since the allowed values for the profile enum collide with + # our namespaces, we need to explicitly remap their meaning in the context + context_dict[name] = { + "@id": node["@id"], + "@type": "@vocab", + "@context": { + "core": "https://spdx.org/rdf/Core/ProfileIdentifierType/core", + "software": "https://spdx.org/rdf/Core/ProfileIdentifierType/software", + "licensing": "https://spdx.org/rdf/Core/ProfileIdentifierType/licensing", + "security": "https://spdx.org/rdf/Core/ProfileIdentifierType/security", + "build": "https://spdx.org/rdf/Core/ProfileIdentifierType/build", + "ai": "https://spdx.org/rdf/Core/ProfileIdentifierType/ai", + "dataset": "https://spdx.org/rdf/Core/ProfileIdentifierType/dataset", + "usage": "https://spdx.org/rdf/Core/ProfileIdentifierType/usage", + "extension": "https://spdx.org/rdf/Core/ProfileIdentifierType/extension", + }, + } + else: + context_dict[name] = { + "@id": node["@id"], + "@type": "@vocab", + "@context": {"@vocab": type_id + "/"}, + } + elif node_type == "owl:ObjectProperty" and type_id in REFERENCE_PROPERTY_TYPES: + context_dict[name] = {"@id": node["@id"], "@type": "@id"} + else: + context_dict[name] = {"@id": node["@id"], "@type": type_id} + + elif node_type == "owl:Class": + name = node["@id"].split(":")[-1] + context_dict[name] = node["@id"] + + elif isinstance(node_type, list): + name = node["@id"].split(":")[-1] + context_dict[name] = node["@id"] + + else: + print(f"unknown node_type: {node_type}") + + with open(os.path.join(os.path.dirname(__file__), "context.json"), "w") as infile: + json.dump(context_dict, infile) + + +if __name__ == "__main__": + convert_spdx_owl_to_jsonld_context("SPDX_OWL.json") diff --git a/src/spdx_tools/spdx3/writer/json_ld/process.md b/src/spdx_tools/spdx3/writer/json_ld/process.md new file mode 100644 index 000000000..7d04d5ccd --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/process.md @@ -0,0 +1,27 @@ +### Workflow + +Process to produce context file and a serialization example: + +1. Run +``` +spec-parser --gen-md --gen-refs --gen-rdf ../spdx-3-model/model +``` +- spdx-3-model (commit: 6cb4316, last commit where spec-parser is able to run)
+- spec-parser (main with commits from PR 44, 45) + +2. Convert the generated `spec-parser/md_generated/model.ttl` to a json-ld file using https://frogcat.github.io/ttl2jsonld/demo/. +3. Convert owl to context using `convert_spdx_owl_to_jsonld_context("SPDX_OWL.json")`. +4. Place the generated `context.json` in `spdx_tools/spdx3/writer/jsonld/`. +5. To generate the jsonld from the testfile run +``` +pyspdxtools3 -i ./tests/spdx/data/SPDXJSONExample-v2.3.spdx.json -o example_with_context +``` + + +### Manually + + +### Known limitations +- Validation of enums does not work +- Additional keys seem to be ignored in validation +- inherited properties aren't validated diff --git a/tests/data/doc_parse/expected.json b/tests/data/doc_parse/expected.json deleted file mode 100644 index 1556f1387..000000000 --- a/tests/data/doc_parse/expected.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "id": "SPDXRef-DOCUMENT", - "specVersion": { - "major": 2, - "minor": 1 - }, - "namespace": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", - "name": "Sample_Document-V2.1", - "comment": "This is a sample spreadsheet", - "dataLicense": { - "type": "Single", - "identifier": "CC0-1.0", - "name": "Creative Commons Zero v1.0 Universal" - }, - "licenseListVersion": { - "major": 3, - "minor": 6 - }, - "creators": [ - { - "name": "Gary O'Neall", - "email": null, - "type": "Person" - }, - { - "name": "Source Auditor Inc.", - "email": null, - "type": "Organization" - }, - { - "name": "SourceAuditor-V1.2", - "type": "Tool" - } - ], - "created": "2010-02-03T00:00:00Z", - "creatorComment": "This is an example of an SPDX spreadsheet format", - "package": { - "id": "SPDXRef-Package", - "name": "SPDX Translator", - "packageFileName": "spdxtranslator-1.0.zip", - "summary": "SPDX Translator utility", - "description": "This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document.", - "versionInfo": "Version 0.9.2", - "sourceInfo": "Version 1.0 of the SPDX Translator application", - "downloadLocation": "http://www.spdx.org/tools", - "homepage": null, - "originator": { - "name": "SPDX", - "email": null, - "type": "Organization" - }, - "supplier": { - "name": "Linux Foundation", - "email": null, - "type": "Organization" - }, - "licenseConcluded": { - "type": "Conjunction", - "identifier": [ - "Apache-1.0", - "Apache-2.0", - "LicenseRef-1", - "LicenseRef-2", - "LicenseRef-3", - "LicenseRef-4", - "MPL-1.1" - ], - "name": [ - "Apache License 1.0", - "Apache License 2.0", - "CyberNeko License", - "Mozilla Public License 1.1", - "None", - "None", - "None" - ] - }, - "licenseDeclared": { - "type": "Conjunction", - "identifier": [ - "Apache-2.0", - "LicenseRef-1", - "LicenseRef-2", - "LicenseRef-3", - "LicenseRef-4", - "MPL-1.1" - ], - "name": [ - "Apache License 2.0", - "CyberNeko License", - "Mozilla Public License 1.1", - "None", - "None", - "None" - ] - }, - "copyrightText": " Copyright 2010, 2011 Source Auditor Inc.", - "licenseComment": "The declared license information can be found in the NOTICE file at the root of the archive file", - "checksum": { - "identifier": "SHA1", - "value": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" - }, - "files": [ - { - "id": "SPDXRef-File1", - "name": "Jenna-2.6.3/jena-2.6.3-sources.jar", - "type": 3, - "comment": "This file belongs to Jena", - "licenseConcluded": { - "type": "Single", - "identifier": "LicenseRef-1", - "name": null - }, - "copyrightText": "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP", - "licenseComment": "This license is used by Jena", - "notice": null, - "checksum": { - "identifier": "SHA1", - "value": "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" - }, - "licenseInfoFromFiles": [ - { - "type": "Single", - "identifier": "LicenseRef-1", - "name": null - } - ], - "contributors": [], - "dependencies": [], - "artifactOfProjectName": [ - "Jena" - ], - "artifactOfProjectHome": [ - "http://www.openjena.org/" - ], - "artifactOfProjectURI": [ - "http://subversion.apache.org/doap.rdf" - ] - }, - { - "id": "SPDXRef-File2", - "name": "src/org/spdx/parser/DOAPProject.java", - "type": 1, - "comment": null, - "licenseConcluded": { - "type": "Single", - "identifier": "Apache-2.0", - "name": "Apache License 2.0" - }, - "copyrightText": "Copyright 2010, 2011 Source Auditor Inc.", - "licenseComment": null, - "notice": null, - "checksum": { - "identifier": "SHA1", - "value": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" - }, - "licenseInfoFromFiles": [ - { - "type": "Single", - "identifier": "Apache-2.0", - "name": "Apache License 2.0" - } - ], - "contributors": [], - "dependencies": [], - "artifactOfProjectName": [], - "artifactOfProjectHome": [], - "artifactOfProjectURI": [] - } - ], - "licenseInfoFromFiles": [ - { - "type": "Single", - "identifier": "Apache-1.0", - "name": "Apache License 1.0" - }, - { - "type": "Single", - "identifier": "Apache-2.0", - "name": "Apache License 2.0" - }, - { - "type": "Single", - "identifier": "LicenseRef-1", - "name": null - }, - { - "type": "Single", - "identifier": "LicenseRef-2", - "name": null - }, - { - "type": "Single", - "identifier": "LicenseRef-3", - "name": "CyberNeko License" - }, - { - "type": "Single", - "identifier": "LicenseRef-4", - "name": null - }, - { - "type": "Single", - "identifier": "MPL-1.1", - "name": "Mozilla Public License 1.1" - } - ], - "verificationCode": { - "value": "4e3211c67a2d28fced849ee1bb76e7391b93feba", - "excludedFilesNames": [ - "SpdxTranslatorSpdx.rdf", - "SpdxTranslatorSpdx.txt" - ] - } - }, - "externalDocumentRefs": [ - { - "externalDocumentId": "DocumentRef-spdx-tool-2.1", - "spdxDocumentNamespace": "https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301", - "checksum": { - "identifier": "SHA1", - "value": "d6a770ba38583ed4bb4525bd96e50461655d2759" - } - } - ], - "extractedLicenses": [ - { - "name": null, - "identifier": "LicenseRef-1", - "text": "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */", - "comment": null, - "cross_refs": [] - }, - { - "name": null, - "identifier": "LicenseRef-2", - "text": "This package includes the GRDDL parser developed by Hewlett Packard under the following license:\n\u00a9 Copyright 2007 Hewlett-Packard Development Company, LP\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: \n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \nThe name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ", - "comment": null, - "cross_refs": [] - }, - { - "name": "CyberNeko License", - "identifier": "LicenseRef-3", - "text": "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the\n distribution.\n\n3. The end-user documentation included with the redistribution,\n if any, must include the following acknowledgment: \n \"This product includes software developed by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software itself,\n if and wherever such third-party acknowledgments normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n or promote products derived from this software without prior \n written permission. For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", - "comment": "This is tye CyperNeko License", - "cross_refs": [ - "http://justasample.url.com", - "http://people.apache.org/~andyc/neko/LICENSE" - ] - }, - { - "name": null, - "identifier": "LicenseRef-4", - "text": "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */ ", - "comment": null, - "cross_refs": [] - } - ], - "annotations": [ - { - "id": "SPDXRef-45", - "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses", - "type": "REVIEW", - "annotator": { - "name": "Jim Reviewer", - "email": null, - "type": "Person" - }, - "date": "2012-06-13T00:00:00Z" - } - ], - "reviews": [ - { - "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses", - "reviewer": { - "name": "Joe Reviewer", - "email": null, - "type": "Person" - }, - "date": "2010-02-10T00:00:00Z" - }, - { - "comment": "Another example reviewer.", - "reviewer": { - "name": "Suzanne Reviewer", - "email": null, - "type": "Person" - }, - "date": "2011-03-13T00:00:00Z" - } - ], - "snippets": [ - { - "id": "SPDXRef-Snippet", - "name": "from linux kernel", - "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later.", - "copyrightText": "Copyright 2008-2010 John Smith", - "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz.", - "fileId": "SPDXRef-DoapSource", - "licenseConcluded": { - "type": "Single", - "identifier": "Apache-2.0", - "name": "Apache License 2.0" - }, - "licenseInfoFromSnippet": [ - { - "type": "Single", - "identifier": "Apache-2.0", - "name": "Apache License 2.0" - } - ] - } - ] -} \ No newline at end of file diff --git a/tests/data/doc_parse/spdx-expected.json b/tests/data/doc_parse/spdx-expected.json deleted file mode 100644 index 23ab2dd89..000000000 --- a/tests/data/doc_parse/spdx-expected.json +++ /dev/null @@ -1,312 +0,0 @@ -{ - "comment": "This is a sample spreadsheet", - "externalDocumentRefs": [ - { - "checksum": { - "identifier": "SHA1", - "value": "d6a770ba38583ed4bb4525bd96e50461655d2759" - }, - "spdxDocumentNamespace": "https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301", - "externalDocumentId": "DocumentRef-spdx-tool-2.1" - } - ], - "licenseListVersion": { - "major": 3, - "minor": 6 - }, - "specVersion": { - "major": 2, - "minor": 1 - }, - "id": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DOCUMENT", - "name": "Sample_Document-V2.1", - "created": "2010-02-03T00:00:00Z", - "creatorComment": "This is an example of an SPDX spreadsheet format", - "package": { - "id": "SPDXRef-Package", - "originator": { - "type": "Organization", - "name": "SPDX", - "email": null - }, - "files": [ - { - "comment": "This file belongs to Jena", - "licenseInfoFromFiles": [ - { - "identifier": "LicenseRef-1", - "type": "Single", - "name": null - } - ], - "contributors": [], - "notice": null, - "licenseConcluded": { - "identifier": "LicenseRef-1", - "type": "Single", - "name": null - }, - "dependencies": [], - "artifactOfProjectName": [ - "Jena" - ], - "artifactOfProjectURI": [], - "id": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-File1", - "licenseComment": "This license is used by Jena", - "name": "Jenna-2.6.3/jena-2.6.3-sources.jar", - "artifactOfProjectHome": [ - "http://www.openjena.org/" - ], - "checksum": { - "identifier": "SHA1", - "value": "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" - }, - "copyrightText": "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP", - "type": 3 - }, - { - "comment": null, - "licenseInfoFromFiles": [ - { - "identifier": "Apache-2.0", - "type": "Single", - "name": "Apache License 2.0" - } - ], - "contributors": [], - "notice": null, - "licenseConcluded": { - "identifier": "Apache-2.0", - "type": "Single", - "name": "Apache License 2.0" - }, - "dependencies": [], - "artifactOfProjectName": [], - "artifactOfProjectURI": [], - "id": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-File2", - "licenseComment": null, - "name": "src/org/spdx/parser/DOAPProject.java", - "artifactOfProjectHome": [], - "checksum": { - "identifier": "SHA1", - "value": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" - }, - "copyrightText": "Copyright 2010, 2011 Source Auditor Inc.", - "type": 1 - } - ], - "licenseComment": "The declared license information can be found in the NOTICE file at the root of the archive file", - "name": "SPDX Translator", - "packageFileName": "spdxtranslator-1.0.zip", - "licenseDeclared": { - "identifier": [ - "Apache-2.0", - "LicenseRef-1", - "LicenseRef-2", - "LicenseRef-3", - "LicenseRef-4", - "MPL-1.1" - ], - "type": "Conjunction", - "name": [ - "Apache License 2.0", - "CyberNeko License", - "Mozilla Public License 1.1", - "None", - "None", - "None" - ] - }, - "sourceInfo": "Version 1.0 of the SPDX Translator application", - "summary": "SPDX Translator utility", - "licenseInfoFromFiles": [ - { - "identifier": "Apache-1.0", - "type": "Single", - "name": "Apache License 1.0" - }, - { - "identifier": "Apache-2.0", - "type": "Single", - "name": "Apache License 2.0" - }, - { - "identifier": "LicenseRef-1", - "type": "Single", - "name": null - }, - { - "identifier": "LicenseRef-2", - "type": "Single", - "name": null - }, - { - "identifier": "LicenseRef-3", - "type": "Single", - "name": "CyberNeko License" - }, - { - "identifier": "LicenseRef-4", - "type": "Single", - "name": null - }, - { - "identifier": "MPL-1.1", - "type": "Single", - "name": "Mozilla Public License 1.1" - } - ], - "licenseConcluded": { - "identifier": [ - "Apache-1.0", - "Apache-2.0", - "LicenseRef-1", - "LicenseRef-2", - "LicenseRef-3", - "LicenseRef-4", - "MPL-1.1" - ], - "type": "Conjunction", - "name": [ - "Apache License 1.0", - "Apache License 2.0", - "CyberNeko License", - "Mozilla Public License 1.1", - "None", - "None", - "None" - ] - }, - "copyrightText": " Copyright 2010, 2011 Source Auditor Inc.", - "verificationCode": { - "value": "4e3211c67a2d28fced849ee1bb76e7391b93feba", - "excludedFilesNames": [ - "SpdxTranslatorSpdx.rdf", - "SpdxTranslatorSpdx.txt" - ] - }, - "checksum": { - "identifier": "SHA1", - "value": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" - }, - "supplier": { - "type": "Organization", - "name": "Linux Foundation", - "email": null - }, - "versionInfo": "Version 0.9.2", - "homepage": null, - "downloadLocation": "http://www.spdx.org/tools", - "description": "This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document." - }, - "namespace": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", - "reviews": [ - { - "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses", - "reviewer": { - "type": "Person", - "name": "Joe Reviewer", - "email": null - }, - "date": "2010-02-10T00:00:00Z" - }, - { - "comment": "Another example reviewer.", - "reviewer": { - "type": "Person", - "name": "Suzanne Reviewer", - "email": null - }, - "date": "2011-03-13T00:00:00Z" - } - ], - "dataLicense": { - "identifier": "CC0-1.0", - "type": "Single", - "name": "Creative Commons Zero v1.0 Universal" - }, - "extractedLicenses": [ - { - "comment": null, - "text": "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */", - "cross_refs": [], - "identifier": "LicenseRef-1", - "name": null - }, - { - "comment": null, - "text": "This package includes the GRDDL parser developed by Hewlett Packard under the following license:\n\u00a9 Copyright 2007 Hewlett-Packard Development Company, LP\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: \n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \nThe name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ", - "cross_refs": [], - "identifier": "LicenseRef-2", - "name": null - }, - { - "comment": "This is tye CyperNeko License", - "text": "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the\n distribution.\n\n3. The end-user documentation included with the redistribution,\n if any, must include the following acknowledgment: \n \"This product includes software developed by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software itself,\n if and wherever such third-party acknowledgments normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n or promote products derived from this software without prior \n written permission. For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", - "cross_refs": [ - "http://justasample.url.com", - "http://people.apache.org/~andyc/neko/LICENSE" - ], - "identifier": "LicenseRef-3", - "name": "CyberNeko License" - }, - { - "comment": null, - "text": "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */ ", - "cross_refs": [], - "identifier": "LicenseRef-4", - "name": null - } - ], - "creators": [ - { - "type": "Person", - "name": "Gary O'Neall", - "email": null - }, - { - "type": "Organization", - "name": "Source Auditor Inc.", - "email": null - }, - { - "type": "Tool", - "name": "SourceAuditor-V1.2" - } - ], - "annotations": [ - { - "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses", - "date": "2012-06-13T00:00:00Z", - "type": "REVIEW", - "id": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-45", - "annotator": { - "type": "Person", - "name": "Jim Reviewer", - "email": null - } - } - ], - "snippets": [ - { - "id": "SPDXRef-Snippet", - "name": "from linux kernel", - "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later.", - "copyrightText": "Copyright 2008-2010 John Smith", - "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz.", - "fileId": "SPDXRef-DoapSource", - "licenseConcluded": { - "identifier": "Apache-2.0", - "name": "Apache License 2.0", - "type": "Single" - }, - "licenseInfoFromSnippet": [ - { - "identifier": "Apache-2.0", - "name": "Apache License 2.0", - "type": "Single" - } - ] - } - ] -} \ No newline at end of file diff --git a/tests/data/doc_write/json-simple-plus.json b/tests/data/doc_write/json-simple-plus.json deleted file mode 100644 index fc3ffa1b1..000000000 --- a/tests/data/doc_write/json-simple-plus.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "Document": { - "specVersion": "SPDX-2.1", - "dataLicense": "CC0-1.0", - "name": "Sample_Document-V2.1", - "id": "SPDXRef-DOCUMENT", - "namespace": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", - "documentDescribes": [ - { - "Package": { - "id": "SPDXRef-Package", - "name": "some/path", - "downloadLocation": "NOASSERTION", - "copyrightText": "Some copyrught", - "packageVerificationCode": { - "value": "SOME code" - }, - "checksums": [ - { - "algorithm": "checksumAlgorithm_sha1", - "value": "SOME-SHA1" - } - ], - "licenseDeclared": "NOASSERTION", - "licenseConcluded": "NOASSERTION", - "files": [ - { - "File": { - "name": "./some/path/tofile", - "id": "SPDXRef-File", - "checksums": [ - { - "algorithm": "checksumAlgorithm_sha1", - "value": "SOME-SHA1" - } - ], - "licenseConcluded": "NOASSERTION", - "copyrightText": "NOASSERTION", - "licenseInfoFromFiles": ["LGPL-2.1-or-later"], - "sha1": "SOME-SHA1" - } - } - ], - "licenseInfoFromFiles": ["LGPL-2.1-or-later"], - "sha1": "SOME-SHA1" - } - } - ] - } -} diff --git a/tests/data/doc_write/json-simple.json b/tests/data/doc_write/json-simple.json deleted file mode 100644 index 93093932d..000000000 --- a/tests/data/doc_write/json-simple.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "Document": { - "specVersion": "SPDX-2.1", - "dataLicense": "CC0-1.0", - "name": "Sample_Document-V2.1", - "id": "SPDXRef-DOCUMENT", - "namespace": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", - "documentDescribes": [ - { - "Package": { - "id": "SPDXRef-Package", - "name": "some/path", - "downloadLocation": "NOASSERTION", - "copyrightText": "Some copyrught", - "packageVerificationCode": { - "value": "SOME code" - }, - "checksums": [ - { - "algorithm": "checksumAlgorithm_sha1", - "value": "SOME-SHA1" - } - ], - "licenseDeclared": "NOASSERTION", - "licenseConcluded": "NOASSERTION", - "files": [ - { - "File": { - "name": "./some/path/tofile", - "id": "SPDXRef-File", - "checksums": [ - { - "algorithm": "checksumAlgorithm_sha1", - "value": "SOME-SHA1" - } - ], - "licenseConcluded": "NOASSERTION", - "copyrightText": "NOASSERTION", - "licenseInfoFromFiles": ["LGPL-2.1-only"], - "sha1": "SOME-SHA1" - } - } - ], - "licenseInfoFromFiles": ["LGPL-2.1-only"], - "sha1": "SOME-SHA1" - } - } - ] - } -} diff --git a/tests/data/doc_write/rdf-mini.json b/tests/data/doc_write/rdf-mini.json deleted file mode 100644 index a193c970f..000000000 --- a/tests/data/doc_write/rdf-mini.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "rdf:RDF": { - "@xmlns:ns1": "http://spdx.org/rdf/terms#", - "@xmlns:rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", - "ns1:SpdxDocument": { - "@rdf:about": "http://www.spdx.org/tools#SPDXRef-DOCUMENT", - "ns1:specVersion": "SPDX-2.1", - "ns1:dataLicense": { - "@rdf:resource": "http://spdx.org/licenses/CC0-1.0" - }, - "ns1:describesPackage": { - "ns1:Package": { - "@rdf:about": "http://www.spdx.org/tools#SPDXRef-Package", - "ns1:downloadLocation": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:licenseConcluded": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:name": "None", - "ns1:copyrightText": "None", - "ns1:licenseDeclared": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - } - } - } - } - } -} \ No newline at end of file diff --git a/tests/data/doc_write/rdf-simple-plus.json b/tests/data/doc_write/rdf-simple-plus.json deleted file mode 100644 index 5f84b380f..000000000 --- a/tests/data/doc_write/rdf-simple-plus.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "rdf:RDF": { - "@xmlns:ns1": "http://spdx.org/rdf/terms#", - "@xmlns:rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", - "ns1:SpdxDocument": { - "ns1:describesPackage": { - "ns1:Package": { - "@rdf:about": "http://www.spdx.org/tools#SPDXRef-Package", - "ns1:Package": { - "@rdf:resource": "SPDXRef-Package" - }, - "ns1:hasFile": { - "@rdf:resource": "http://www.spdx.org/files#SPDXRef-File" - }, - "ns1:name": "some/path", - "ns1:licenseDeclared": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:downloadLocation": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:licenseInfoFromFiles": { - "@rdf:resource": "http://spdx.org/licenses/LGPL-2.1-or-later" - }, - "ns1:licenseConcluded": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:copyrightText": "Some copyrught", - "ns1:checksum": { - "ns1:Checksum": { - "ns1:algorithm": "SHA1", - "ns1:checksumValue": "SOME-SHA1" - } - } - } - }, - "ns1:specVersion": "SPDX-2.1", - "ns1:dataLicense": { - "@rdf:resource": "http://spdx.org/licenses/CC0-1.0" - }, - "ns1:name": { - "@rdf:resource": "Sample_Document-V2.1" - }, - "ns1:referencesFile": { - "ns1:File": { - "@rdf:about": "http://www.spdx.org/files#SPDXRef-File", - "ns1:fileName": "./some/path/tofile", - "ns1:checksum": { - "ns1:Checksum": { - "ns1:checksumValue": "SOME-SHA1", - "ns1:algorithm": "SHA1" - } - }, - "ns1:licenseConcluded": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:copyrightText": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:licenseInfoInFile": { - "@rdf:resource": "http://spdx.org/licenses/LGPL-2.1-or-later" - } - } - }, - "@rdf:about": "http://www.spdx.org/tools#SPDXRef-DOCUMENT" - } - } -} \ No newline at end of file diff --git a/tests/data/doc_write/rdf-simple.json b/tests/data/doc_write/rdf-simple.json deleted file mode 100644 index 7327c703f..000000000 --- a/tests/data/doc_write/rdf-simple.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "rdf:RDF": { - "@xmlns:ns1": "http://spdx.org/rdf/terms#", - "@xmlns:rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", - "ns1:SpdxDocument": { - "ns1:describesPackage": { - "ns1:Package": { - "@rdf:about": "http://www.spdx.org/tools#SPDXRef-Package", - "ns1:Package": { - "@rdf:resource": "SPDXRef-Package" - }, - "ns1:hasFile": { - "@rdf:resource": "http://www.spdx.org/files#SPDXRef-File" - }, - "ns1:downloadLocation": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:licenseDeclared": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:name": "some/path", - "ns1:licenseInfoFromFiles": { - "@rdf:resource": "http://spdx.org/licenses/LGPL-2.1-only" - }, - "ns1:licenseConcluded": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:copyrightText": "Some copyrught", - "ns1:checksum": { - "ns1:Checksum": { - "ns1:algorithm": "SHA1", - "ns1:checksumValue": "SOME-SHA1" - } - } - } - }, - "ns1:specVersion": "SPDX-2.1", - "ns1:dataLicense": { - "@rdf:resource": "http://spdx.org/licenses/CC0-1.0" - }, - "ns1:name": { - "@rdf:resource": "Sample_Document-V2.1" - }, - "ns1:referencesFile": { - "ns1:File": { - "@rdf:about": "http://www.spdx.org/files#SPDXRef-File", - "ns1:licenseInfoInFile": { - "@rdf:resource": "http://spdx.org/licenses/LGPL-2.1-only" - }, - "ns1:checksum": { - "ns1:Checksum": { - "ns1:checksumValue": "SOME-SHA1", - "ns1:algorithm": "SHA1" - } - }, - "ns1:licenseConcluded": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:copyrightText": { - "@rdf:resource": "http://spdx.org/rdf/terms#noassertion" - }, - "ns1:fileName": "./some/path/tofile" - } - }, - "@rdf:about": "http://www.spdx.org/tools#SPDXRef-DOCUMENT" - } - } -} \ No newline at end of file diff --git a/tests/data/doc_write/tv-mini.tv b/tests/data/doc_write/tv-mini.tv deleted file mode 100644 index 161849ac5..000000000 --- a/tests/data/doc_write/tv-mini.tv +++ /dev/null @@ -1,11 +0,0 @@ -# Document Information -SPDXVersion: SPDX-2.1 -DataLicense: CC0-1.0 -SPDXID: SPDXRef-DOCUMENT -# Creation Info -# Package -PackageDownloadLocation: NOASSERTION -PackageVerificationCode: None -PackageLicenseDeclared: NOASSERTION -PackageLicenseConcluded: NOASSERTION -# Extracted Licenses \ No newline at end of file diff --git a/tests/data/doc_write/tv-simple-plus.tv b/tests/data/doc_write/tv-simple-plus.tv deleted file mode 100644 index 8b4c7008a..000000000 --- a/tests/data/doc_write/tv-simple-plus.tv +++ /dev/null @@ -1,25 +0,0 @@ -# Document Information -SPDXVersion: SPDX-2.1 -DataLicense: CC0-1.0 -DocumentName: Sample_Document-V2.1 -SPDXID: SPDXRef-DOCUMENT -DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 -# Creation Info -# Package -PackageName: some/path -SPDXID: SPDXRef-Package -PackageDownloadLocation: NOASSERTION -PackageChecksum: SHA1: SOME-SHA1 -PackageVerificationCode: SOME code -PackageLicenseDeclared: NOASSERTION -PackageLicenseConcluded: NOASSERTION -PackageLicenseInfoFromFiles: LGPL-2.1-or-later -PackageCopyrightText: Some copyrught -# File -FileName: ./some/path/tofile -SPDXID: SPDXRef-File -FileChecksum: SHA1: SOME-SHA1 -LicenseConcluded: NOASSERTION -LicenseInfoInFile: LGPL-2.1-or-later -FileCopyrightText: NOASSERTION -# Extracted Licenses \ No newline at end of file diff --git a/tests/data/doc_write/tv-simple.tv b/tests/data/doc_write/tv-simple.tv deleted file mode 100644 index 614a8d874..000000000 --- a/tests/data/doc_write/tv-simple.tv +++ /dev/null @@ -1,25 +0,0 @@ -# Document Information -SPDXVersion: SPDX-2.1 -DataLicense: CC0-1.0 -DocumentName: Sample_Document-V2.1 -SPDXID: SPDXRef-DOCUMENT -DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 -# Creation Info -# Package -PackageName: some/path -SPDXID: SPDXRef-Package -PackageDownloadLocation: NOASSERTION -PackageChecksum: SHA1: SOME-SHA1 -PackageVerificationCode: SOME code -PackageLicenseDeclared: NOASSERTION -PackageLicenseConcluded: NOASSERTION -PackageLicenseInfoFromFiles: LGPL-2.1-only -PackageCopyrightText: Some copyrught -# File -FileName: ./some/path/tofile -SPDXID: SPDXRef-File -FileChecksum: SHA1: SOME-SHA1 -LicenseConcluded: NOASSERTION -LicenseInfoInFile: LGPL-2.1-only -FileCopyrightText: NOASSERTION -# Extracted Licenses \ No newline at end of file diff --git a/tests/data/doc_write/xml-simple-plus.xml b/tests/data/doc_write/xml-simple-plus.xml deleted file mode 100644 index 16567e563..000000000 --- a/tests/data/doc_write/xml-simple-plus.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - SPDX-2.1 - CC0-1.0 - Sample_Document-V2.1 - SPDXRef-DOCUMENT - https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 - - - SPDXRef-Package - some/path - NOASSERTION - Some copyrught - - SOME code - - - SOME-SHA1 - checksumAlgorithm_sha1 - - NOASSERTION - NOASSERTION - - - ./some/path/tofile - SPDXRef-File - - SOME-SHA1 - checksumAlgorithm_sha1 - - NOASSERTION - NOASSERTION - LGPL-2.1-or-later - SOME-SHA1 - - - LGPL-2.1-or-later - SOME-SHA1 - - - - \ No newline at end of file diff --git a/tests/data/doc_write/xml-simple.xml b/tests/data/doc_write/xml-simple.xml deleted file mode 100644 index 80bd16617..000000000 --- a/tests/data/doc_write/xml-simple.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - SPDX-2.1 - CC0-1.0 - Sample_Document-V2.1 - SPDXRef-DOCUMENT - https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 - - - SPDXRef-Package - some/path - NOASSERTION - Some copyrught - - SOME code - - - SOME-SHA1 - checksumAlgorithm_sha1 - - NOASSERTION - NOASSERTION - - - ./some/path/tofile - SPDXRef-File - - SOME-SHA1 - checksumAlgorithm_sha1 - - NOASSERTION - NOASSERTION - LGPL-2.1-only - SOME-SHA1 - - - LGPL-2.1-only - SOME-SHA1 - - - - \ No newline at end of file diff --git a/tests/data/doc_write/yaml-simple-plus.yaml b/tests/data/doc_write/yaml-simple-plus.yaml deleted file mode 100644 index 41c9fdabe..000000000 --- a/tests/data/doc_write/yaml-simple-plus.yaml +++ /dev/null @@ -1,35 +0,0 @@ ---- -Document: - specVersion: "SPDX-2.1" - dataLicense: "CC0-1.0" - name: "Sample_Document-V2.1" - id: "SPDXRef-DOCUMENT" - namespace: "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" - documentDescribes: - - Package: - id: "SPDXRef-Package" - name: "some/path" - downloadLocation: "NOASSERTION" - copyrightText: "Some copyrught" - packageVerificationCode: - value: "SOME code" - checksums: - - algorithm: "checksumAlgorithm_sha1" - value: "SOME-SHA1" - licenseDeclared: "NOASSERTION" - licenseConcluded: "NOASSERTION" - files: - - File: - name: "./some/path/tofile" - id: "SPDXRef-File" - checksums: - - algorithm: "checksumAlgorithm_sha1" - value: "SOME-SHA1" - licenseConcluded: "NOASSERTION" - copyrightText: "NOASSERTION" - licenseInfoFromFiles: - - "LGPL-2.1-or-later" - sha1: "SOME-SHA1" - licenseInfoFromFiles: - - "LGPL-2.1-or-later" - sha1: "SOME-SHA1" diff --git a/tests/data/doc_write/yaml-simple.yaml b/tests/data/doc_write/yaml-simple.yaml deleted file mode 100644 index 5d9245f38..000000000 --- a/tests/data/doc_write/yaml-simple.yaml +++ /dev/null @@ -1,35 +0,0 @@ ---- -Document: - specVersion: "SPDX-2.1" - dataLicense: "CC0-1.0" - name: "Sample_Document-V2.1" - id: "SPDXRef-DOCUMENT" - namespace: "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" - documentDescribes: - - Package: - id: "SPDXRef-Package" - name: "some/path" - downloadLocation: "NOASSERTION" - copyrightText: "Some copyrught" - packageVerificationCode: - value: "SOME code" - checksums: - - algorithm: "checksumAlgorithm_sha1" - value: "SOME-SHA1" - licenseDeclared: "NOASSERTION" - licenseConcluded: "NOASSERTION" - files: - - File: - name: "./some/path/tofile" - id: "SPDXRef-File" - checksums: - - algorithm: "checksumAlgorithm_sha1" - value: "SOME-SHA1" - licenseConcluded: "NOASSERTION" - copyrightText: "NOASSERTION" - licenseInfoFromFiles: - - "LGPL-2.1-only" - sha1: "SOME-SHA1" - licenseInfoFromFiles: - - "LGPL-2.1-only" - sha1: "SOME-SHA1" diff --git a/tests/data/formats/SPDXJsonExample.json b/tests/data/formats/SPDXJsonExample.json deleted file mode 100644 index ff624d40a..000000000 --- a/tests/data/formats/SPDXJsonExample.json +++ /dev/null @@ -1,185 +0,0 @@ -{ - "Document": { - "comment": "This is a sample spreadsheet", - "name": "Sample_Document-V2.1", - "documentDescribes": [ - { - "Package": { - "id": "SPDXRef-Package", - "originator": "Organization: SPDX", - "files": [ - { - "File": { - "comment": "This file belongs to Jena", - "licenseInfoFromFiles": [ - "LicenseRef-1" - ], - "sha1": "3ab4e1c67a2d28fced849ee1bb76e7391b93f125", - "name": "Jenna-2.6.3/jena-2.6.3-sources.jar", - "copyrightText": "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP", - "artifactOf" : [ - { - "name" : "Jena", - "homePage" : "http://www.openjena.org/", - "projectUri" : "http://subversion.apache.org/doap.rdf" - } - ], - "licenseConcluded": "LicenseRef-1", - "licenseComments": "This license is used by Jena", - "checksums": [ - { - "value": "3ab4e1c67a2d28fced849ee1bb76e7391b93f125", - "algorithm": "checksumAlgorithm_sha1" - } - ], - "fileTypes": [ - "fileType_archive" - ], - "id": "SPDXRef-File1" - } - }, - { - "File": { - "licenseInfoFromFiles": [ - "Apache-2.0" - ], - "sha1": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "name": "src/org/spdx/parser/DOAPProject.java", - "copyrightText": "Copyright 2010, 2011 Source Auditor Inc.", - "licenseConcluded": "Apache-2.0", - "checksums": [ - { - "value": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "algorithm": "checksumAlgorithm_sha1" - } - ], - "fileTypes": [ - "fileType_source" - ], - "id": "SPDXRef-File2" - } - } - ], - "licenseInfoFromFiles": [ - "Apache-1.0", - "LicenseRef-3", - "MPL-1.1", - "LicenseRef-2", - "LicenseRef-4", - "Apache-2.0", - "LicenseRef-1" - ], - "sha1": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "name": "SPDX Translator", - "packageFileName": "spdxtranslator-1.0.zip", - "licenseComments": "The declared license information can be found in the NOTICE file at the root of the archive file", - "summary": "SPDX Translator utility", - "sourceInfo": "Version 1.0 of the SPDX Translator application", - "copyrightText": " Copyright 2010, 2011 Source Auditor Inc.", - "packageVerificationCode": { - "value": "4e3211c67a2d28fced849ee1bb76e7391b93feba", - "excludedFilesNames": [ - "SpdxTranslatorSpdx.rdf", - "SpdxTranslatorSpdx.txt" - ] - }, - "licenseConcluded": "(Apache-1.0 AND LicenseRef-2 AND MPL-1.1 AND LicenseRef-3 AND LicenseRef-4 AND Apache-2.0 AND LicenseRef-1)", - "supplier": "Organization: Linux Foundation", - "checksums": [ - { - "value": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "algorithm": "checksumAlgorithm_sha1" - } - ], - "versionInfo": "Version 0.9.2", - "licenseDeclared": "(LicenseRef-4 AND LicenseRef-3 AND Apache-2.0 AND LicenseRef-2 AND MPL-1.1 AND LicenseRef-1)", - "downloadLocation": "http://www.spdx.org/tools", - "description": "This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document." - } - } - ], - "creationInfo": { - "comment": "This is an example of an SPDX spreadsheet format", - "creators": [ - "Tool: SourceAuditor-V1.2", - "Person: Gary O'Neall", - "Organization: Source Auditor Inc." - ], - "licenseListVersion": "3.6", - "created": "2010-02-03T00:00:00Z" - }, - "externalDocumentRefs": [ - { - "checksum": { - "value": "d6a770ba38583ed4bb4525bd96e50461655d2759", - "algorithm": "checksumAlgorithm_sha1" - }, - "spdxDocumentNamespace": "https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301", - "externalDocumentId": "DocumentRef-spdx-tool-2.1" - } - ], - "namespace": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", - "annotations": [ - { - "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses", - "annotationType": "REVIEW", - "id": "SPDXRef-45", - "annotationDate": "2012-06-13T00:00:00Z", - "annotator": "Person: Jim Reviewer" - } - ], - "dataLicense": "CC0-1.0", - "reviewers": [ - { - "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses", - "reviewer": "Person: Joe Reviewer", - "reviewDate": "2010-02-10T00:00:00Z" - }, - { - "comment": "Another example reviewer.", - "reviewer": "Person: Suzanne Reviewer", - "reviewDate": "2011-03-13T00:00:00Z" - } - ], - "extractedLicenseInfos": [ - { - "extractedText": "This package includes the GRDDL parser developed by Hewlett Packard under the following license:\n\u00a9 Copyright 2007 Hewlett-Packard Development Company, LP\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: \n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \nThe name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ", - "licenseId": "LicenseRef-2" - }, - { - "extractedText": "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the\n distribution.\n\n3. The end-user documentation included with the redistribution,\n if any, must include the following acknowledgment: \n \"This product includes software developed by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software itself,\n if and wherever such third-party acknowledgments normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n or promote products derived from this software without prior \n written permission. For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", - "comment": "This is tye CyperNeko License", - "licenseId": "LicenseRef-3", - "name": "CyberNeko License", - "seeAlso": [ - "http://justasample.url.com", - "http://people.apache.org/~andyc/neko/LICENSE" - ] - }, - { - "extractedText": "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */ ", - "licenseId": "LicenseRef-4" - }, - { - "extractedText": "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */", - "licenseId": "LicenseRef-1" - } - ], - "specVersion": "SPDX-2.1", - "id": "SPDXRef-DOCUMENT", - "snippets": [ - { - "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later.", - "name": "from linux kernel", - "copyrightText": "Copyright 2008-2010 John Smith", - "licenseConcluded": "Apache-2.0", - "licenseInfoFromSnippet": [ - "Apache-2.0" - ], - "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz.", - "id": "SPDXRef-Snippet", - "fileId": "SPDXRef-DoapSource" - } - ] - } -} \ No newline at end of file diff --git a/tests/data/formats/SPDXRdfExample.rdf b/tests/data/formats/SPDXRdfExample.rdf deleted file mode 100644 index f954a0aa0..000000000 --- a/tests/data/formats/SPDXRdfExample.rdf +++ /dev/null @@ -1,299 +0,0 @@ - - - - - - from linux kernel - Copyright 2008-2010 John Smith - The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. - This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later. - - - - - Sample_Document-V2.1 - - - 2010-02-03T00:00:00Z - This is an example of an SPDX spreadsheet format - Tool: SourceAuditor-V1.2 - Organization: Source Auditor Inc. - Person: Gary O'Neall - - - SPDX-2.1 - - - DocumentRef-spdx-tool-2.1 - - - - d6a770ba38583ed4bb4525bd96e50461655d2759 - - - - - - - > - - - /* - * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - LicenseRef-1 - - - - - http://www.openjena.org/ - Jena - - - This license is used by Jena - Jenna-2.6.3/jena-2.6.3-sources.jar - - (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - - This file belongs to Jena - - - 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - - - - - - - - This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - 2010-02-10T00:00:00Z - Person: Joe Reviewer - - - - - - - Another example reviewer. - 2011-03-13T00:00:00Z - Person: Suzanne Reviewer - - - - - - This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - 2012-06-13T00:00:00Z - Person: Jim Reviewer - - - - - Copyright 2010, 2011 Source Auditor Inc. - - - - - - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - - - - src/org/spdx/parser/DOAPProject.java - - - - - - http://www.spdx.org/tools - false - Organization:Linux Foundation - - - - - 4e3211c67a2d28fced849ee1bb76e7391b93feba - SpdxTranslatorSpdx.txt - SpdxTranslatorSpdx.rdf - - - - - - - This package includes the GRDDL parser developed by Hewlett Packard under the following license: -© Copyright 2007 Hewlett-Packard Development Company, LP - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - LicenseRef-2 - - - - - - - - - /* - * (c) Copyright 2009 University of Bristol - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - LicenseRef-4 - - - - - http://justasample.url.com - http://people.apache.org/~andyc/neko/LICENSE - CyberNeko License - This is tye CyperNeko License - The CyberNeko Software License, Version 1.0 - - -(C) Copyright 2002-2005, Andy Clark. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -3. The end-user documentation included with the redistribution, - if any, must include the following acknowledgment: - "This product includes software developed by Andy Clark." - Alternately, this acknowledgment may appear in the software itself, - if and wherever such third-party acknowledgments normally appear. - -4. The names "CyberNeko" and "NekoHTML" must not be used to endorse - or promote products derived from this software without prior - written permission. For written permission, please contact - andyc@cyberneko.net. - -5. Products derived from this software may not be called "CyberNeko", - nor may "CyberNeko" appear in their name, without prior written - permission of the author. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - LicenseRef-3 - - - - - Version 1.0 of the SPDX Translator application - - - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - - - - spdxtranslator-1.0.zip - This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document. - - SPDX Translator - Version 0.9.2 - - - - Copyright 2010, 2011 Source Auditor Inc. - - - - - - - - - - - - Organization:SPDX - The declared license information can be found in the NOTICE file at the root of the archive file - SPDX Translator utility - - - - - - org.apache.commons:commons-lang:3.2.1 - NIST National Vulnerability Database (NVD) describes security vulnerabilities (CVEs) which affect Vendor Product Version acmecorp:acmenator:6.6.6 - - - - - This is a sample spreadsheet - - - - - diff --git a/tests/data/formats/SPDXSimpleTag.tag b/tests/data/formats/SPDXSimpleTag.tag deleted file mode 100644 index 72b2f0322..000000000 --- a/tests/data/formats/SPDXSimpleTag.tag +++ /dev/null @@ -1,63 +0,0 @@ -# Document info -SPDXVersion: SPDX-2.1 -DataLicense: CC0-1.0 -DocumentName: Sample_Document-V2.1 -SPDXID: SPDXRef-DOCUMENT -DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 -DocumentComment: Sample Comment -ExternalDocumentRef:DocumentRef-spdx-tool-2.1 https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759 - -# Creation info -Creator: Person: Bob (bob@example.com) -Creator: Organization: Acme -Created: 2014-02-03T00:00:00Z -CreatorComment: Sample Comment - -# Review #1 -Reviewer: Person: Bob the Reviewer -ReviewDate: 2014-02-10T00:00:00Z -ReviewComment: Bob was Here. - -# Review #2 -Reviewer: Person: Alice the Reviewer -ReviewDate: 2014-04-10T00:00:00Z -ReviewComment: Alice was also here. - - -# Package info -PackageName: Test -SPDXID: SPDXRef-Package -PackageVersion: Version 0.9.2 -PackageDownloadLocation: http://example.com/test -PackageSummary: Test package -PackageSourceInfo: Version 1.0 of test -PackageFileName: test-1.0.zip -PackageSupplier: Organization:ACME -PackageOriginator: Organization:ACME -PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 -PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt) -PackageDescription: A package. -PackageCopyrightText: Copyright 2010, 2011 Acme Inc. -PackageLicenseDeclared: Apache-2.0 -PackageLicenseConcluded: (LicenseRef-2.0 and Apache-2.0) -PackageLicenseInfoFromFiles: Apache-1.0 -PackageLicenseInfoFromFiles: Apache-2.0 -PackageLicenseComments: License Comments - -# File Info - -FileName: testfile.java -SPDXID: SPDXRef-File -FileType: SOURCE -FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 -LicenseConcluded: Apache-2.0 -LicenseInfoInFile: Apache-2.0 -FileCopyrightText: Copyright 2014 Acme Inc. -ArtifactOfProjectName: AcmeTest -ArtifactOfProjectHomePage: http://www.acme.org/ -ArtifactOfProjectURI: http://www.acme.org/ -FileComment: Very long file - - - - diff --git a/tests/data/formats/SPDXTagExample.tag b/tests/data/formats/SPDXTagExample.tag deleted file mode 100644 index 03260755e..000000000 --- a/tests/data/formats/SPDXTagExample.tag +++ /dev/null @@ -1,211 +0,0 @@ -SPDXVersion: SPDX-2.1 -DataLicense: CC0-1.0 -DocumentName: Sample_Document-V2.1 -SPDXID: SPDXRef-DOCUMENT -DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 -DocumentComment: This is a sample spreadsheet - -## Creation Information -Creator: Person: Gary O'Neall -Creator: Organization: Source Auditor Inc. -Creator: Tool: SourceAuditor-V1.2 -Created: 2010-02-03T00:00:00Z -CreatorComment: This is an example of an SPDX spreadsheet format - -## Review Information -Reviewer: Person: Joe Reviewer -ReviewDate: 2010-02-10T00:00:00Z -ReviewComment: This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - -Reviewer: Person: Suzanne Reviewer -ReviewDate: 2011-03-13T00:00:00Z -ReviewComment: Another example reviewer. - -## Annotation Information -Annotator: Person: Jim Annotator -AnnotationType: REVIEW -AnnotationDate: 2012-03-11T00:00:00Z -AnnotationComment: An example annotation comment. -SPDXREF: SPDXRef-45 - -## Package Information -PackageName: SPDX Translator -SPDXID: SPDXRef-Package -PackageVersion: Version 0.9.2 -PackageDownloadLocation: http://www.spdx.org/tools -PackageSummary: SPDX Translator utility -PackageSourceInfo: Version 1.0 of the SPDX Translator application -PackageFileName: spdxtranslator-1.0.zip -PackageSupplier: Organization:Linux Foundation -PackageOriginator: Organization:SPDX -PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 -PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (SpdxTranslatorSpdx.rdf, SpdxTranslatorSpdx.txt) -PackageDescription: This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document. -PackageComment: This package includes several sub-packages. - -PackageCopyrightText: Copyright 2010, 2011 Source Auditor Inc. - -PackageLicenseDeclared: (LicenseRef-3 AND LicenseRef-4 AND Apache-2.0 AND MPL-1.1 AND LicenseRef-1 AND LicenseRef-2) -PackageLicenseConcluded: (LicenseRef-3 AND LicenseRef-4 AND Apache-1.0 AND Apache-2.0 AND MPL-1.1 AND LicenseRef-1 AND LicenseRef-2) - -PackageLicenseInfoFromFiles: Apache-1.0 -PackageLicenseInfoFromFiles: LicenseRef-3 -PackageLicenseInfoFromFiles: Apache-2.0 -PackageLicenseInfoFromFiles: LicenseRef-4 -PackageLicenseInfoFromFiles: LicenseRef-2 -PackageLicenseInfoFromFiles: LicenseRef-1 -PackageLicenseInfoFromFiles: MPL-1.1 -PackageLicenseComments: The declared license information can be found in the NOTICE file at the root of the archive file - -ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*: -ExternalRefComment: NIST National Vulnerability Database (NVD) describes security vulnerabilities (CVEs) which affect Vendor Product Version acmecorp:acmenator:6.6.6. - -## File Information -FileName: src/org/spdx/parser/DOAPProject.java -SPDXID: SPDXRef-File1 -FileType: SOURCE -FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 -LicenseConcluded: Apache-2.0 -LicenseInfoInFile: Apache-2.0 -FileCopyrightText: Copyright 2010, 2011 Source Auditor Inc. - -FileName: Jenna-2.6.3/jena-2.6.3-sources.jar -SPDXID: SPDXRef-File2 -FileType: ARCHIVE -FileChecksum: SHA1: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 -LicenseConcluded: LicenseRef-1 -LicenseInfoInFile: LicenseRef-1 -LicenseComments: This license is used by Jena -FileCopyrightText: (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP -ArtifactOfProjectName: Jena -ArtifactOfProjectHomePage: http://www.openjena.org/ -ArtifactOfProjectURI: UNKNOWN -FileComment: This file belongs to Jena - -## Snippet Information -SnippetSPDXID: SPDXRef-Snippet -SnippetFromFileSPDXID: SPDXRef-DoapSource -SnippetLicenseComments: The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. -SnippetCopyrightText: Copyright 2008-2010 John Smith -SnippetComment: This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later. -SnippetName: from linux kernel -SnippetLicenseConcluded: Apache-2.0 -LicenseInfoInSnippet: Apache-2.0 - -## License Information -LicenseID: LicenseRef-3 -ExtractedText: The CyberNeko Software License, Version 1.0 - - -(C) Copyright 2002-2005, Andy Clark. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -3. The end-user documentation included with the redistribution, - if any, must include the following acknowledgment: - "This product includes software developed by Andy Clark." - Alternately, this acknowledgment may appear in the software itself, - if and wherever such third-party acknowledgments normally appear. - -4. The names "CyberNeko" and "NekoHTML" must not be used to endorse - or promote products derived from this software without prior - written permission. For written permission, please contact - andyc@cyberneko.net. - -5. Products derived from this software may not be called "CyberNeko", - nor may "CyberNeko" appear in their name, without prior written - permission of the author. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -LicenseName: CyberNeko License -LicenseCrossReference: http://people.apache.org/~andyc/neko/LICENSE -LicenseCrossReference: http://justasample.url.com -LicenseComment: This is tye CyperNeko License - -LicenseID: LicenseRef-1 -ExtractedText: /* - * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -LicenseID: LicenseRef-2 -ExtractedText: This package includes the GRDDL parser developed by Hewlett Packard under the following license: -© Copyright 2007 Hewlett-Packard Development Company, LP - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -LicenseID: LicenseRef-4 -ExtractedText: /* - * (c) Copyright 2009 University of Bristol - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - diff --git a/tests/data/formats/SPDXXmlExample.xml b/tests/data/formats/SPDXXmlExample.xml deleted file mode 100644 index f74859355..000000000 --- a/tests/data/formats/SPDXXmlExample.xml +++ /dev/null @@ -1,247 +0,0 @@ - - - - This is a sample spreadsheet - Sample_Document-V2.1 - - - SPDXRef-Package - Organization: SPDX - - - Apache-2.0 - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - src/org/spdx/parser/DOAPProject.java - Copyright 2010, 2011 Source Auditor Inc. - Apache-2.0 - - - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - checksumAlgorithm_sha1 - - fileType_source - SPDXRef-File2 - - - - - This file belongs to Jena - LicenseRef-1 - 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - Jenna-2.6.3/jena-2.6.3-sources.jar - (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - - Jena - http://www.openjena.org/ - http://subversion.apache.org/doap.rdf - - LicenseRef-1 - This license is used by Jena - - 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - checksumAlgorithm_sha1 - - fileType_archive - SPDXRef-File1 - - - LicenseRef-3 - LicenseRef-1 - Apache-1.0 - LicenseRef-4 - Apache-2.0 - LicenseRef-2 - MPL-1.1 - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - SPDX Translator - spdxtranslator-1.0.zip - The declared license information can be found in the NOTICE file at the root of the archive file - SPDX Translator utility - Version 1.0 of the SPDX Translator application - Copyright 2010, 2011 Source Auditor Inc. - - 4e3211c67a2d28fced849ee1bb76e7391b93feba - SpdxTranslatorSpdx.rdf - SpdxTranslatorSpdx.txt - - (LicenseRef-1 AND MPL-1.1 AND LicenseRef-2 AND LicenseRef-3 AND Apache-2.0 AND LicenseRef-4 AND Apache-1.0) - Organization: Linux Foundation - - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - checksumAlgorithm_sha1 - - Version 0.9.2 - (LicenseRef-3 AND LicenseRef-2 AND Apache-2.0 AND MPL-1.1 AND LicenseRef-1 AND LicenseRef-4) - http://www.spdx.org/tools - This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document. - - - - This is an example of an SPDX spreadsheet format - Tool: SourceAuditor-V1.2 - Person: Gary O'Neall - Organization: Source Auditor Inc. - 3.6 - 2010-02-03T00:00:00Z - - - - d6a770ba38583ed4bb4525bd96e50461655d2759 - checksumAlgorithm_sha1 - - https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 - DocumentRef-spdx-tool-2.1 - - https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 - - This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - REVIEW - SPDXRef-45 - 2012-06-13T00:00:00Z - Person: Jim Reviewer - - CC0-1.0 - - This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses - Person: Joe Reviewer - 2010-02-10T00:00:00Z - - - Another example reviewer. - Person: Suzanne Reviewer - 2011-03-13T00:00:00Z - - - /* - * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - LicenseRef-1 - - - This package includes the GRDDL parser developed by Hewlett Packard under the following license: -© Copyright 2007 Hewlett-Packard Development Company, LP - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - LicenseRef-2 - - - The CyberNeko Software License, Version 1.0 - - -(C) Copyright 2002-2005, Andy Clark. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -3. The end-user documentation included with the redistribution, - if any, must include the following acknowledgment: - "This product includes software developed by Andy Clark." - Alternately, this acknowledgment may appear in the software itself, - if and wherever such third-party acknowledgments normally appear. - -4. The names "CyberNeko" and "NekoHTML" must not be used to endorse - or promote products derived from this software without prior - written permission. For written permission, please contact - andyc@cyberneko.net. - -5. Products derived from this software may not be called "CyberNeko", - nor may "CyberNeko" appear in their name, without prior written - permission of the author. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - This is tye CyperNeko License - LicenseRef-3 - CyberNeko License - http://justasample.url.com - http://people.apache.org/~andyc/neko/LICENSE - - - /* - * (c) Copyright 2009 University of Bristol - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - LicenseRef-4 - - SPDX-2.1 - SPDXRef-DOCUMENT - - This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0-or-later. - from linux kernel - Copyright 2008-2010 John Smith - Apache-2.0 - Apache-2.0 - The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. - SPDXRef-Snippet - SPDXRef-DoapSource - - - \ No newline at end of file diff --git a/tests/data/formats/SPDXYamlExample.yaml b/tests/data/formats/SPDXYamlExample.yaml deleted file mode 100644 index afd6791f7..000000000 --- a/tests/data/formats/SPDXYamlExample.yaml +++ /dev/null @@ -1,221 +0,0 @@ ---- -Document: - annotations: - - annotationDate: '2012-06-13T00:00:00Z' - annotationType: REVIEW - annotator: 'Person: Jim Reviewer' - comment: This is just an example. Some of the non-standard licenses look like - they are actually BSD 3 clause licenses - id: SPDXRef-45 - comment: This is a sample spreadsheet - creationInfo: - comment: This is an example of an SPDX spreadsheet format - created: '2010-02-03T00:00:00Z' - creators: - - 'Tool: SourceAuditor-V1.2' - - 'Organization: Source Auditor Inc.' - - 'Person: Gary O''Neall' - licenseListVersion: '3.6' - dataLicense: CC0-1.0 - documentDescribes: - - Package: - id: SPDXRef-Package - checksums: - - algorithm: checksumAlgorithm_sha1 - value: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - copyrightText: ' Copyright 2010, 2011 Source Auditor Inc.' - description: This utility translates and SPDX RDF XML document to a spreadsheet, - translates a spreadsheet to an SPDX RDF XML document and translates an SPDX - RDFa document to an SPDX RDF XML document. - downloadLocation: http://www.spdx.org/tools - files: - - File: - checksums: - - algorithm: checksumAlgorithm_sha1 - value: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - comment: This file belongs to Jena - copyrightText: (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009 Hewlett-Packard Development Company, LP - artifactOf: - - name: "Jena" - homePage: "http://www.openjena.org/" - projectUri: "http://subversion.apache.org/doap.rdf" - fileTypes: - - fileType_archive - id: SPDXRef-File1 - licenseComments: This license is used by Jena - licenseConcluded: LicenseRef-1 - licenseInfoFromFiles: - - LicenseRef-1 - name: Jenna-2.6.3/jena-2.6.3-sources.jar - sha1: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 - - File: - checksums: - - algorithm: checksumAlgorithm_sha1 - value: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - copyrightText: Copyright 2010, 2011 Source Auditor Inc. - fileTypes: - - fileType_source - id: SPDXRef-File2 - licenseConcluded: Apache-2.0 - licenseInfoFromFiles: - - Apache-2.0 - name: src/org/spdx/parser/DOAPProject.java - sha1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - licenseComments: The declared license information can be found in the NOTICE - file at the root of the archive file - licenseConcluded: (LicenseRef-3 AND LicenseRef-1 AND MPL-1.1 AND Apache-2.0 - AND LicenseRef-2 AND Apache-1.0 AND LicenseRef-4) - licenseDeclared: (MPL-1.1 AND LicenseRef-4 AND LicenseRef-2 AND LicenseRef-1 - AND Apache-2.0 AND LicenseRef-3) - licenseInfoFromFiles: - - Apache-2.0 - - MPL-1.1 - - LicenseRef-3 - - LicenseRef-1 - - LicenseRef-4 - - Apache-1.0 - - LicenseRef-2 - name: SPDX Translator - originator: 'Organization: SPDX' - packageFileName: spdxtranslator-1.0.zip - packageVerificationCode: - excludedFilesNames: - - SpdxTranslatorSpdx.txt - - SpdxTranslatorSpdx.rdf - value: 4e3211c67a2d28fced849ee1bb76e7391b93feba - sha1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - sourceInfo: Version 1.0 of the SPDX Translator application - summary: SPDX Translator utility - supplier: 'Organization: Linux Foundation' - versionInfo: Version 0.9.2 - externalDocumentRefs: - - checksum: - algorithm: checksumAlgorithm_sha1 - value: d6a770ba38583ed4bb4525bd96e50461655d2759 - externalDocumentId: DocumentRef-spdx-tool-2.1 - spdxDocumentNamespace: https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 - extractedLicenseInfos: - - comment: This is tye CyperNeko License - extractedText: "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright\ - \ 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in\ - \ source and binary forms, with or without\nmodification, are permitted provided\ - \ that the following conditions\nare met:\n\n1. Redistributions of source code\ - \ must retain the above copyright\n notice, this list of conditions and the\ - \ following disclaimer. \n\n2. Redistributions in binary form must reproduce\ - \ the above copyright\n notice, this list of conditions and the following\ - \ disclaimer in\n the documentation and/or other materials provided with the\n\ - \ distribution.\n\n3. The end-user documentation included with the redistribution,\n\ - \ if any, must include the following acknowledgment: \n \"This product\ - \ includes software developed by Andy Clark.\"\n Alternately, this acknowledgment\ - \ may appear in the software itself,\n if and wherever such third-party acknowledgments\ - \ normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be\ - \ used to endorse\n or promote products derived from this software without\ - \ prior \n written permission. For written permission, please contact \n \ - \ andyc@cyberneko.net.\n\n5. Products derived from this software may not be\ - \ called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without\ - \ prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS\ - \ IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED\ - \ TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\ - \ PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\n\ - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL\ - \ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS\ - \ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER\ - \ CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY,\ - \ OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ - \ USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." - licenseId: LicenseRef-3 - name: CyberNeko License - seeAlso: - - http://justasample.url.com - - http://people.apache.org/~andyc/neko/LICENSE - - extractedText: "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006,\ - \ 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n\ - \ *\n * Redistribution and use in source and binary forms, with or without\n\ - \ * modification, are permitted provided that the following conditions\n * are\ - \ met:\n * 1. Redistributions of source code must retain the above copyright\n\ - \ * notice, this list of conditions and the following disclaimer.\n * 2.\ - \ Redistributions in binary form must reproduce the above copyright\n * notice,\ - \ this list of conditions and the following disclaimer in the\n * documentation\ - \ and/or other materials provided with the distribution.\n * 3. The name of\ - \ the author may not be used to endorse or promote products\n * derived from\ - \ this software without specific prior written permission.\n *\n * THIS SOFTWARE\ - \ IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES,\ - \ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY\ - \ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL\ - \ THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY,\ - \ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF\ - \ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS\ - \ INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN\ - \ CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE)\ - \ ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF\ - \ THE POSSIBILITY OF SUCH DAMAGE.\n */" - licenseId: LicenseRef-1 - - extractedText: "This package includes the GRDDL parser developed by Hewlett Packard\ - \ under the following license:\n\xA9 Copyright 2007 Hewlett-Packard Development\ - \ Company, LP\n\nRedistribution and use in source and binary forms, with or\ - \ without modification, are permitted provided that the following conditions\ - \ are met: \n\nRedistributions of source code must retain the above copyright\ - \ notice, this list of conditions and the following disclaimer. \nRedistributions\ - \ in binary form must reproduce the above copyright notice, this list of conditions\ - \ and the following disclaimer in the documentation and/or other materials provided\ - \ with the distribution. \nThe name of the author may not be used to endorse\ - \ or promote products derived from this software without specific prior written\ - \ permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS\ - \ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\ - \ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN\ - \ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\ - \ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\ - \ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\ - \ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\ - \ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\ - \ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\ - \ POSSIBILITY OF SUCH DAMAGE. " - licenseId: LicenseRef-2 - - extractedText: "/*\n * (c) Copyright 2009 University of Bristol\n * All rights\ - \ reserved.\n *\n * Redistribution and use in source and binary forms, with\ - \ or without\n * modification, are permitted provided that the following conditions\n\ - \ * are met:\n * 1. Redistributions of source code must retain the above copyright\n\ - \ * notice, this list of conditions and the following disclaimer.\n * 2.\ - \ Redistributions in binary form must reproduce the above copyright\n * notice,\ - \ this list of conditions and the following disclaimer in the\n * documentation\ - \ and/or other materials provided with the distribution.\n * 3. The name of\ - \ the author may not be used to endorse or promote products\n * derived from\ - \ this software without specific prior written permission.\n *\n * THIS SOFTWARE\ - \ IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES,\ - \ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY\ - \ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL\ - \ THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY,\ - \ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF\ - \ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS\ - \ INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN\ - \ CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE)\ - \ ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF\ - \ THE POSSIBILITY OF SUCH DAMAGE.\n */ " - licenseId: LicenseRef-4 - id: SPDXRef-DOCUMENT - name: Sample_Document-V2.1 - namespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 - reviewers: - - comment: Another example reviewer. - reviewDate: '2011-03-13T00:00:00Z' - reviewer: 'Person: Suzanne Reviewer' - - comment: This is just an example. Some of the non-standard licenses look like - they are actually BSD 3 clause licenses - reviewDate: '2010-02-10T00:00:00Z' - reviewer: 'Person: Joe Reviewer' - snippets: - - comment: This snippet was identified as significant and highlighted in this Apache-2.0 - file, when a commercial scanner identified it as being derived from file foo.c - in package xyz which is licensed under GPL-2.0-or-later. - copyrightText: Copyright 2008-2010 John Smith - fileId: SPDXRef-DoapSource - id: SPDXRef-Snippet - licenseComments: The concluded license was taken from package xyz, from which - the snippet was copied into the current file. The concluded license information - was found in the COPYING.txt file in package xyz. - licenseConcluded: Apache-2.0 - licenseInfoFromSnippet: - - Apache-2.0 - name: from linux kernel - specVersion: SPDX-2.1 diff --git a/tests/spdx/__init__.py b/tests/spdx/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/data/SPDXJSONExample-UTF-16.spdx.json b/tests/spdx/data/SPDXJSONExample-UTF-16.spdx.json new file mode 100644 index 000000000..570d67d3e Binary files /dev/null and b/tests/spdx/data/SPDXJSONExample-UTF-16.spdx.json differ diff --git a/tests/spdx/data/SPDXJSONExample-v2.2.spdx.json b/tests/spdx/data/SPDXJSONExample-v2.2.spdx.json new file mode 100644 index 000000000..89171a143 --- /dev/null +++ b/tests/spdx/data/SPDXJSONExample-v2.2.spdx.json @@ -0,0 +1,284 @@ +{ + "SPDXID" : "SPDXRef-DOCUMENT", + "spdxVersion" : "SPDX-2.2", + "creationInfo" : { + "comment" : "This package has been shipped in source and binary form.\nThe binaries were created with gcc 4.5.1 and expect to link to\ncompatible system run time libraries.", + "created" : "2010-01-29T18:30:22Z", + "creators" : [ "Tool: LicenseFind-1.0", "Organization: ExampleCodeInspect ()", "Person: Jane Doe ()" ], + "licenseListVersion" : "3.9" + }, + "name" : "SPDX-Tools-v2.0", + "dataLicense" : "CC0-1.0", + "comment" : "This document was created using SPDX 2.0 using licenses from the web site.", + "externalDocumentRefs" : [ { + "externalDocumentId" : "DocumentRef-spdx-tool-1.2", + "checksum" : { + "algorithm" : "SHA1", + "checksumValue" : "d6a770ba38583ed4bb4525bd96e50461655d2759" + }, + "spdxDocument" : "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301" + } ], + "hasExtractedLicensingInfos" : [ { + "licenseId" : "LicenseRef-1", + "extractedText" : "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/" + }, { + "licenseId" : "LicenseRef-2", + "extractedText" : "This package includes the GRDDL parser developed by Hewlett Packard under the following license:\n� Copyright 2007 Hewlett-Packard Development Company, LP\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: \n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \nThe name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + }, { + "licenseId" : "LicenseRef-4", + "extractedText" : "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/" + }, { + "licenseId" : "LicenseRef-Beerware-4.2", + "comment" : "The beerware license has a couple of other standard variants.", + "extractedText" : "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "name" : "Beer-Ware License (Version 42)", + "seeAlsos" : [ "http://people.freebsd.org/~phk/" ] + }, { + "licenseId" : "LicenseRef-3", + "comment" : "This is tye CyperNeko License", + "extractedText" : "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the\n distribution.\n\n3. The end-user documentation included with the redistribution,\n if any, must include the following acknowledgment: \n \"This product includes software developed by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software itself,\n if and wherever such third-party acknowledgments normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n or promote products derived from this software without prior \n written permission. For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", + "name" : "CyberNeko License", + "seeAlsos" : [ "http://people.apache.org/~andyc/neko/LICENSE", "http://justasample.url.com" ] + } ], + "annotations" : [ { + "annotationDate" : "2010-01-29T18:30:22Z", + "annotationType" : "OTHER", + "annotator" : "Person: Jane Doe ()", + "comment" : "Document level annotation" + }, { + "annotationDate" : "2010-02-10T00:00:00Z", + "annotationType" : "REVIEW", + "annotator" : "Person: Joe Reviewer", + "comment" : "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses" + }, { + "annotationDate" : "2011-03-13T00:00:00Z", + "annotationType" : "REVIEW", + "annotator" : "Person: Suzanne Reviewer", + "comment" : "Another example reviewer." + } ], + "documentNamespace" : "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", + "documentDescribes" : [ "SPDXRef-File", "SPDXRef-Package" ], + "packages" : [ { + "SPDXID" : "SPDXRef-Package", + "annotations" : [ { + "annotationDate" : "2011-01-29T18:30:22Z", + "annotationType" : "OTHER", + "annotator" : "Person: Package Commenter", + "comment" : "Package level annotation" + } ], + "attributionTexts" : [ "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually." ], + "checksums" : [ { + "algorithm" : "MD5", + "checksumValue" : "624c1abb3664f4b35547e7c73864ad24" + }, { + "algorithm" : "SHA1", + "checksumValue" : "85ed0817af83a24ad8da68c2b5094de69833983c" + }, { + "algorithm" : "SHA256", + "checksumValue" : "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd" + } ], + "copyrightText" : "Copyright 2008-2010 John Smith", + "description" : "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems.", + "downloadLocation" : "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "externalRefs" : [ { + "referenceCategory" : "SECURITY", + "referenceLocator" : "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*", + "referenceType" : "cpe23Type" + }, { + "comment" : "This is the external ref for Acme", + "referenceCategory" : "OTHER", + "referenceLocator" : "acmecorp/acmenator/4.1.3-alpha", + "referenceType" : "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge" + } ], + "filesAnalyzed" : true, + "hasFiles" : [ "SPDXRef-CommonsLangSrc", "SPDXRef-JenaLib", "SPDXRef-DoapSource" ], + "homepage" : "http://ftp.gnu.org/gnu/glibc", + "licenseComments" : "The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change.", + "licenseConcluded" : "(LGPL-2.0-only OR LicenseRef-3)", + "licenseDeclared" : "(LGPL-2.0-only AND LicenseRef-3)", + "licenseInfoFromFiles" : [ "GPL-2.0-only", "LicenseRef-2", "LicenseRef-1" ], + "name" : "glibc", + "originator" : "Organization: ExampleCodeInspect (contact@example.com)", + "packageFileName" : "glibc-2.11.1.tar.gz", + "packageVerificationCode" : { + "packageVerificationCodeExcludedFiles" : [ "./package.spdx" ], + "packageVerificationCodeValue" : "d6a770ba38583ed4bb4525bd96e50461655d2758" + }, + "sourceInfo" : "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git.", + "summary" : "GNU C library.", + "supplier" : "Person: Jane Doe (jane.doe@example.com)", + "versionInfo" : "2.11.1" + }, { + "SPDXID" : "SPDXRef-fromDoap-1", + "copyrightText" : "NOASSERTION", + "downloadLocation" : "NOASSERTION", + "filesAnalyzed" : false, + "homepage" : "http://commons.apache.org/proper/commons-lang/", + "licenseConcluded" : "NOASSERTION", + "licenseDeclared" : "NOASSERTION", + "name" : "Apache Commons Lang" + }, { + "SPDXID" : "SPDXRef-fromDoap-0", + "copyrightText" : "NOASSERTION", + "downloadLocation" : "https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz", + "externalRefs" : [ { + "referenceCategory" : "PACKAGE_MANAGER", + "referenceLocator" : "pkg:maven/org.apache.jena/apache-jena@3.12.0", + "referenceType" : "purl" + } ], + "filesAnalyzed" : false, + "homepage" : "http://www.openjena.org/", + "licenseConcluded" : "NOASSERTION", + "licenseDeclared" : "NOASSERTION", + "name" : "Jena", + "versionInfo" : "3.12.0" + }, { + "SPDXID" : "SPDXRef-Saxon", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "85ed0817af83a24ad8da68c2b5094de69833983c" + } ], + "copyrightText" : "Copyright Saxonica Ltd", + "description" : "The Saxon package is a collection of tools for processing XML documents.", + "downloadLocation" : "https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download", + "filesAnalyzed" : false, + "homepage" : "http://saxon.sourceforge.net/", + "licenseComments" : "Other versions available for a commercial license", + "licenseConcluded" : "MPL-1.0", + "licenseDeclared" : "MPL-1.0", + "name" : "Saxon", + "packageFileName" : "saxonB-8.8.zip", + "versionInfo" : "8.8" + } ], + "files" : [ { + "SPDXID" : "SPDXRef-DoapSource", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" + } ], + "copyrightText" : "Copyright 2010, 2011 Source Auditor Inc.", + "fileContributors" : [ "Protecode Inc.", "SPDX Technical Team Members", "Open Logic Inc.", "Source Auditor Inc.", "Black Duck Software In.c" ], + "fileName" : "./src/org/spdx/parser/DOAPProject.java", + "fileTypes" : [ "SOURCE" ], + "licenseConcluded" : "Apache-2.0", + "licenseInfoInFiles" : [ "Apache-2.0" ] + }, { + "SPDXID" : "SPDXRef-CommonsLangSrc", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "c2b4e1c67a2d28fced849ee1bb76e7391b93f125" + } ], + "comment" : "This file is used by Jena", + "copyrightText" : "Copyright 2001-2011 The Apache Software Foundation", + "fileContributors" : [ "Apache Software Foundation" ], + "fileName" : "./lib-source/commons-lang3-3.1-sources.jar", + "fileTypes" : [ "ARCHIVE" ], + "licenseConcluded" : "Apache-2.0", + "licenseInfoInFiles" : [ "Apache-2.0" ], + "noticeText" : "Apache Commons Lang\nCopyright 2001-2011 The Apache Software Foundation\n\nThis product includes software developed by\nThe Apache Software Foundation (http://www.apache.org/).\n\nThis product includes software from the Spring Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())" + }, { + "SPDXID" : "SPDXRef-JenaLib", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" + } ], + "comment" : "This file belongs to Jena", + "copyrightText" : "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP", + "fileContributors" : [ "Apache Software Foundation", "Hewlett Packard Inc." ], + "fileName" : "./lib-source/jena-2.6.3-sources.jar", + "fileTypes" : [ "ARCHIVE" ], + "licenseComments" : "This license is used by Jena", + "licenseConcluded" : "LicenseRef-1", + "licenseInfoInFiles" : [ "LicenseRef-1" ] + }, { + "SPDXID" : "SPDXRef-File", + "annotations" : [ { + "annotationDate" : "2011-01-29T18:30:22Z", + "annotationType" : "OTHER", + "annotator" : "Person: File Commenter", + "comment" : "File level annotation" + } ], + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "d6a770ba38583ed4bb4525bd96e50461655d2758" + }, { + "algorithm" : "MD5", + "checksumValue" : "624c1abb3664f4b35547e7c73864ad24" + } ], + "comment" : "The concluded license was taken from the package level that the file was included in.\nThis information was found in the COPYING.txt file in the xyz directory.", + "copyrightText" : "Copyright 2008-2010 John Smith", + "fileContributors" : [ "The Regents of the University of California", "Modified by Paul Mundt lethal@linux-sh.org", "IBM Corporation" ], + "fileName" : "./package/foo.c", + "fileTypes" : [ "SOURCE" ], + "licenseComments" : "The concluded license was taken from the package level that the file was included in.", + "licenseConcluded" : "(LGPL-2.0-only OR LicenseRef-2)", + "licenseInfoInFiles" : [ "GPL-2.0-only", "LicenseRef-2" ], + "noticeText" : "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the �Software�), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: \nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED �AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + } ], + "snippets" : [ { + "SPDXID" : "SPDXRef-Snippet", + "comment" : "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0.", + "copyrightText" : "Copyright 2008-2010 John Smith", + "licenseComments" : "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz.", + "licenseConcluded" : "GPL-2.0-only", + "licenseInfoInSnippets" : [ "GPL-2.0-only" ], + "name" : "from linux kernel", + "ranges" : [ { + "endPointer" : { + "offset" : 420, + "reference" : "SPDXRef-DoapSource" + }, + "startPointer" : { + "offset" : 310, + "reference" : "SPDXRef-DoapSource" + } + }, { + "endPointer" : { + "lineNumber" : 23, + "reference" : "SPDXRef-DoapSource" + }, + "startPointer" : { + "lineNumber" : 5, + "reference" : "SPDXRef-DoapSource" + } + } ], + "snippetFromFile" : "SPDXRef-DoapSource" + } ], + "relationships" : [ { + "spdxElementId" : "SPDXRef-DOCUMENT", + "relatedSpdxElement" : "SPDXRef-Package", + "relationshipType" : "CONTAINS" + }, { + "spdxElementId" : "SPDXRef-DOCUMENT", + "relatedSpdxElement" : "DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement", + "relationshipType" : "COPY_OF" + }, { + "spdxElementId" : "SPDXRef-DOCUMENT", + "relatedSpdxElement" : "SPDXRef-File", + "relationshipType" : "DESCRIBES" + }, { + "spdxElementId" : "SPDXRef-DOCUMENT", + "relatedSpdxElement" : "SPDXRef-Package", + "relationshipType" : "DESCRIBES" + }, { + "spdxElementId" : "SPDXRef-Package", + "relatedSpdxElement" : "SPDXRef-JenaLib", + "relationshipType" : "CONTAINS" + }, { + "spdxElementId" : "SPDXRef-Package", + "relatedSpdxElement" : "SPDXRef-Saxon", + "relationshipType" : "DYNAMIC_LINK" + }, { + "spdxElementId" : "SPDXRef-CommonsLangSrc", + "relatedSpdxElement" : "NOASSERTION", + "relationshipType" : "GENERATED_FROM" + }, { + "spdxElementId" : "SPDXRef-JenaLib", + "relatedSpdxElement" : "SPDXRef-Package", + "relationshipType" : "CONTAINS" + }, { + "spdxElementId" : "SPDXRef-File", + "relatedSpdxElement" : "SPDXRef-fromDoap-0", + "relationshipType" : "GENERATED_FROM" + } ] +} diff --git a/tests/spdx/data/SPDXJSONExample-v2.3.spdx.json b/tests/spdx/data/SPDXJSONExample-v2.3.spdx.json new file mode 100644 index 000000000..d4ee447de --- /dev/null +++ b/tests/spdx/data/SPDXJSONExample-v2.3.spdx.json @@ -0,0 +1,289 @@ +{ + "SPDXID" : "SPDXRef-DOCUMENT", + "spdxVersion" : "SPDX-2.3", + "creationInfo" : { + "comment" : "This package has been shipped in source and binary form.\nThe binaries were created with gcc 4.5.1 and expect to link to\ncompatible system run time libraries.", + "created" : "2010-01-29T18:30:22Z", + "creators" : [ "Tool: LicenseFind-1.0", "Organization: ExampleCodeInspect ()", "Person: Jane Doe ()" ], + "licenseListVersion" : "3.17" + }, + "name" : "SPDX-Tools-v2.0", + "dataLicense" : "CC0-1.0", + "comment" : "This document was created using SPDX 2.0 using licenses from the web site.", + "externalDocumentRefs" : [ { + "externalDocumentId" : "DocumentRef-spdx-tool-1.2", + "checksum" : { + "algorithm" : "SHA1", + "checksumValue" : "d6a770ba38583ed4bb4525bd96e50461655d2759" + }, + "spdxDocument" : "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301" + } ], + "hasExtractedLicensingInfos" : [ { + "licenseId" : "LicenseRef-1", + "extractedText" : "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/" + }, { + "licenseId" : "LicenseRef-2", + "extractedText" : "This package includes the GRDDL parser developed by Hewlett Packard under the following license:\n© Copyright 2007 Hewlett-Packard Development Company, LP\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: \n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \nThe name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + }, { + "licenseId" : "LicenseRef-4", + "extractedText" : "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/" + }, { + "licenseId" : "LicenseRef-Beerware-4.2", + "comment" : "The beerware license has a couple of other standard variants.", + "extractedText" : "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "name" : "Beer-Ware License (Version 42)", + "seeAlsos" : [ "http://people.freebsd.org/~phk/" ] + }, { + "licenseId" : "LicenseRef-3", + "comment" : "This is tye CyperNeko License", + "extractedText" : "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the\n distribution.\n\n3. The end-user documentation included with the redistribution,\n if any, must include the following acknowledgment: \n \"This product includes software developed by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software itself,\n if and wherever such third-party acknowledgments normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n or promote products derived from this software without prior \n written permission. For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", + "name" : "CyberNeko License", + "seeAlsos" : [ "http://people.apache.org/~andyc/neko/LICENSE", "http://justasample.url.com" ] + } ], + "annotations" : [ { + "annotationDate" : "2010-01-29T18:30:22Z", + "annotationType" : "OTHER", + "annotator" : "Person: Jane Doe ()", + "comment" : "Document level annotation" + }, { + "annotationDate" : "2010-02-10T00:00:00Z", + "annotationType" : "REVIEW", + "annotator" : "Person: Joe Reviewer", + "comment" : "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses" + }, { + "annotationDate" : "2011-03-13T00:00:00Z", + "annotationType" : "REVIEW", + "annotator" : "Person: Suzanne Reviewer", + "comment" : "Another example reviewer." + } ], + "documentDescribes" : [ "SPDXRef-File", "SPDXRef-Package" ], + "documentNamespace" : "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", + "packages" : [ { + "SPDXID" : "SPDXRef-Package", + "annotations" : [ { + "annotationDate" : "2011-01-29T18:30:22Z", + "annotationType" : "OTHER", + "annotator" : "Person: Package Commenter", + "comment" : "Package level annotation" + } ], + "attributionTexts" : [ "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually." ], + "builtDate" : "2011-01-29T18:30:22Z", + "checksums" : [ { + "algorithm" : "MD5", + "checksumValue" : "624c1abb3664f4b35547e7c73864ad24" + }, { + "algorithm" : "SHA1", + "checksumValue" : "85ed0817af83a24ad8da68c2b5094de69833983c" + }, { + "algorithm" : "SHA256", + "checksumValue" : "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd" + }, { + "algorithm" : "BLAKE2b-384", + "checksumValue" : "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706" + } ], + "copyrightText" : "Copyright 2008-2010 John Smith", + "description" : "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems.", + "downloadLocation" : "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "externalRefs" : [ { + "referenceCategory" : "SECURITY", + "referenceLocator" : "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*", + "referenceType" : "cpe23Type" + }, { + "comment" : "This is the external ref for Acme", + "referenceCategory" : "OTHER", + "referenceLocator" : "acmecorp/acmenator/4.1.3-alpha", + "referenceType" : "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge" + } ], + "filesAnalyzed" : true, + "homepage" : "http://ftp.gnu.org/gnu/glibc", + "licenseComments" : "The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change.", + "licenseConcluded" : "(LGPL-2.0-only OR LicenseRef-3)", + "licenseDeclared" : "(LGPL-2.0-only AND LicenseRef-3)", + "licenseInfoFromFiles" : [ "GPL-2.0-only", "LicenseRef-2", "LicenseRef-1" ], + "name" : "glibc", + "originator" : "Organization: ExampleCodeInspect (contact@example.com)", + "packageFileName" : "glibc-2.11.1.tar.gz", + "packageVerificationCode" : { + "packageVerificationCodeExcludedFiles" : [ "./package.spdx" ], + "packageVerificationCodeValue" : "d6a770ba38583ed4bb4525bd96e50461655d2758" + }, + "primaryPackagePurpose" : "SOURCE", + "hasFiles" : [ "SPDXRef-Specification", "SPDXRef-Specification", "SPDXRef-CommonsLangSrc", "SPDXRef-Specification", "SPDXRef-CommonsLangSrc", "SPDXRef-JenaLib", "SPDXRef-Specification", "SPDXRef-CommonsLangSrc", "SPDXRef-JenaLib", "SPDXRef-DoapSource", "SPDXRef-Specification", "SPDXRef-CommonsLangSrc", "SPDXRef-JenaLib", "SPDXRef-DoapSource" ], + "releaseDate" : "2012-01-29T18:30:22Z", + "sourceInfo" : "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git.", + "summary" : "GNU C library.", + "supplier" : "Person: Jane Doe (jane.doe@example.com)", + "validUntilDate" : "2014-01-29T18:30:22Z", + "versionInfo" : "2.11.1" + }, { + "SPDXID" : "SPDXRef-fromDoap-1", + "copyrightText" : "NOASSERTION", + "downloadLocation" : "NOASSERTION", + "filesAnalyzed" : false, + "homepage" : "http://commons.apache.org/proper/commons-lang/", + "licenseConcluded" : "NOASSERTION", + "licenseDeclared" : "NOASSERTION", + "name" : "Apache Commons Lang" + }, { + "SPDXID" : "SPDXRef-fromDoap-0", + "downloadLocation" : "https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz", + "externalRefs" : [ { + "referenceCategory" : "PACKAGE-MANAGER", + "referenceLocator" : "pkg:maven/org.apache.jena/apache-jena@3.12.0", + "referenceType" : "purl" + } ], + "filesAnalyzed" : false, + "homepage" : "http://www.openjena.org/", + "name" : "Jena", + "versionInfo" : "3.12.0" + }, { + "SPDXID" : "SPDXRef-Saxon", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "85ed0817af83a24ad8da68c2b5094de69833983c" + } ], + "copyrightText" : "Copyright Saxonica Ltd", + "description" : "The Saxon package is a collection of tools for processing XML documents.", + "downloadLocation" : "https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download", + "filesAnalyzed" : false, + "homepage" : "http://saxon.sourceforge.net/", + "licenseComments" : "Other versions available for a commercial license", + "licenseConcluded" : "MPL-1.0", + "licenseDeclared" : "MPL-1.0", + "name" : "Saxon", + "packageFileName" : "saxonB-8.8.zip", + "versionInfo" : "8.8" + } ], + "files" : [ { + "SPDXID" : "SPDXRef-DoapSource", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" + } ], + "copyrightText" : "Copyright 2010, 2011 Source Auditor Inc.", + "fileContributors" : [ "Protecode Inc.", "SPDX Technical Team Members", "Open Logic Inc.", "Source Auditor Inc.", "Black Duck Software In.c" ], + "fileName" : "./src/org/spdx/parser/DOAPProject.java", + "fileTypes" : [ "SOURCE" ], + "licenseConcluded" : "Apache-2.0", + "licenseInfoInFiles" : [ "Apache-2.0" ] + }, { + "SPDXID" : "SPDXRef-CommonsLangSrc", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "c2b4e1c67a2d28fced849ee1bb76e7391b93f125" + } ], + "comment" : "This file is used by Jena", + "copyrightText" : "Copyright 2001-2011 The Apache Software Foundation", + "fileContributors" : [ "Apache Software Foundation" ], + "fileName" : "./lib-source/commons-lang3-3.1-sources.jar", + "fileTypes" : [ "ARCHIVE" ], + "licenseConcluded" : "Apache-2.0", + "licenseInfoInFiles" : [ "Apache-2.0" ], + "noticeText" : "Apache Commons Lang\nCopyright 2001-2011 The Apache Software Foundation\n\nThis product includes software developed by\nThe Apache Software Foundation (http://www.apache.org/).\n\nThis product includes software from the Spring Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())" + }, { + "SPDXID" : "SPDXRef-JenaLib", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" + } ], + "comment" : "This file belongs to Jena", + "copyrightText" : "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP", + "fileContributors" : [ "Apache Software Foundation", "Hewlett Packard Inc." ], + "fileName" : "./lib-source/jena-2.6.3-sources.jar", + "fileTypes" : [ "ARCHIVE" ], + "licenseComments" : "This license is used by Jena", + "licenseConcluded" : "LicenseRef-1", + "licenseInfoInFiles" : [ "LicenseRef-1" ] + }, { + "SPDXID" : "SPDXRef-Specification", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "fff4e1c67a2d28fced849ee1bb76e7391b93f125" + } ], + "comment" : "Specification Documentation", + "fileName" : "./docs/myspec.pdf", + "fileTypes" : [ "DOCUMENTATION" ] + }, { + "SPDXID" : "SPDXRef-File", + "annotations" : [ { + "annotationDate" : "2011-01-29T18:30:22Z", + "annotationType" : "OTHER", + "annotator" : "Person: File Commenter", + "comment" : "File level annotation" + } ], + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "d6a770ba38583ed4bb4525bd96e50461655d2758" + }, { + "algorithm" : "MD5", + "checksumValue" : "624c1abb3664f4b35547e7c73864ad24" + } ], + "comment" : "The concluded license was taken from the package level that the file was included in.\nThis information was found in the COPYING.txt file in the xyz directory.", + "copyrightText" : "Copyright 2008-2010 John Smith", + "fileContributors" : [ "The Regents of the University of California", "Modified by Paul Mundt lethal@linux-sh.org", "IBM Corporation" ], + "fileName" : "./package/foo.c", + "fileTypes" : [ "SOURCE" ], + "licenseComments" : "The concluded license was taken from the package level that the file was included in.", + "licenseConcluded" : "(LGPL-2.0-only OR LicenseRef-2)", + "licenseInfoInFiles" : [ "GPL-2.0-only", "LicenseRef-2" ], + "noticeText" : "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: \nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + } ], + "snippets" : [ { + "SPDXID" : "SPDXRef-Snippet", + "comment" : "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0.", + "copyrightText" : "Copyright 2008-2010 John Smith", + "licenseComments" : "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz.", + "licenseConcluded" : "GPL-2.0-only", + "licenseInfoInSnippets" : [ "GPL-2.0-only" ], + "name" : "from linux kernel", + "ranges" : [ { + "endPointer" : { + "offset" : 420, + "reference" : "SPDXRef-DoapSource" + }, + "startPointer" : { + "offset" : 310, + "reference" : "SPDXRef-DoapSource" + } + }, { + "endPointer" : { + "lineNumber" : 23, + "reference" : "SPDXRef-DoapSource" + }, + "startPointer" : { + "lineNumber" : 5, + "reference" : "SPDXRef-DoapSource" + } + } ], + "snippetFromFile" : "SPDXRef-DoapSource" + } ], + "relationships" : [ { + "spdxElementId" : "SPDXRef-DOCUMENT", + "relationshipType" : "CONTAINS", + "relatedSpdxElement" : "SPDXRef-Package" + }, { + "spdxElementId" : "SPDXRef-DOCUMENT", + "relationshipType" : "COPY_OF", + "relatedSpdxElement" : "DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement" + }, { + "spdxElementId" : "SPDXRef-Package", + "relationshipType" : "DYNAMIC_LINK", + "relatedSpdxElement" : "SPDXRef-Saxon" + }, { + "spdxElementId" : "SPDXRef-CommonsLangSrc", + "relationshipType" : "GENERATED_FROM", + "relatedSpdxElement" : "NOASSERTION" + }, { + "spdxElementId" : "SPDXRef-JenaLib", + "relationshipType" : "CONTAINS", + "relatedSpdxElement" : "SPDXRef-Package" + }, { + "spdxElementId" : "SPDXRef-Specification", + "relationshipType" : "SPECIFICATION_FOR", + "relatedSpdxElement" : "SPDXRef-fromDoap-0" + }, { + "spdxElementId" : "SPDXRef-File", + "relationshipType" : "GENERATED_FROM", + "relatedSpdxElement" : "SPDXRef-fromDoap-0" + } ] +} diff --git a/tests/spdx/data/SPDXLite.spdx b/tests/spdx/data/SPDXLite.spdx new file mode 100644 index 000000000..d080bb86a --- /dev/null +++ b/tests/spdx/data/SPDXLite.spdx @@ -0,0 +1,36 @@ +# from https://github.com/OpenChain-Project/OpenChain-JWG/blob/4675d7a61ad552e8f9780419c54dddbdf87f6018/subgroups/sbom-sg/outcomes/SPDX-Lite/sample/SPDX-tools-spdxlite.txt +## 2 Document Creation Information + +SPDXVersion: SPDX-2.2 +DataLicense: CC0-1.0 +SPDXID: SPDXRef-DOCUMENT +DocumentName: example-v1.0 +DocumentNamespace: https://example.com/example-v1.0 +Creator: Person: someone +Created: 2021-04-05T01:23:45Z + +## 3 Package Information + +PackageName: SPDX tools +SPDXID: SPDXRef-spdxtools +PackageVersion: 2.0.3 +PackageFileName: spdx-tools-2.0.2-jar-with-dependencies.jar +PackageDownloadLocation: NONE +FilesAnalyzed: false +PackageHomePage: https://spdx.org/tools +PackageLicenseConcluded: Apache-2.0 +PackageLicenseDeclared: Apache-2.0 +PackageLicenseComments: +PackageCopyrightText: software copyright (c) 2000-2003, BEA Systems, +PackageComment: + ModificationRecord: NO + CompileOptions: --some-option + LinkMethodology: Dynamic + + +## 6 Other Licensing Information Detected + +LicenseID: LicenseRef-1 +ExtractedText: hoge +LicenseName: NOASSERTION +LicenseComment: diff --git a/tests/spdx/data/SPDXRdfExample-UTF-16.spdx.rdf.xml b/tests/spdx/data/SPDXRdfExample-UTF-16.spdx.rdf.xml new file mode 100644 index 000000000..c3760c7c8 Binary files /dev/null and b/tests/spdx/data/SPDXRdfExample-UTF-16.spdx.rdf.xml differ diff --git a/tests/spdx/data/SPDXRdfExample-v2.2.spdx.rdf.xml b/tests/spdx/data/SPDXRdfExample-v2.2.spdx.rdf.xml new file mode 100644 index 000000000..f5c306f74 --- /dev/null +++ b/tests/spdx/data/SPDXRdfExample-v2.2.spdx.rdf.xml @@ -0,0 +1,4146 @@ + + + + from linux kernel + + + + + 23 + + + Copyright 2010, 2011 Source Auditor Inc. + Open Logic Inc. + ./src/org/spdx/parser/DOAPProject.java + Black Duck Software In.c + Source Auditor Inc. + SPDX Technical Team Members + + + + <div class="optional-license-text"> + <p>Apache License + <br /> + +Version 2.0, January 2004 + <br /> + +http://www.apache.org/licenses/ + </p> + + </div> + <div class="optional-license-text"> + <p>TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION</p> + + </div> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">1.</var> + Definitions. + +<ul style="list-style:none"> +<li> + <p>&quot;License&quot; shall mean the terms and conditions for use, reproduction, and distribution + as defined by Sections 1 through 9 of this document.</p> + + </li> +<li> + <p>&quot;Licensor&quot; shall mean the copyright owner or entity authorized by the copyright owner + that is granting the License.</p> + + </li> +<li> + <p>&quot;Legal Entity&quot; shall mean the union of the acting entity and all other entities that + control, are controlled by, or are under common control with that entity. For the purposes of + this definition, &quot;control&quot; means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or otherwise, or (ii) ownership of + fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such + entity.</p> + + </li> +<li> + <p>&quot;You&quot; (or &quot;Your&quot;) shall mean an individual or Legal Entity exercising + permissions granted by this License.</p> + + </li> +<li> + <p>&quot;Source&quot; form shall mean the preferred form for making modifications, including but not + limited to software source code, documentation source, and configuration files.</p> + + </li> +<li> + <p>&quot;Object&quot; form shall mean any form resulting from mechanical transformation or + translation of a Source form, including but not limited to compiled object code, generated + documentation, and conversions to other media types.</p> + + </li> +<li> + <p>&quot;Work&quot; shall mean the work of authorship, whether in Source or Object form, made + available under the License, as indicated by a copyright notice that is included in or + attached to the work (an example is provided in the Appendix below).</p> + + </li> +<li> + <p>&quot;Derivative Works&quot; shall mean any work, whether in Source or Object form, that is based + on (or derived from) the Work and for which the editorial revisions, annotations, + elaborations, or other modifications represent, as a whole, an original work of authorship. + For the purposes of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative + Works thereof.</p> + + </li> +<li> + <p>&quot;Contribution&quot; shall mean any work of authorship, including the original version of the + Work and any modifications or additions to that Work or Derivative Works thereof, that is + intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an + individual or Legal Entity authorized to submit on behalf of the copyright owner. For the + purposes of this definition, &quot;submitted&quot; means any form of electronic, verbal, or + written communication sent to the Licensor or its representatives, including but not limited + to communication on electronic mailing lists, source code control systems, and issue tracking + systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and + improving the Work, but excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as &quot;Not a Contribution.&quot;</p> + + </li> +<li> + <p>&quot;Contributor&quot; shall mean Licensor and any individual or Legal Entity on behalf of whom + a Contribution has been received by Licensor and subsequently incorporated within the + Work.</p> + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">2.</var> + Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor + hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or + Object form. + </li> +<li> + <var class="replacable-license-text">3.</var> + Grant of Patent License. Subject to the terms and conditions of this License, each Contributor + hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + irrevocable (except as stated in this section) patent license to make, have made, use, offer + to sell, sell, import, and otherwise transfer the Work, where such license applies only to + those patent claims licensable by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) with the Work to which such + Contribution(s) was submitted. If You institute patent litigation against any entity + (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a + Contribution incorporated within the Work constitutes direct or contributory patent + infringement, then any patent licenses granted to You under this License for that Work shall + terminate as of the date such litigation is filed. + </li> +<li> + <var class="replacable-license-text">4.</var> + Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof + in any medium, with or without modifications, and in Source or Object form, provided that You + meet the following conditions: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">(a)</var> + You must give any other recipients of the Work or Derivative Works a copy of this License; and + </li> +<li> + <var class="replacable-license-text">(b)</var> + You must cause any modified files to carry prominent notices stating that You changed the files; and + </li> +<li> + <var class="replacable-license-text">(c)</var> + You must retain, in the Source form of any Derivative Works that You distribute, all + copyright, patent, trademark, and attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of the Derivative Works; and + </li> +<li> + <var class="replacable-license-text">(d)</var> + If the Work includes a &quot;NOTICE&quot; text file as part of its distribution, then any + Derivative Works that You distribute must include a readable copy of the attribution + notices contained within such NOTICE file, excluding those notices that do not pertain to + any part of the Derivative Works, in at least one of the following places: within a NOTICE + text file distributed as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, within a display generated + by the Derivative Works, if and wherever such third-party notices normally appear. The + contents of the NOTICE file are for informational purposes only and do not modify the + License. You may add Your own attribution notices within Derivative Works that You + distribute, alongside or as an addendum to the NOTICE text from the Work, provided that + such additional attribution notices cannot be construed as modifying the License. + <p>You may add Your own copyright statement to Your modifications and may provide additional or + different license terms and conditions for use, reproduction, or distribution of Your + modifications, or for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with the conditions stated + in this License.</p> + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">5.</var> + Submission of Contributions. Unless You explicitly state otherwise, any Contribution + intentionally submitted for inclusion in the Work by You to the Licensor shall be under the + terms and conditions of this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate + license agreement you may have executed with Licensor regarding such Contributions. + </li> +<li> + <var class="replacable-license-text">6.</var> + Trademarks. This License does not grant permission to use the trade names, trademarks, service + marks, or product names of the Licensor, except as required for reasonable and customary use + in describing the origin of the Work and reproducing the content of the NOTICE file. + </li> +<li> + <var class="replacable-license-text">7.</var> + Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor + provides the Work (and each Contributor provides its Contributions) on an &quot;AS IS&quot; + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, + without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, + or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any risks associated with Your + exercise of permissions under this License. + </li> +<li> + <var class="replacable-license-text">8.</var> + Limitation of Liability. In no event and under no legal theory, whether in tort (including + negligence), contract, or otherwise, unless required by applicable law (such as deliberate and + grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for + damages, including any direct, indirect, special, incidental, or consequential damages of any + character arising as a result of this License or out of the use or inability to use the Work + (including but not limited to damages for loss of goodwill, work stoppage, computer failure or + malfunction, or any and all other commercial damages or losses), even if such Contributor has + been advised of the possibility of such damages. + </li> +<li> + <var class="replacable-license-text">9.</var> + Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works + thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, + indemnity, or other liability obligations and/or rights consistent with this License. However, + in accepting such obligations, You may act only on Your own behalf and on Your sole + responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability incurred by, or claims asserted + against, such Contributor by reason of your accepting any such warranty or additional + liability. + </li> +</ul> + + <div class="optional-license-text"> + <p>END OF TERMS AND CONDITIONS</p> + + <p>APPENDIX: How to apply the Apache License to your work.</p> + + <p>To apply the Apache License to your work, attach the following boilerplate notice, with the fields + enclosed by brackets &quot;[]&quot; replaced with your own identifying information. (Don&apos;t + include the brackets!) The text should be enclosed in the appropriate comment syntax for the file + format. We also recommend that a file or class name and description of purpose be included on the same + &quot;printed page&quot; as the copyright notice for easier identification within third-party + archives.</p> + + <p>Copyright <var class="replacable-license-text">[yyyy] [name of copyright owner]</var></p> + + <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); + <br /> + +you may not use this file except in compliance with the License. + <br /> + +You may obtain a copy of the License at + </p> + + <p>http://www.apache.org/licenses/LICENSE-2.0</p> + + <p>Unless required by applicable law or agreed to in writing, software + <br /> + +distributed under the License is distributed on an &quot;AS IS&quot; BASIS, + <br /> + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + <br /> + +See the License for the specific language governing permissions and + <br /> + +limitations under the License. + </p> + + </div> + + This license was released January 2004 + Apache License 2.0 + + + 0 + 2021-05-20 - 16:57:10 + http://www.apache.org/licenses/LICENSE-2.0 + true + false + true + true + + + <<beginOptional>> Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +<<endOptional>><<beginOptional>> TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +<<endOptional>> + + <<var;name="bullet";original="1.";match=".{0,20}">> Definitions. + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + <<var;name="bullet";original="2.";match=".{0,20}">> Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + <<var;name="bullet";original="3.";match=".{0,20}">> Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + <<var;name="bullet";original="4.";match=".{0,20}">> Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + <<var;name="bullet";original="(a)";match=".{0,20}">> You must give any other recipients of the Work or Derivative Works a copy of this License; and + + <<var;name="bullet";original="(b)";match=".{0,20}">> You must cause any modified files to carry prominent notices stating that You changed the files; and + + <<var;name="bullet";original="(c)";match=".{0,20}">> You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + <<var;name="bullet";original="(d)";match=".{0,20}">> If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + <<var;name="bullet";original="5.";match=".{0,20}">> Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + <<var;name="bullet";original="6.";match=".{0,20}">> Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + <<var;name="bullet";original="7.";match=".{0,20}">> Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + <<var;name="bullet";original="8.";match=".{0,20}">> Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + <<var;name="bullet";original="9.";match=".{0,20}">> Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.<<beginOptional>> END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright <<var;name="copyright";original="[yyyy] [name of copyright owner]";match=".+">> + +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. + +<<endOptional>> + + + 1 + 2021-05-20 - 16:57:10 + https://opensource.org/licenses/Apache-2.0 + true + false + true + true + + + Copyright [yyyy] [name of copyright owner] + +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. + + + + <p>Copyright <var class="replacable-license-text">[yyyy] [name of copyright owner]</var></p> + + <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); + <br /> + +you may not use this file except in compliance with the License. + <br /> + +You may obtain a copy of the License at + </p> + + <p>http://www.apache.org/licenses/LICENSE-2.0</p> + + <p>Unless required by applicable law or agreed to in writing, software + <br /> + +distributed under the License is distributed on an &quot;AS IS&quot; BASIS, + <br /> + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + <br /> + +See the License for the specific language governing permissions and + <br /> + +limitations under the License. + </p> + + + Copyright <<var;name="copyright";original="[yyyy] [name of copyright owner]";match=".+">> + +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. + + + true + true + https://opensource.org/licenses/Apache-2.0 + http://www.apache.org/licenses/LICENSE-2.0 + false + Apache-2.0 + Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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. + + + + + + + 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 + + + Protecode Inc. + + + + + + + + + 5 + + + + + + Copyright 2008-2010 John Smith + The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. + + + + + 420 + + + + + + 310 + + + + + + + + + https://opensource.org/licenses/GPL-2.0 + This license was released: June 1991. This license identifier refers to the choice to use the code under GPL-2.0-only, as distinguished from use of code under GPL-2.0-or-later (i.e., GPL-2.0 or some later version). The license notice (as seen in the Standard License Header field below) states which of these applies to the code in the file. The example in the exhibit to the license shows the license notice for the "or later" approach. + GPL-2.0-only + https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + + <div class="optional-license-text"> + <p> + GNU GENERAL PUBLIC LICENSE<br /> + + Version 2, June 1991 + </p> + + </div> + <p> + Copyright (C) 1989, 1991 Free Software Foundation, Inc.<var class="replacable-license-text"></var><br /> + + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<var class="optional-license-text">,</var> + USA + </p> + + <p> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + </p> + + <p> + Preamble + </p> + + <p> + The licenses for most software are designed to take away your freedom + to share and change it. By contrast, the GNU General Public License is + intended to guarantee your freedom to share and change free software--to + make sure the software is free for all its users. This General Public + License applies to most of the Free Software Foundation&apos;s software + and to any other program whose authors commit to using it. (Some other + Free Software Foundation software is covered by the GNU Lesser General + Public License instead.) You can apply it to your programs, too. + </p> + + <p> + When we speak of free software, we are referring to freedom, not price. + Our General Public Licenses are designed to make sure that you have + the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get + it if you want it, that you can change the software or use pieces of + it in new free programs; and that you know you can do these things. + </p> + + <p> + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the + rights. These restrictions translate to certain responsibilities for + you if you distribute copies of the software, or if you modify it. + </p> + + <p> + For example, if you distribute copies of such a program, whether gratis + or for a fee, you must give the recipients all the rights that you + have. You must make sure that they, too, receive or can get the source + code. And you must show them these terms so they know their rights. + </p> + + <p> + We protect your rights with two steps: (1) copyright the + software, and (2) offer you this license which gives you legal + permission to copy, distribute and/or modify the software. + </p> + + <p> + Also, for each author&apos;s protection and ours, we want to make + certain that everyone understands that there is no warranty for + this free software. If the software is modified by someone else + and passed on, we want its recipients to know that what they + have is not the original, so that any problems introduced by + others will not reflect on the original authors&apos; reputations. + </p> + + <p> + Finally, any free program is threatened constantly by software patents. + We wish to avoid the danger that redistributors of a free program + will individually obtain patent licenses, in effect making the program + proprietary. To prevent this, we have made it clear that any patent + must be licensed for everyone&apos;s free use or not licensed at all. + </p> + + <p> + The precise terms and conditions for copying, + distribution and modification follow. + </p> + + <p> + <var class="replacable-license-text"></var> + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + </p> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">0.</var> + This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The &quot;Program&quot;, below, + refers to any such program or work, and a &quot;work based on the Program&quot; + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation + in the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;. + <p> + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act + of running the Program is not restricted, and the output from the + Program is covered only if its contents constitute a work based + on the Program (independent of having been made by running the + Program). Whether that is true depends on what the Program does. + </p> + + </li> +<li> + <var class="replacable-license-text">1.</var> + You may copy and distribute verbatim copies of the Program&apos;s source + code as you receive it, in any medium, provided that you conspicuously + and appropriately publish on each copy an appropriate copyright notice + and disclaimer of warranty; keep intact all the notices that refer to + this License and to the absence of any warranty; and give any other + recipients of the Program a copy of this License along with the Program. + <p> + You may charge a fee for the physical act of + transferring a copy, and you may at your option + offer warranty protection in exchange for a fee. + </p> + + </li> +<li> + <var class="replacable-license-text">2.</var> + You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section + 1 above, provided that you also meet all of these conditions: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + </li> +<li> + <var class="replacable-license-text">b)</var> + You must cause any work that you distribute or publish, + that in whole or in part contains or is derived from the + Program or any part thereof, to be licensed as a whole at no + charge to all third parties under the terms of this License. + </li> +<li> + <var class="replacable-license-text">c)</var> + If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display + an announcement including an appropriate copyright notice and + a notice that there is no warranty (or else, saying that you + provide a warranty) and that users may redistribute the program + under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive + but does not normally print such an announcement, your work + based on the Program is not required to print an announcement.) + </li> +</ul> + <p> + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Program, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not + apply to those sections when you distribute them as separate + works. But when you distribute the same sections as part of a + whole which is a work based on the Program, the distribution + of the whole must be on the terms of this License, whose + permissions for other licensees extend to the entire whole, + and thus to each and every part regardless of who wrote it. + </p> + + <p> + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, + the intent is to exercise the right to control the distribution + of derivative or collective works based on the Program. + </p> + + <p> + In addition, mere aggregation of another work not based on + the Program with the Program (or with a work based on the + Program) on a volume of a storage or distribution medium does + not bring the other work under the scope of this License. + </p> + + </li> +<li> + <var class="replacable-license-text">3.</var> + You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and + 2 above on a medium customarily used for software interchange; or, + </li> +<li> + <var class="replacable-license-text">b)</var> + Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to + be distributed under the terms of Sections 1 and 2 above + on a medium customarily used for software interchange; or, + </li> +<li> + <var class="replacable-license-text">c)</var> + Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative + is allowed only for noncommercial distribution and only if + you received the program in object code or executable form + with such an offer, in accord with Subsection b above.) + </li> +</ul> + <p> + The source code for a work means the preferred form of the work + for making modifications to it. For an executable work, complete + source code means all the source code for all modules it contains, + plus any associated interface definition files, plus the scripts + used to control compilation and installation of the executable. + However, as a special exception, the source code distributed + need not include anything that is normally distributed (in either + source or binary form) with the major components (compiler, + kernel, and so on) of the operating system on which the executable + runs, unless that component itself accompanies the executable. + </p> + + <p> + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are + not compelled to copy the source along with the object code. + </p> + + </li> +<li> + <var class="replacable-license-text">4.</var> + You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program + is void, and will automatically terminate your rights under + this License. However, parties who have received copies, or + rights, from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + </li> +<li> + <var class="replacable-license-text">5.</var> + You are not required to accept this License, since you have + not signed it. However, nothing else grants you permission to + modify or distribute the Program or its derivative works. These + actions are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Program (or any + work based on the Program), you indicate your acceptance of this + License to do so, and all its terms and conditions for copying, + distributing or modifying the Program or works based on it. + </li> +<li> + <var class="replacable-license-text">6.</var> + Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further restrictions + on the recipients&apos; exercise of the rights granted herein. You are not + responsible for enforcing compliance by third parties to this License. + </li> +<li> + <var class="replacable-license-text">7.</var> + If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement + or otherwise) that contradict the conditions of this License, + they do not excuse you from the conditions of this License. If you + cannot distribute so as to satisfy simultaneously your obligations + under this License and any other pertinent obligations, then as a + consequence you may not distribute the Program at all. For example, + if a patent license would not permit royalty-free redistribution of + the Program by all those who receive copies directly or indirectly + through you, then the only way you could satisfy both it and this + License would be to refrain entirely from distribution of the Program. + <p> + If any portion of this section is held invalid or + unenforceable under any particular circumstance, the + balance of the section is intended to apply and the section + as a whole is intended to apply in other circumstances. + </p> + + <p> + It is not the purpose of this section to induce you to infringe + any patents or other property right claims or to contest + validity of any such claims; this section has the sole purpose + of protecting the integrity of the free software distribution + system, which is implemented by public license practices. Many + people have made generous contributions to the wide range of + software distributed through that system in reliance on consistent + application of that system; it is up to the author/donor to + decide if he or she is willing to distribute software through + any other system and a licensee cannot impose that choice. + </p> + + <p> + This section is intended to make thoroughly clear what is + believed to be a consequence of the rest of this License. + </p> + + </li> +<li> + <var class="replacable-license-text">8.</var> + If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Program under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this License + incorporates the limitation as if written in the body of this License. + </li> +<li> + <var class="replacable-license-text">9.</var> + The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such + new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + <p> + Each version is given a distinguishing version number. If the + Program specifies a version number of this License which applies + to it and &quot;any later version&quot;, you have the option of following + the terms and conditions either of that version or of any later + version published by the Free Software Foundation. If the Program + does not specify a version number of this License, you may choose + any version ever published by the Free Software Foundation. + </p> + + </li> +<li> + <var class="replacable-license-text">10.</var> + If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted by the + Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + <p> + NO WARRANTY + </p> + + </li> +<li> + <var class="replacable-license-text">11.</var> + BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT + WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER + PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, + EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF + THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU + ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + </li> +<li> + <var class="replacable-license-text">12.</var> + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF + THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER + OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + </li> +</ul> + <div class="optional-license-text"> + <p> + END OF TERMS AND CONDITIONS + </p> + + <p> + How to Apply These Terms to Your New Programs + </p> + + <p> + If you develop a new program, and you want it to be + of the greatest possible use to the public, the best + way to achieve this is to make it free software which + everyone can redistribute and change under these terms. + </p> + + <p> + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least + the &quot;copyright&quot; line and a pointer to where the full notice is found. + </p> + + <p> + <var class="optional-license-text">&lt;</var>one line to give the program&apos;s name and <var class="replacable-license-text">an</var> idea of what it does.<var class="optional-license-text">&gt;</var> + <br /> + + Copyright (C) + <var class="optional-license-text">&lt;</var><var class="replacable-license-text">yyyy</var><var class="optional-license-text">&gt;</var> + <var class="optional-license-text">&lt;</var>name of author<var class="optional-license-text">&gt;</var> + </p> + + <p> + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version. + </p> + + <p> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more details. + </p> + + <p> + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<var class="optional-license-text">,</var> + USA. + </p> + + <p> + Also add information on how to + contact you by electronic and paper mail. + </p> + + <p> + If the program is interactive, make it output a short + notice like this when it starts in an interactive mode: + </p> + + <p> + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details + type `show w&apos;. This is free software, and you are welcome to + redistribute it under certain conditions; type `show c&apos; for details. + </p> + + <p> + The hypothetical commands `show w&apos; and `show c&apos; should show the + appropriate parts of the General Public License. Of course, the commands + you use may be called something other than `show w&apos; and `show c&apos;; they + could even be mouse-clicks or menu items--whatever suits your program. + </p> + + <p> + You should also get your employer (if you work as a programmer) + or your school, if any, to sign a &quot;copyright disclaimer&quot; for + the program, if necessary. Here is a sample; alter the names: + </p> + + <p> + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision&apos; (which makes passes at compilers) written by James Hacker. + </p> + + <p> + <var class="optional-license-text">&lt;</var>signature of Ty Coon<var class="optional-license-text">&gt;</var>, + 1 April 1989 Ty Coon, President of Vice + </p> + + </div> + <div class="optional-license-text"> + <p> + This General Public License does not permit incorporating your program into + proprietary programs. If your program is a subroutine library, you may + consider it more useful to permit linking proprietary applications with the + library. If this is what you want to do, use the GNU Lesser General + Public License instead of this License. + </p> + + </div> + + true + Copyright (C) <<var;name="copyright";original="yyyy name of author";match=".+">> + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<<beginOptional>>, <<endOptional>> USA. + + + false + GNU General Public License v2.0 only + <<beginOptional>> GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +<<endOptional>> + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. <<var;name="incComma";original="";match=",|">> + +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<<beginOptional>>, <<endOptional>> USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +<<var;name="termsTitle";original="";match="GNU GENERAL PUBLIC LICENSE|">> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + <<var;name="bullet";original="0.";match=".{0,20}">> This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + + <<var;name="bullet";original="1.";match=".{0,20}">> You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + + You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + + <<var;name="bullet";original="2.";match=".{0,20}">> You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + <<var;name="bullet";original="a)";match=".{0,20}">> You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + <<var;name="bullet";original="b)";match=".{0,20}">> You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + <<var;name="bullet";original="c)";match=".{0,20}">> If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + + <<var;name="bullet";original="3.";match=".{0,20}">> You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + <<var;name="bullet";original="a)";match=".{0,20}">> Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + <<var;name="bullet";original="b)";match=".{0,20}">> Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + <<var;name="bullet";original="c)";match=".{0,20}">> Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + + If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + + <<var;name="bullet";original="4.";match=".{0,20}">> You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + + <<var;name="bullet";original="5.";match=".{0,20}">> You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + + <<var;name="bullet";original="6.";match=".{0,20}">> Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + + <<var;name="bullet";original="7.";match=".{0,20}">> If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + + <<var;name="bullet";original="8.";match=".{0,20}">> If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + + <<var;name="bullet";original="9.";match=".{0,20}">> The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + + <<var;name="bullet";original="10.";match=".{0,20}">> If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + <<var;name="bullet";original="11.";match=".{0,20}">> BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + <<var;name="bullet";original="12.";match=".{0,20}">> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.<<beginOptional>> END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +<<beginOptional>><<<endOptional>>one line to give the program's name and <<var;name="ideaArticle";original="an";match="a brief|an">> idea of what it does.<<beginOptional>>><<endOptional>> + +Copyright (C)<<beginOptional>><<<endOptional>> <<var;name="templateYear";original="yyyy";match="yyyy|year">><<beginOptional>>> <<endOptional>><<beginOptional>> <<<endOptional>>name of author<<beginOptional>>><<endOptional>> + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<<beginOptional>>, <<endOptional>> USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +<<beginOptional>><<<endOptional>>signature of Ty Coon<<beginOptional>> ><<endOptional>>, 1 April 1989 Ty Coon, President of Vice + +<<endOptional>><<beginOptional>> This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. + +<<endOptional>> + + Copyright (C) <var class="replacable-license-text">yyyy name of author</var> + <p> + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2. + </p> + + <p> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more details. + </p> + + <p> + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<var class="optional-license-text">,</var> + USA. + </p> + + + + + 1 + 2021-05-20 - 16:58:58 + https://opensource.org/licenses/GPL-2.0 + false + false + true + true + + + + + 0 + 2021-05-20 - 16:58:58 + https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + true + false + true + true + + + true + GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice + + Copyright (C) yyyy name of author + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + + + + + This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. + + + + + + + + http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz + + + + + http://justasample.url.com + http://people.apache.org/~andyc/neko/LICENSE + This is tye CyperNeko License + The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + CyberNeko License + + + + + GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1991 Free Software Foundation, Inc. +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. + +This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. + +Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. + +Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. + +The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. + +Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. + +However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. + +The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. + +Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". + +A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. + +1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. + +(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. + +Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the Library into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. + +5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. + +However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. + +When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. + +If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. + +6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. + +You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: + + a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. + + d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. + + b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. + +14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). + +To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the library's name and an idea of what it does. + Copyright (C) year name of author + + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in +the library `Frob' (a library for tweaking knobs) written +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 +Ty Coon, President of Vice + +That's all there is to it! + LGPL-2.0-only + https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html + false + + Copyright (C) <var class="replacable-license-text">year name of author</var> + <p>This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; version 2.</p> + + <p>This library is distributed + in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU Library General Public License for more details.</p> + + <p>You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + </p> + + + <<beginOptional>> GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +<<endOptional>> <<var;name="copyright";original="Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ";match=".{0,5000}">> + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. + +This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. + +Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. + +Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. + +The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. + +Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. + +However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. + +The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. + +Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + <<var;name="bullet";original="0.";match=".{0,20}">> This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. + + Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. + + <<var;name="bullet";original="1.";match=".{0,20}">> You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. + + You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + + <<var;name="bullet";original="2.";match=".{0,20}">> You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + <<var;name="bullet";original="a)";match=".{0,20}">> The modified work must itself be a software library. + + <<var;name="bullet";original="b)";match=".{0,20}">> You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. + + <<var;name="bullet";original="c)";match=".{0,20}">> You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. + + <<var;name="bullet";original="d)";match=".{0,20}">> If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. + + (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) + + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. + + In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + + <<var;name="bullet";original="3.";match=".{0,20}">> You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. + + Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of the Library into a program that is not a library. + + <<var;name="bullet";original="4.";match=".{0,20}">> You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. + + <<var;name="bullet";original="5.";match=".{0,20}">> A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. + + <<var;name="bullet";original="6.";match=".{0,20}">> As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: + + <<var;name="bullet";original="a)";match=".{0,20}">> Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) + + <<var;name="bullet";original="b)";match=".{0,20}">> Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. + + <<var;name="bullet";original="c)";match=".{0,20}">> If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. + + <<var;name="bullet";original="d)";match=".{0,20}">> Verify that the user has already received a copy of these materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + + It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. + + <<var;name="bullet";original="7.";match=".{0,20}">> You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: + + <<var;name="bullet";original="a)";match=".{0,20}">> Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. + + <<var;name="bullet";original="b)";match=".{0,20}">> Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + + <<var;name="bullet";original="8.";match=".{0,20}">> You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + + <<var;name="bullet";original="9.";match=".{0,20}">> You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. + + <<var;name="bullet";original="10.";match=".{0,20}">> Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + + <<var;name="bullet";original="11.";match=".{0,20}">> If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. + + If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + + <<var;name="bullet";original="12.";match=".{0,20}">> If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + + <<var;name="bullet";original="13.";match=".{0,20}">> The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. + + <<var;name="bullet";original="14.";match=".{0,20}">> If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + <<var;name="bullet";original="15.";match=".{0,20}">> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + <<var;name="bullet";original="16.";match=".{0,20}">> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.<<beginOptional>> END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). + +To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +one line to give the library's name and an idea of what it does. + +Copyright (C) year name of author + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in + +the library `Frob' (a library for tweaking knobs) written + +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 + +Ty Coon, President of Vice + +That's all there is to it! + +<<endOptional>> + + <div class="optional-license-text"> + <p> + GNU LIBRARY GENERAL PUBLIC LICENSE + </p> + + <p> + Version 2, June 1991 + </p> + + </div> + <div class="replacable-license-text"> + <p> + Copyright (C) 1991 Free Software Foundation, Inc.<br /> + + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + </p> + + </div> + <p> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + </p> + + <p> + [This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + </p> + + <p> + Preamble + </p> + + <p> + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + Licenses are intended to guarantee your freedom to share and change + free software--to make sure the software is free for all its users. + </p> + + <p> + This license, the Library General Public License, applies + to some specially designated Free Software Foundation + software, and to any other libraries whose authors + decide to use it. You can use it for your libraries, too. + </p> + + <p> + When we speak of free software, we are referring to freedom, not price. + Our General Public Licenses are designed to make sure that you have + the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get + it if you want it, that you can change the software or use pieces of + it in new free programs; and that you know you can do these things. + </p> + + <p> + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the + rights. These restrictions translate to certain responsibilities for + you if you distribute copies of the library, or if you modify it. + </p> + + <p> + For example, if you distribute copies of the library, whether gratis + or for a fee, you must give the recipients all the rights that we + gave you. You must make sure that they, too, receive or can get the + source code. If you link a program with the library, you must provide + complete object files to the recipients so that they can relink them + with the library, after making changes to the library and recompiling + it. And you must show them these terms so they know their rights. + </p> + + <p> + Our method of protecting your rights has two steps: (1) copyright + the library, and (2) offer you this license which gives you + legal permission to copy, distribute and/or modify the library. + </p> + + <p> + Also, for each distributor&apos;s protection, we want to make certain + that everyone understands that there is no warranty for this + free library. If the library is modified by someone else and + passed on, we want its recipients to know that what they have + is not the original version, so that any problems introduced by + others will not reflect on the original authors&apos; reputations. + </p> + + <p> + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that companies distributing + free software will individually obtain patent licenses, thus + in effect transforming the program into proprietary software. + To prevent this, we have made it clear that any patent must + be licensed for everyone&apos;s free use or not licensed at all. + </p> + + <p> + Most GNU software, including some libraries, is covered by the + ordinary GNU General Public License, which was designed for utility + programs. This license, the GNU Library General Public License, + applies to certain designated libraries. This license is quite + different from the ordinary one; be sure to read it in full, and don&apos;t + assume that anything in it is the same as in the ordinary license. + </p> + + <p> + The reason we have a separate public license for some libraries is + that they blur the distinction we usually make between modifying + or adding to a program and simply using it. Linking a program with + a library, without changing the library, is in some sense simply + using the library, and is analogous to running a utility program + or application program. However, in a textual and legal sense, the + linked executable is a combined work, a derivative of the original + library, and the ordinary General Public License treats it as such. + </p> + + <p> + Because of this blurred distinction, using the ordinary General + Public License for libraries did not effectively promote software + sharing, because most developers did not use the libraries. We + concluded that weaker conditions might promote sharing better. + </p> + + <p> + However, unrestricted linking of non-free programs would deprive the + users of those programs of all benefit from the free status of the + libraries themselves. This Library General Public License is intended + to permit developers of non-free programs to use free libraries, while + preserving your freedom as a user of such programs to change the free + libraries that are incorporated in them. (We have not seen how to + achieve this as regards changes in header files, but we have achieved + it as regards changes in the actual functions of the Library.) The + hope is that this will lead to faster development of free libraries. + </p> + + <p> + The precise terms and conditions for copying, distribution + and modification follow. Pay close attention to the difference + between a &quot;work based on the library&quot; and a &quot;work that uses + the library&quot;. The former contains code derived from the + library, while the latter only works together with the library. + </p> + + <p> + Note that it is possible for a library to be covered by the + ordinary General Public License rather than by this special one. + </p> + + <p> + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + </p> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">0.</var> + This License Agreement applies to any software library + which contains a notice placed by the copyright holder or + other authorized party saying it may be distributed under + the terms of this Library General Public License (also + called &quot;this License&quot;). Each licensee is addressed as &quot;you&quot;. + <p> + A &quot;library&quot; means a collection of software functions and/or data + prepared so as to be conveniently linked with application programs + (which use some of those functions and data) to form executables. + </p> + + <p> + The &quot;Library&quot;, below, refers to any such software library or work + which has been distributed under these terms. A &quot;work based on + the Library&quot; means either the Library or any derivative work under + copyright law: that is to say, a work containing the Library or a + portion of it, either verbatim or with modifications and/or translated + straightforwardly into another language. (Hereinafter, translation + is included without limitation in the term &quot;modification&quot;.) + </p> + + <p> + &quot;Source code&quot; for a work means the preferred form of the work + for making modifications to it. For a library, complete source + code means all the source code for all modules it contains, + plus any associated interface definition files, plus the scripts + used to control compilation and installation of the library. + </p> + + <p> + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act of + running a program using the Library is not restricted, and output + from such a program is covered only if its contents constitute a + work based on the Library (independent of the use of the Library + in a tool for writing it). Whether that is true depends on what + the Library does and what the program that uses the Library does. + </p> + + </li> +<li> + <var class="replacable-license-text">1.</var> + You may copy and distribute verbatim copies of the Library&apos;s complete + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any warranty; + and distribute a copy of this License along with the Library. + <p> + You may charge a fee for the physical act of + transferring a copy, and you may at your option + offer warranty protection in exchange for a fee. + </p> + + </li> +<li> + <var class="replacable-license-text">2.</var> + You may modify your copy or copies of the Library or any portion + of it, thus forming a work based on the Library, and copy and + distribute such modifications or work under the terms of Section + 1 above, provided that you also meet all of these conditions: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + The modified work must itself be a software library. + </li> +<li> + <var class="replacable-license-text">b)</var> + You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + </li> +<li> + <var class="replacable-license-text">c)</var> + You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + </li> +<li> + <var class="replacable-license-text">d)</var> + If a facility in the modified Library refers to a function + or a table of data to be supplied by an application program + that uses the facility, other than as an argument passed + when the facility is invoked, then you must make a good faith + effort to ensure that, in the event an application does not + supply such function or table, the facility still operates, + and performs whatever part of its purpose remains meaningful. + <p> + (For example, a function in a library to compute square roots + has a purpose that is entirely well-defined independent of + the application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function + must be optional: if the application does not supply it, + the square root function must still compute square roots.) + </p> + + </li> +</ul> + <p> + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Library, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not + apply to those sections when you distribute them as separate + works. But when you distribute the same sections as part of a + whole which is a work based on the Library, the distribution + of the whole must be on the terms of this License, whose + permissions for other licensees extend to the entire whole, + and thus to each and every part regardless of who wrote it. + </p> + + <p> + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, + the intent is to exercise the right to control the distribution + of derivative or collective works based on the Library. + </p> + + <p> + In addition, mere aggregation of another work not based on + the Library with the Library (or with a work based on the + Library) on a volume of a storage or distribution medium does + not bring the other work under the scope of this License. + </p> + + </li> +<li> + <var class="replacable-license-text">3.</var> + You may opt to apply the terms of the ordinary GNU General + Public License instead of this License to a given copy of the + Library. To do this, you must alter all the notices that refer + to this License, so that they refer to the ordinary GNU General + Public License, version 2, instead of to this License. (If a + newer version than version 2 of the ordinary GNU General Public + License has appeared, then you can specify that version instead + if you wish.) Do not make any other change in these notices. + <p> + Once this change is made in a given copy, it is irreversible for + that copy, so the ordinary GNU General Public License applies to + all subsequent copies and derivative works made from that copy. + </p> + + <p> + This option is useful when you wish to copy part of the + code of the Library into a program that is not a library. + </p> + + </li> +<li> + <var class="replacable-license-text">4.</var> + You may copy and distribute the Library (or a portion or derivative + of it, under Section 2) in object code or executable form under + the terms of Sections 1 and 2 above provided that you accompany + it with the complete corresponding machine-readable source code, + which must be distributed under the terms of Sections 1 and 2 + above on a medium customarily used for software interchange. + <p> + If distribution of object code is made by offering access to copy + from a designated place, then offering equivalent access to copy + the source code from the same place satisfies the requirement + to distribute the source code, even though third parties are + not compelled to copy the source along with the object code. + </p> + + </li> +<li> + <var class="replacable-license-text">5.</var> + A program that contains no derivative of any portion of the + Library, but is designed to work with the Library by being compiled + or linked with it, is called a &quot;work that uses the Library&quot;. + Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License. + <p> + However, linking a &quot;work that uses the Library&quot; with the Library + creates an executable that is a derivative of the Library (because + it contains portions of the Library), rather than a &quot;work that uses + the library&quot;. The executable is therefore covered by this License. + Section 6 states terms for distribution of such executables. + </p> + + <p> + When a &quot;work that uses the Library&quot; uses material from a header + file that is part of the Library, the object code for the work may + be a derivative work of the Library even though the source code is + not. Whether this is true is especially significant if the work can + be linked without the Library, or if the work is itself a library. + The threshold for this to be true is not precisely defined by law. + </p> + + <p> + If such an object file uses only numerical parameters, data + structure layouts and accessors, and small macros and small inline + functions (ten lines or less in length), then the use of the + object file is unrestricted, regardless of whether it is legally + a derivative work. (Executables containing this object code + plus portions of the Library will still fall under Section 6.) + </p> + + <p> + Otherwise, if the work is a derivative of the Library, you may + distribute the object code for the work under the terms of Section + 6. Any executables containing that work also fall under Section 6, + whether or not they are linked directly with the Library itself. + </p> + + </li> +<li> + <var class="replacable-license-text">6.</var> + As an exception to the Sections above, you may also compile or + link a &quot;work that uses the Library&quot; with the Library to produce + a work containing portions of the Library, and distribute + that work under terms of your choice, provided that the terms + permit modification of the work for the customer&apos;s own use + and reverse engineering for debugging such modifications. + <p> + You must give prominent notice with each copy of the work + that the Library is used in it and that the Library and its + use are covered by this License. You must supply a copy of + this License. If the work during execution displays copyright + notices, you must include the copyright notice for the Library + among them, as well as a reference directing the user to the + copy of this License. Also, you must do one of these things: + </p> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + Accompany the work with the complete corresponding machine-readable + source code for the Library including whatever changes were used in + the work (which must be distributed under Sections 1 and 2 above); + and, if the work is an executable linked with the Library, with the + complete machine-readable &quot;work that uses the Library&quot;, as object + code and/or source code, so that the user can modify the Library + and then relink to produce a modified executable containing the + modified Library. (It is understood that the user who changes the + contents of definitions files in the Library will not necessarily be + able to recompile the application to use the modified definitions.) + </li> +<li> + <var class="replacable-license-text">b)</var> + Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no + more than the cost of performing this distribution. + </li> +<li> + <var class="replacable-license-text">c)</var> + If distribution of the work is made by offering access to + copy from a designated place, offer equivalent access to + copy the above specified materials from the same place. + </li> +<li> + <var class="replacable-license-text">d)</var> + Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + </li> +</ul> + <p> + For an executable, the required form of the &quot;work that uses + the Library&quot; must include any data and utility programs needed + for reproducing the executable from it. However, as a special + exception, the source code distributed need not include + anything that is normally distributed (in either source or + binary form) with the major components (compiler, kernel, + and so on) of the operating system on which the executable + runs, unless that component itself accompanies the executable. + </p> + + <p> + It may happen that this requirement contradicts the + license restrictions of other proprietary libraries that + do not normally accompany the operating system. Such + a contradiction means you cannot use both them and the + Library together in an executable that you distribute. + </p> + + </li> +<li> + <var class="replacable-license-text">7.</var> + You may place library facilities that are a work based on the + Library side-by-side in a single library together with other library + facilities not covered by this License, and distribute such a + combined library, provided that the separate distribution of the + work based on the Library and of the other library facilities is + otherwise permitted, and provided that you do these two things: + </li> +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities. + This must be distributed under the terms of the Sections above. + </li> +<li> + <var class="replacable-license-text">b)</var> + Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + </li> +</ul> +<li> + <var class="replacable-license-text">8.</var> + You may not copy, modify, sublicense, link with, or distribute the + Library except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, link with, or distribute + the Library is void, and will automatically terminate your rights + under this License. However, parties who have received copies, or + rights, from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + </li> +<li> + <var class="replacable-license-text">9.</var> + You are not required to accept this License, since you have + not signed it. However, nothing else grants you permission to + modify or distribute the Library or its derivative works. These + actions are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Library (or any + work based on the Library), you indicate your acceptance of this + License to do so, and all its terms and conditions for copying, + distributing or modifying the Library or works based on it. + </li> +<li> + <var class="replacable-license-text">10.</var> + Each time you redistribute the Library (or any work based on + the Library), the recipient automatically receives a license + from the original licensor to copy, distribute, link with or + modify the Library subject to these terms and conditions. You + may not impose any further restrictions on the recipients&apos; + exercise of the rights granted herein. You are not responsible + for enforcing compliance by third parties to this License. + </li> +<li> + <var class="replacable-license-text">11.</var> + If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement + or otherwise) that contradict the conditions of this License, + they do not excuse you from the conditions of this License. If you + cannot distribute so as to satisfy simultaneously your obligations + under this License and any other pertinent obligations, then as a + consequence you may not distribute the Library at all. For example, + if a patent license would not permit royalty-free redistribution of + the Library by all those who receive copies directly or indirectly + through you, then the only way you could satisfy both it and this + License would be to refrain entirely from distribution of the Library. + <p> + If any portion of this section is held invalid or + unenforceable under any particular circumstance, the + balance of the section is intended to apply, and the section + as a whole is intended to apply in other circumstances. + </p> + + <p> + It is not the purpose of this section to induce you to infringe + any patents or other property right claims or to contest + validity of any such claims; this section has the sole purpose + of protecting the integrity of the free software distribution + system which is implemented by public license practices. Many + people have made generous contributions to the wide range of + software distributed through that system in reliance on consistent + application of that system; it is up to the author/donor to + decide if he or she is willing to distribute software through + any other system and a licensee cannot impose that choice. + </p> + + <p> + This section is intended to make thoroughly clear what is + believed to be a consequence of the rest of this License. + </p> + + </li> +<li> + <var class="replacable-license-text">12.</var> + If the distribution and/or use of the Library is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Library under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this License + incorporates the limitation as if written in the body of this License. + </li> +<li> + <var class="replacable-license-text">13.</var> + The Free Software Foundation may publish revised and/or new versions + of the Library General Public License from time to time. Such + new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + <p> + Each version is given a distinguishing version number. If + the Library specifies a version number of this License which + applies to it and &quot;any later version&quot;, you have the option of + following the terms and conditions either of that version or of + any later version published by the Free Software Foundation. If + the Library does not specify a license version number, you may + choose any version ever published by the Free Software Foundation. + </p> + + </li> +<li> + <var class="replacable-license-text">14.</var> + If you wish to incorporate parts of the Library into other free programs + whose distribution conditions are incompatible with these, write to + the author to ask for permission. For software which is copyrighted by + the Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + <p> + NO WARRANTY + </p> + + </li> +<li> + <var class="replacable-license-text">15.</var> + BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT + WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER + PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, + EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF + THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU + ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + </li> +<li> + <var class="replacable-license-text">16.</var> + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF + THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER + OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + </li> +</ul> + <div class="optional-license-text"> + <p> + END OF TERMS AND CONDITIONS + </p> + + <p> + How to Apply These Terms to Your New Libraries + </p> + + <p> + If you develop a new library, and you want it to be of the greatest + possible use to the public, we recommend making it free software + that everyone can redistribute and change. You can do so by + permitting redistribution under these terms (or, alternatively, + under the terms of the ordinary General Public License). + </p> + + <p> + To apply these terms, attach the following notices to the + library. It is safest to attach them to the start of each + source file to most effectively convey the exclusion of + warranty; and each file should have at least the &quot;copyright&quot; + line and a pointer to where the full notice is found. + </p> + + <p> + one line to give the library&apos;s name + and an idea of what it does.<br /> + + Copyright (C) year name of author + </p> + + <p> + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + </p> + + <p> + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + the GNU Library General Public License for more details. + </p> + + <p> + You should have received a copy of the GNU Library + General Public License along with this library; if + not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + </p> + + <p> + Also add information on how to contact you by electronic and paper mail. + </p> + + <p> + You should also get your employer (if you work as a programmer) + or your school, if any, to sign a &quot;copyright disclaimer&quot; for + the library, if necessary. Here is a sample; alter the names: + </p> + + <p> + Yoyodyne, Inc., hereby disclaims all copyright interest in<br /> + + the library `Frob&apos; (a library for tweaking knobs) written<br /> + + by James Random Hacker. + </p> + + <p> + signature of Ty Coon, 1 April 1990<br /> + + Ty Coon, President of Vice + </p> + + <p> + That&apos;s all there is to it! + </p> + + </div> + + true + Copyright (C) year name of author + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + + + + + 0 + 2021-05-20 - 16:59:22 + https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html + true + false + true + true + + + This license was released: June 1991. This license has been superseded by LGPL-2.1. This license identifier refers to the choice to use the code under LGPL-2.0-only, as distinguished from use of code under LGPL-2.0-or-later (i.e., LGPL-2.0 or some later version). The license notice (as seen in the Standard License Header field below) states which of these applies to the code in the file. The example in the exhibit to the license shows the license notice for the "or later" approach. + GNU Library General Public License v2 only + Copyright (C) <<var;name="copyright";original="year name of author";match=".+">> + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + + + + + + + + + + 85ed0817af83a24ad8da68c2b5094de69833983c + + + The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. + + true + 2.11.1 + + + + 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd + + + + + /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + http://ftp.gnu.org/gnu/glibc + glibc + Person: Jane Doe (jane.doe@example.com) + + + + + + This license is used by Jena + Hewlett Packard Inc. + + (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + + + + + + + Apache Software Foundation + + + + 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 + + + + This file belongs to Jena + ./lib-source/jena-2.6.3-sources.jar + + + + + + + + + This is the external ref for Acme + + acmecorp/acmenator/4.1.3-alpha + + + + + + + + + The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. + Organization: ExampleCodeInspect (contact@example.com) + + + + This package includes the GRDDL parser developed by Hewlett Packard under the following license: +� Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + + + + + 624c1abb3664f4b35547e7c73864ad24 + + + + + Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) + + + + + + + + + Apache Software Foundation + + + + c2b4e1c67a2d28fced849ee1bb76e7391b93f125 + + + ./lib-source/commons-lang3-3.1-sources.jar + Copyright 2001-2011 The Apache Software Foundation + This file is used by Jena + + + + + + + + cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* + + + + + d6a770ba38583ed4bb4525bd96e50461655d2758 + ./package.spdx + + + + + Person: Package Commenter + Package level annotation + + 2011-01-29T18:30:22Z + + + + + + + Saxon + The Saxon package is a collection of tools for processing XML documents. + http://saxon.sourceforge.net/ + 8.8 + Other versions available for a commercial license + + + + 85ed0817af83a24ad8da68c2b5094de69833983c + + + https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download + saxonB-8.8.zip + + + https://opensource.org/licenses/MPL-1.0 + + <p><var class="optional-license-text">&quot;</var>The contents of this file are subject to the Mozilla Public License Version 1.0 (the + &quot;License&quot;); you may not use this file except in compliance with the License. You may obtain + a copy of the License at http://www.mozilla.org/MPL/</p> + + <p>Software distributed under the License is distributed on an &quot;AS IS&quot; basis, WITHOUT WARRANTY OF + ANY KIND, either express or implied. See the License for the specific language governing rights and + limitations under the License.</p> + + <p>The Original Code is + <var class="replacable-license-text">_____</var>. The Initial Developer of the Original Code is + <var class="replacable-license-text">_____</var>. Portions created by + <var class="replacable-license-text">_____</var> are Copyright (C) + <var class="replacable-license-text">_____</var>. All Rights Reserved. Contributor(s): + <var class="replacable-license-text">_____</var>.<var class="optional-license-text">&quot;</var> + </p> + + + MOZILLA PUBLIC LICENSE +Version 1.0 + +1. Definitions. + + 1.1. ``Contributor'' means each entity that creates or contributes to the creation of Modifications. + + 1.2. ``Contributor Version'' means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. + + 1.3. ``Covered Code'' means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. + + 1.4. ``Electronic Distribution Mechanism'' means a mechanism generally accepted in the software development community for the electronic transfer of data. + + 1.5. ``Executable'' means Covered Code in any form other than Source Code. + + 1.6. ``Initial Developer'' means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. + + 1.7. ``Larger Work'' means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. + + 1.8. ``License'' means this document. + + 1.9. ``Modifications'' means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: + + A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or previous Modifications. + + 1.10. ``Original Code'' means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. + + 1.11. ``Source Code'' means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. + + 1.12. ``You'' means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, ``You'' includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, ``control'' means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. +The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + (a) to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and + + (b) under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell (``Utilize'') the Original Code (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + + 2.2. Contributor Grant. +Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + (a) to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and + + (b) under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + + (a) Third Party Claims. + If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled ``LEGAL'' which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. +If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. + +5. Application of this License. +This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation (``Netscape'') may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. + + 6.3. Derivative Works. + If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases ``Mozilla'', ``MOZILLAPL'', ``MOZPL'', ``Netscape'', ``NPL'' or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) + +7. DISCLAIMER OF WARRANTY. +COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN ``AS IS'' BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. +This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. + +9. LIMITATION OF LIABILITY. +UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. +The Covered Code is a ``commercial item,'' as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of ``commercial computer software'' and ``commercial computer software documentation,'' as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. + +11. MISCELLANEOUS. +This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the United States of America: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Santa Clara County, California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. + +12. RESPONSIBILITY FOR CLAIMS. +Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute responsibility on an equitable basis. + +EXHIBIT A. + +``The contents of this file are subject to the Mozilla Public License Version 1.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.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is ______________________________________. + +The Initial Developer of the Original Code is ________________________. Portions created by ______________________ are Copyright (C) ______ _______________________. All Rights Reserved. + +Contributor(s): ______________________________________.'' + This license has been superseded by v1.1 + http://www.mozilla.org/MPL/MPL-1.0.html + + <div class="optional-license-text"> + <p>MOZILLA PUBLIC LICENSE + <br /> + +Version 1.0 + </p> + + </div> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">1.</var> + Definitions. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">1.1.</var> + &quot;Contributor&quot; means each entity that creates or contributes to the creation of + Modifications. + </li> +<li> + <var class="replacable-license-text">1.2.</var> + &quot;Contributor Version&quot; means the combination of the Original Code, prior + Modifications used by a Contributor, and the Modifications made by that particular + Contributor. + </li> +<li> + <var class="replacable-license-text">1.3.</var> + &quot;Covered Code&quot; means the Original Code or Modifications or the combination of the + Original Code and Modifications, in each case including portions thereof. + </li> +<li> + <var class="replacable-license-text">1.4.</var> + &quot;Electronic Distribution Mechanism&quot; means a mechanism generally accepted in the + software development community for the electronic transfer of data. + </li> +<li> + <var class="replacable-license-text">1.5.</var> + &quot;Executable&quot; means Covered Code in any form other than Source Code. + </li> +<li> + <var class="replacable-license-text">1.6.</var> + &quot;Initial Developer&quot; means the individual or entity identified as the Initial + Developer in the Source Code notice required by Exhibit A. + </li> +<li> + <var class="replacable-license-text">1.7.</var> + &quot;Larger Work&quot; means a work which combines Covered Code or portions thereof with + code not governed by the terms of this License. + </li> +<li> + <var class="replacable-license-text">1.8.</var> + &quot;License&quot; means this document. + </li> +<li> + <var class="replacable-license-text">1.9.</var> + &quot;Modifications&quot; means any addition to or deletion from the substance or structure + of either the Original Code or any previous Modifications. When Covered Code is released + as a series of files, a Modification is: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">A.</var> + Any addition to or deletion from the contents of a file containing Original Code or + previous Modifications. + </li> +<li> + <var class="replacable-license-text">B.</var> + Any new file that contains any part of the Original Code or previous Modifications. + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">1.10.</var> + &quot;Original Code&quot; means Source Code of computer software code which is described in + the Source Code notice required by Exhibit A as Original Code, and which, at the time of + its release under this License is not already Covered Code governed by this License. + </li> +<li> + <var class="replacable-license-text">1.11.</var> + &quot;Source Code&quot; means the preferred form of the Covered Code for making + modifications to it, including all modules it contains, plus any associated interface + definition files, scripts used to control compilation and installation of an Executable, + or a list of source code differential comparisons against either the Original Code or + another well known, available Covered Code of the Contributor&apos;s choice. The Source + Code can be in a compressed or archival form, provided the appropriate decompression or + de-archiving software is widely available for no charge. + </li> +<li> + <var class="replacable-license-text">1.12.</var> + &quot;You&quot; means an individual or a legal entity exercising rights under, and + complying with all of the terms of, this License or a future version of this License + issued under Section 6.1. For legal entities, &quot;You&quot; includes any entity which + controls, is controlled by, or is under common control with You. For purposes of this + definition, &quot;control&quot; means (a) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or otherwise, or (b) ownership + of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such + entity. + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">2.</var> + Source Code License. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">2.1.</var> + The Initial Developer Grant. + <br /> + + The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive + license, subject to third party intellectual property claims: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">(a)</var> + to use, reproduce, modify, display, perform, sublicense and distribute the Original Code + (or portions thereof) with or without Modifications, or as part of a Larger Work; + and + </li> +<li> + <var class="replacable-license-text">(b)</var> + under patents now or hereafter owned or controlled by Initial Developer, to make, have + made, use and sell (&quot;Utilize&quot;) the Original Code (or portions thereof), + but solely to the extent that any such patent is reasonably necessary to enable You to + Utilize the Original Code (or portions thereof) and not to any greater extent that may + be necessary to Utilize further Modifications or combinations. + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">2.2.</var> + Contributor Grant. + <br /> + + Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, + subject to third party intellectual property claims: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">(a)</var> + to use, reproduce, modify, display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an unmodified basis, with + other Modifications, as Covered Code or as part of a Larger Work; and + </li> +<li> + <var class="replacable-license-text">(b)</var> + under patents now or hereafter owned or controlled by Contributor, to Utilize the + Contributor Version (or portions thereof), but solely to the extent that any such + patent is reasonably necessary to enable You to Utilize the Contributor Version (or + portions thereof), and not to any greater extent that may be necessary to Utilize + further Modifications or combinations. + </li> +</ul> + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">3.</var> + Distribution Obligations. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">3.1.</var> + Application of License. + <br /> + + The Modifications which You create or to which You contribute are governed by the terms + of this License, including without limitation Section 2.2. The Source Code version + of Covered Code may be distributed only under the terms of this License or a + future version of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You distribute. You may + not offer or impose any terms on any Source Code version that alters or restricts + the applicable version of this License or the recipients&apos; rights hereunder. + However, You may include an additional document offering the additional rights + described in Section 3.5. + + </li> +<li> + <var class="replacable-license-text">3.2.</var> + Availability of Source Code. + <br /> + + Any Modification which You create or to which You contribute must be made available in + Source Code form under the terms of this License either on the same media as an + Executable version or via an accepted Electronic Distribution Mechanism to anyone + to whom you made an Executable version available; and if made available via + Electronic Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six (6) months + after a subsequent version of that particular Modification has been made available + to such recipients. You are responsible for ensuring that the Source Code version + remains available even if the Electronic Distribution Mechanism is maintained by a + third party. + + </li> +<li> + <var class="replacable-license-text">3.3.</var> + Description of Modifications. + <br /> + + You must cause all Covered Code to which you contribute to contain a file documenting + the changes You made to create that Covered Code and the date of any change. You + must include a prominent statement that the Modification is derived, directly or + indirectly, from Original Code provided by the Initial Developer and including the + name of the Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the origin or + ownership of the Covered Code. + + </li> +<li> + <var class="replacable-license-text">3.4.</var> + Intellectual Property Matters + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">(a)</var> + Third Party Claims. + <br /> + + If You have knowledge that a party claims an intellectual property right in + particular functionality or code (or its utilization under this License), you + must include a text file with the source code distribution titled + &quot;LEGAL&quot; which describes the claim and the party making the claim + in sufficient detail that a recipient will know whom to contact. If you obtain + such knowledge after You make Your Modification available as described in + Section 3.2, You shall promptly modify the LEGAL file in all copies You make + available thereafter and shall take other steps (such as notifying appropriate + mailing lists or newsgroups) reasonably calculated to inform those who + received the Covered Code that new knowledge has been obtained. + + </li> +<li> + <var class="replacable-license-text">(b)</var> + Contributor APIs. + <br /> + + If Your Modification is an application programming interface and You own or control + patents which are reasonably necessary to implement that API, you must also + include this information in the LEGAL file. + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">3.5.</var> + Required Notices. + <br /> + + You must duplicate the notice in Exhibit A in each file of the Source Code, and this + License in any documentation for the Source Code, where You describe + recipients&apos; rights relating to Covered Code. If You created one or more + Modification(s), You may add your name as a Contributor to the notice described in + Exhibit A. If it is not possible to put such notice in a particular Source Code + file due to its structure, then you must include such notice in a location (such + as a relevant directory file) where a user would be likely to look for such a + notice. You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered Code. + However, You may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than any such + warranty, support, indemnity or liability obligation is offered by You alone, and + You hereby agree to indemnify the Initial Developer and every Contributor for any + liability incurred by the Initial Developer or such Contributor as a result of + warranty, support, indemnity or liability terms You offer. + + </li> +<li> + <var class="replacable-license-text">3.6.</var> + Distribution of Executable Versions. + <br /> + + You may distribute Covered Code in Executable form only if the requirements of Section + 3.1-3.5 have been met for that Covered Code, and if You include a notice stating + that the Source Code version of the Covered Code is available under the terms of + this License, including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included in any + notice in an Executable version, related documentation or collateral in which You + describe recipients&apos; rights relating to the Covered Code. You may distribute + the Executable version of Covered Code under a license of Your choice, which may + contain terms different from this License, provided that You are in compliance + with the terms of this License and that the license for the Executable version + does not attempt to limit or alter the recipient&apos;s rights in the Source Code + version from the rights set forth in this License. If You distribute the + Executable version under a different license You must make it absolutely clear + that any terms which differ from this License are offered by You alone, not by the + Initial Developer or any Contributor. You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the Initial + Developer or such Contributor as a result of any such terms You offer. + + </li> +<li> + <var class="replacable-license-text">3.7.</var> + Larger Works. + <br /> + + You may create a Larger Work by combining Covered Code with other code not governed by + the terms of this License and distribute the Larger Work as a single product. In + such a case, You must make sure the requirements of this License are fulfilled for + the Covered Code. + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">4.</var> + Inability to Comply Due to Statute or Regulation. + <br /> + + If it is impossible for You to comply with any of the terms of this License with respect to + some or all of the Covered Code due to statute or regulation then You must: (a) comply + with the terms of this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be included in the LEGAL + file described in Section 3.4 and must be included with all distributions of the + Source Code. Except to the extent prohibited by statute or regulation, such + description must be sufficiently detailed for a recipient of ordinary skill to be able + to understand it. + + </li> +<li> + <var class="replacable-license-text">5.</var> + Application of this License. + <br /> + + This License applies to code to which the Initial Developer has attached the notice in + Exhibit A, and to related Covered Code. + + </li> +<li> + <var class="replacable-license-text">6.</var> + Versions of the License. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">6.1.</var> + New Versions. + <br /> + + Netscape Communications Corporation (&quot;Netscape&quot;) may publish revised and/or + new versions of the License from time to time. Each version will be given a + distinguishing version number. + + </li> +<li> + <var class="replacable-license-text">6.2.</var> + Effect of New Versions. + <br /> + + Once Covered Code has been published under a particular version of the License, You may + always continue to use it under the terms of that version. You may also choose to + use such Covered Code under the terms of any subsequent version of the License + published by Netscape. No one other than Netscape has the right to modify the + terms applicable to Covered Code created under this License. + + </li> +<li> + <var class="replacable-license-text">6.3.</var> + Derivative Works. + <br /> + + If you create or use a modified version of this License (which you may only do in order + to apply it to code which is not already Covered Code governed by this License), + you must (a) rename Your license so that the phrases &quot;Mozilla&quot;, + &quot;MOZILLAPL&quot;, &quot;MOZPL&quot;, &quot;Netscape&quot;, + &quot;NPL&quot; or any confusingly similar phrase do not appear anywhere in your + license and (b) otherwise make it clear that your version of the license contains + terms which differ from the Mozilla Public License and Netscape Public License. + (Filling in the name of the Initial Developer, Original Code or Contributor in the + notice described in Exhibit A shall not of themselves be deemed to be + modifications of this License.) + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">7.</var> + DISCLAIMER OF WARRANTY. + <br /> + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN &quot;AS IS&quot; BASIS, WITHOUT + WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, + WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A + PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND + PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE + IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY + CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS + AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + + </li> +<li> + <var class="replacable-license-text">8.</var> + TERMINATION. + <br /> + + This License and the rights granted hereunder will terminate automatically if You fail to + comply with terms herein and fail to cure such breach within 30 days of becoming aware + of the breach. All sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their nature, must + remain in effect beyond the termination of this License shall survive. + + </li> +<li> + <var class="replacable-license-text">9.</var> + LIMITATION OF LIABILITY. + <br /> + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), + CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY + DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU + OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF + ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK + STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR + LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH + DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR + PERSONAL INJURY RESULTING FROM SUCH PARTY&apos;S NEGLIGENCE TO THE EXTENT APPLICABLE + LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR + LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION + MAY NOT APPLY TO YOU. + + </li> +<li> + <var class="replacable-license-text">10.</var> + U.S. GOVERNMENT END USERS. + <br /> + + The Covered Code is a &quot;commercial item,&quot; as that term is defined in 48 C.F.R. + 2.101 (Oct. 1995), consisting of &quot;commercial computer software&quot; and + &quot;commercial computer software documentation,&quot; as such terms are used in 48 + C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 + through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code + with only those rights set forth herein. + + </li> +<li> + <var class="replacable-license-text">11.</var> + MISCELLANEOUS. + <br /> + + This License represents the complete agreement concerning subject matter hereof. If any + provision of this License is held to be unenforceable, such provision shall be + reformed only to the extent necessary to make it enforceable. This License shall be + governed by California law provisions (except to the extent applicable law, if any, + provides otherwise), excluding its conflict-of-law provisions. With respect to + disputes in which at least one party is a citizen of, or an entity chartered or + registered to do business in, the United States of America: (a) unless otherwise + agreed in writing, all disputes relating to this License (excepting any dispute + relating to intellectual property rights) shall be subject to final and binding + arbitration, with the losing party paying all costs of arbitration; (b) any + arbitration relating to this Agreement shall be held in Santa Clara County, + California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to + this Agreement shall be subject to the jurisdiction of the Federal Courts of the + Northern District of California, with venue lying in Santa Clara County, California, + with the losing party responsible for costs, including without limitation, court costs + and reasonable attorneys fees and expenses. The application of the United Nations + Convention on Contracts for the International Sale of Goods is expressly excluded. Any + law or regulation which provides that the language of a contract shall be construed + against the drafter shall not apply to this License. + + </li> +<li> + <var class="replacable-license-text">12.</var> + RESPONSIBILITY FOR CLAIMS. + <br /> + + Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for + damages arising, directly or indirectly, out of Your utilization of rights under this License, based + on the number of copies of Covered Code you made available, the revenues you received from utilizing + such rights, and other relevant factors. You agree to work with affected parties to distribute + responsibility on an equitable basis. + </li> +</ul> + <div class="optional-license-text"> + <p>EXHIBIT A.</p> + + <p><var class="optional-license-text">&quot;</var>The contents of this file are subject to the Mozilla Public License Version 1.0 (the + &quot;License&quot;); you may not use this file except in compliance with the License. You may obtain + a copy of the License at http://www.mozilla.org/MPL/</p> + + <p>Software distributed under the License is distributed on an &quot;AS IS&quot; basis, WITHOUT WARRANTY OF + ANY KIND, either express or implied. See the License for the specific language governing rights and + limitations under the License.</p> + + <p>The Original Code is + <var class="replacable-license-text">_____</var>. The Initial Developer of the Original Code is + <var class="replacable-license-text">_____</var>. Portions created by + <var class="replacable-license-text">_____</var> are Copyright (C) + <var class="replacable-license-text">_____</var>. All Rights Reserved. Contributor(s): + <var class="replacable-license-text">_____</var>.<var class="optional-license-text">&quot;</var> + </p> + + </div> + + + + 0 + 2021-05-20 - 16:53:35 + http://www.mozilla.org/MPL/MPL-1.0.html + true + false + true + true + + + Mozilla Public License 1.0 + "The contents of this file are subject to the Mozilla Public License Version 1.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.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is _____ . The Initial Developer of the Original Code is _____ . Portions created by _____ are Copyright (C) _____ . All Rights Reserved. Contributor(s): _____ ." + + + <<beginOptional>>"<<endOptional>>The contents of this file are subject to the Mozilla Public License Version 1.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.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is <<var;name="code";original="_____";match=".+">> . The Initial Developer of the Original Code is <<var;name="InitialDeveloper";original="_____";match=".+">> . Portions created by <<var;name="createdby";original="_____";match=".+">> are Copyright (C) <<var;name="copyright";original="_____";match=".+">> . All Rights Reserved. Contributor(s): <<var;name="contributor";original="_____";match=".+">> .<<beginOptional>>"<<endOptional>> + + + true + <<beginOptional>> MOZILLA PUBLIC LICENSE + +Version 1.0 + +<<endOptional>> + + <<var;name="bullet";original="1.";match=".{0,20}">> Definitions. + + <<var;name="bullet";original="1.1.";match=".{0,20}">> "Contributor" means each entity that creates or contributes to the creation of Modifications. + + <<var;name="bullet";original="1.2.";match=".{0,20}">> "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. + + <<var;name="bullet";original="1.3.";match=".{0,20}">> "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. + + <<var;name="bullet";original="1.4.";match=".{0,20}">> "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. + + <<var;name="bullet";original="1.5.";match=".{0,20}">> "Executable" means Covered Code in any form other than Source Code. + + <<var;name="bullet";original="1.6.";match=".{0,20}">> "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. + + <<var;name="bullet";original="1.7.";match=".{0,20}">> "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. + + <<var;name="bullet";original="1.8.";match=".{0,20}">> "License" means this document. + + <<var;name="bullet";original="1.9.";match=".{0,20}">> "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: + + <<var;name="bullet";original="A.";match=".{0,20}">> Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. + + <<var;name="bullet";original="B.";match=".{0,20}">> Any new file that contains any part of the Original Code or previous Modifications. + + <<var;name="bullet";original="1.10.";match=".{0,20}">> "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. + + <<var;name="bullet";original="1.11.";match=".{0,20}">> "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. + + <<var;name="bullet";original="1.12.";match=".{0,20}">> "You" means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. + + <<var;name="bullet";original="2.";match=".{0,20}">> Source Code License. + + <<var;name="bullet";original="2.1.";match=".{0,20}">> The Initial Developer Grant. + + The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + <<var;name="bullet";original="(a)";match=".{0,20}">> to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and + + <<var;name="bullet";original="(b)";match=".{0,20}">> under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell ("Utilize") the Original Code (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + + <<var;name="bullet";original="2.2.";match=".{0,20}">> Contributor Grant. + + Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + <<var;name="bullet";original="(a)";match=".{0,20}">> to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and + + <<var;name="bullet";original="(b)";match=".{0,20}">> under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + + <<var;name="bullet";original="3.";match=".{0,20}">> Distribution Obligations. + + <<var;name="bullet";original="3.1.";match=".{0,20}">> Application of License. + + The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. + + <<var;name="bullet";original="3.2.";match=".{0,20}">> Availability of Source Code. + + Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. + + <<var;name="bullet";original="3.3.";match=".{0,20}">> Description of Modifications. + + You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. + + <<var;name="bullet";original="3.4.";match=".{0,20}">> Intellectual Property Matters + + <<var;name="bullet";original="(a)";match=".{0,20}">> Third Party Claims. + + If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. + + <<var;name="bullet";original="(b)";match=".{0,20}">> Contributor APIs. + + If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file. + + <<var;name="bullet";original="3.5.";match=".{0,20}">> Required Notices. + + You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. + + <<var;name="bullet";original="3.6.";match=".{0,20}">> Distribution of Executable Versions. + + You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. + + <<var;name="bullet";original="3.7.";match=".{0,20}">> Larger Works. + + You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. + + <<var;name="bullet";original="4.";match=".{0,20}">> Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. + + <<var;name="bullet";original="5.";match=".{0,20}">> Application of this License. + + This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code. + + <<var;name="bullet";original="6.";match=".{0,20}">> Versions of the License. + + <<var;name="bullet";original="6.1.";match=".{0,20}">> New Versions. + + Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. + + <<var;name="bullet";original="6.2.";match=".{0,20}">> Effect of New Versions. + + Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. + + <<var;name="bullet";original="6.3.";match=".{0,20}">> Derivative Works. + + If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "NPL" or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) + + <<var;name="bullet";original="7.";match=".{0,20}">> DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + + <<var;name="bullet";original="8.";match=".{0,20}">> TERMINATION. + + This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. + + <<var;name="bullet";original="9.";match=".{0,20}">> LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + + <<var;name="bullet";original="10.";match=".{0,20}">> U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. + + <<var;name="bullet";original="11.";match=".{0,20}">> MISCELLANEOUS. + + This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the United States of America: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Santa Clara County, California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. + + <<var;name="bullet";original="12.";match=".{0,20}">> RESPONSIBILITY FOR CLAIMS. + + Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute responsibility on an equitable basis.<<beginOptional>> EXHIBIT A. + +<<beginOptional>>"<<endOptional>>The contents of this file are subject to the Mozilla Public License Version 1.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.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is <<var;name="code";original="_____";match=".+">> . The Initial Developer of the Original Code is <<var;name="InitialDeveloper";original="_____";match=".+">> . Portions created by <<var;name="createdby";original="_____";match=".+">> are Copyright (C) <<var;name="copyright";original="_____";match=".+">> . All Rights Reserved. Contributor(s): <<var;name="contributor";original="_____";match=".+">> .<<beginOptional>>"<<endOptional>> + +<<endOptional>> + + + 1 + 2021-05-20 - 16:53:36 + https://opensource.org/licenses/MPL-1.0 + true + false + true + true + + + false + MPL-1.0 + + + false + Copyright Saxonica Ltd + + + + + + + uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. + glibc-2.11.1.tar.gz + GNU C library. + Copyright 2008-2010 John Smith + The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. + + + + + + + + + + ./package/foo.c + The concluded license was taken from the package level that the file was included in. + + + + + 624c1abb3664f4b35547e7c73864ad24 + + + + + + d6a770ba38583ed4bb4525bd96e50461655d2758 + + + + Copyright 2008-2010 John Smith + The Regents of the University of California + Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the �Software�), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED �AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + + + + + + pkg:maven/org.apache.jena/apache-jena@3.12.0 + + + + + Jena + 3.12.0 + https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz + http://www.openjena.org/ + false + NOASSERTION + + + + + + + + Person: File Commenter + File level annotation + + 2011-01-29T18:30:22Z + + + Modified by Paul Mundt lethal@linux-sh.org + + + + + + + + IBM Corporation + The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. + + + + + + + + This package has been shipped in source and binary form. +The binaries were created with gcc 4.5.1 and expect to link to +compatible system run time libraries. + 2010-01-29T18:30:22Z + Person: Jane Doe () + Organization: ExampleCodeInspect () + Tool: LicenseFind-1.0 + 3.9 + + + SPDX-2.2 + + + false + true + false + + + 0 + 2021-05-20 - 16:55:09 + https://creativecommons.org/publicdomain/zero/1.0/legalcode + false + false + true + true + + + + <div class="optional-license-text"> + <div class="optional-license-text"> + <p>Creative Commons<var class="optional-license-text"> Legal Code</var></p> + + </div> + <p>CC0 1.0 Universal</p> + + </div> + <div class="optional-license-text"> + <p>CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS + DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION + ON AN &quot;AS-IS&quot; BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT + OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE + USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.</p> + + </div> + + <p>Statement of Purpose</p> + + <p>The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related + Rights (defined below) upon the creator and subsequent owner(s) (each and all, an &quot;owner&quot;) + of an original work of authorship and/or a database (each, a &quot;Work&quot;).</p> + + <p>Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a + commons of creative, cultural and scientific works (&quot;Commons&quot;) that the public can reliably + and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse + and redistribute as freely as possible in any form whatsoever and for any purposes, including without + limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a + free culture and the further production of creative, cultural and scientific works, or to gain + reputation or greater distribution for their Work in part through the use and efforts of others.</p> + + <p>For these and/or other purposes and motivations, and without any expectation of additional consideration + or compensation, the person associating CC0 with a Work (the &quot;Affirmer&quot;), to the extent that + he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to + the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and + Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.</p> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">1.</var> + Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and + related or neighboring rights (&quot;Copyright and Related Rights&quot;). Copyright and + Related Rights include, but are not limited to, the following: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">i.</var> + the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + </li> +<li> + <var class="replacable-license-text">ii.</var> + moral rights retained by the original author(s) and/or performer(s); + </li> +<li> + <var class="replacable-license-text">iii.</var> + publicity and privacy rights pertaining to a person&apos;s image or likeness depicted in a Work; + </li> +<li> + <var class="replacable-license-text">iv.</var> + rights protecting against unfair competition in regards to a Work, subject to the limitations + in paragraph 4(a), below; + </li> +<li> + <var class="replacable-license-text">v.</var> + rights protecting the extraction, dissemination, use and reuse of data in a Work; + </li> +<li> + <var class="replacable-license-text">vi.</var> + database rights (such as those arising under Directive 96/9/EC of the European Parliament and + of the Council of 11 March 1996 on the legal protection of databases, and under any + national implementation thereof, including any amended or successor version of such + directive); and + </li> +<li> + <var class="replacable-license-text">vii.</var> + other similar, equivalent or corresponding rights throughout the world based on applicable + law or treaty, and any national implementations thereof. + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">2.</var> + Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, + Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, + and surrenders all of Affirmer&apos;s Copyright and Related Rights and associated claims and + causes of action, whether now known or unknown (including existing as well as future claims + and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum + duration provided by applicable law or treaty (including future time extensions), (iii) in any + current or future medium and for any number of copies, and (iv) for any purpose whatsoever, + including without limitation commercial, advertising or promotional purposes (the + &quot;Waiver&quot;). Affirmer makes the Waiver for the benefit of each member of the public at + large and to the detriment of Affirmer&apos;s heirs and successors, fully intending that such + Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other + legal or equitable action to disrupt the quiet enjoyment of the Work by the public as + contemplated by Affirmer&apos;s express Statement of Purpose. + </li> +<li> + <var class="replacable-license-text">3.</var> + Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid + or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent + permitted taking into account Affirmer&apos;s express Statement of Purpose. In addition, to + the extent the Waiver is so judged Affirmer hereby grants to each affected person a + royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and + unconditional license to exercise Affirmer&apos;s Copyright and Related Rights in the Work (i) + in all territories worldwide, (ii) for the maximum duration provided by applicable law or + treaty (including future time extensions), (iii) in any current or future medium and for any + number of copies, and (iv) for any purpose whatsoever, including without limitation + commercial, advertising or promotional purposes (the &quot;License&quot;). The License shall + be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of + the License for any reason be judged legally invalid or ineffective under applicable law, such + partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and + in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her + remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and + causes of action with respect to the Work, in either case contrary to Affirmer&apos;s express + Statement of Purpose. + </li> +<li> + <var class="replacable-license-text">4.</var> + Limitations and Disclaimers. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a.</var> + No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed + or otherwise affected by this document. + </li> +<li> + <var class="replacable-license-text">b.</var> + Affirmer offers the Work as-is and makes no representations or warranties of any kind + concerning the Work, express, implied, statutory or otherwise, including without + limitation warranties of title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or the present or + absence of errors, whether or not discoverable, all to the greatest extent permissible + under applicable law. + </li> +<li> + <var class="replacable-license-text">c.</var> + Affirmer disclaims responsibility for clearing rights of other persons that may apply to the + Work or any use thereof, including without limitation any person&apos;s Copyright and + Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any + necessary consents, permissions or other rights required for any use of the Work. + </li> +<li> + <var class="replacable-license-text">d.</var> + Affirmer understands and acknowledges that Creative Commons is not a party to this document + and has no duty or obligation with respect to this CC0 or use of the Work. + </li> +</ul> + </li> +</ul> + <var class="optional-license-text"><var class="replacable-license-text"></var></var> + + <<beginOptional>> <<beginOptional>> Creative Commons<<beginOptional>> Legal Code<<endOptional>> + +<<endOptional>> + +CC0 1.0 Universal + +<<endOptional>><<beginOptional>> CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. + +<<endOptional>> + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. + + <<var;name="bullet";original="1.";match=".{0,20}">> Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: + + <<var;name="bullet";original="i.";match=".{0,20}">> the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + + <<var;name="bullet";original="ii.";match=".{0,20}">> moral rights retained by the original author(s) and/or performer(s); + + <<var;name="bullet";original="iii.";match=".{0,20}">> publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; + + <<var;name="bullet";original="iv.";match=".{0,20}">> rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; + + <<var;name="bullet";original="v.";match=".{0,20}">> rights protecting the extraction, dissemination, use and reuse of data in a Work; + + <<var;name="bullet";original="vi.";match=".{0,20}">> database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and + + <<var;name="bullet";original="vii.";match=".{0,20}">> other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. + + <<var;name="bullet";original="2.";match=".{0,20}">> Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. + + <<var;name="bullet";original="3.";match=".{0,20}">> Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. + + <<var;name="bullet";original="4.";match=".{0,20}">> Limitations and Disclaimers. + + <<var;name="bullet";original="a.";match=".{0,20}">> No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. + + <<var;name="bullet";original="b.";match=".{0,20}">> Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. + + <<var;name="bullet";original="c.";match=".{0,20}">> Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. + + <<var;name="bullet";original="d.";match=".{0,20}">> Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.<<beginOptional>> <<var;name="upstreamLink";original="";match="For more information, please see <http://creativecommons.org/publicdomain/zero/1.0/>">><<endOptional>> + Creative Commons Zero v1.0 Universal + CC0-1.0 + Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + + https://creativecommons.org/publicdomain/zero/1.0/legalcode + + + + + + http://people.freebsd.org/~phk/ + The beerware license has a couple of other standard variants. + "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp + Beer-Ware License (Version 42) + + + + + Person: Joe Reviewer + This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses + + 2010-02-10T00:00:00Z + + + + + + + + + d6a770ba38583ed4bb4525bd96e50461655d2759 + + + + + + + /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + + + + + + + + This document was created using SPDX 2.0 using licenses from the web site. + + + + + + + + + Person: Suzanne Reviewer + Another example reviewer. + + 2011-03-13T00:00:00Z + + + SPDX-Tools-v2.0 + + + Person: Jane Doe () + Document level annotation + + 2010-01-29T18:30:22Z + + + + + + http://commons.apache.org/proper/commons-lang/ + NOASSERTION + + NOASSERTION + Apache Commons Lang + + false + + diff --git a/tests/spdx/data/SPDXRdfExample-v2.3.spdx.rdf.xml b/tests/spdx/data/SPDXRdfExample-v2.3.spdx.rdf.xml new file mode 100644 index 000000000..cd70429a3 --- /dev/null +++ b/tests/spdx/data/SPDXRdfExample-v2.3.spdx.rdf.xml @@ -0,0 +1,4339 @@ + + + from linux kernel + Copyright 2008-2010 John Smith + The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. + + + + + + 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 + + + Copyright 2010, 2011 Source Auditor Inc. + Open Logic Inc. + ./src/org/spdx/parser/DOAPProject.java + Black Duck Software In.c + Source Auditor Inc. + SPDX Technical Team Members + + + <<beginOptional>>Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +<<endOptional>><<beginOptional>> TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +<<endOptional>> + + <<var;name="bullet";original="1.";match=".{0,20}">> Definitions. + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + <<var;name="bullet";original="2.";match=".{0,20}">> Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + <<var;name="bullet";original="3.";match=".{0,20}">> Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + <<var;name="bullet";original="4.";match=".{0,20}">> Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + <<var;name="bullet";original="(a)";match=".{0,20}">> You must give any other recipients of the Work or Derivative Works a copy of this License; and + + <<var;name="bullet";original="(b)";match=".{0,20}">> You must cause any modified files to carry prominent notices stating that You changed the files; and + + <<var;name="bullet";original="(c)";match=".{0,20}">> You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + <<var;name="bullet";original="(d)";match=".{0,20}">> If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + <<var;name="bullet";original="5.";match=".{0,20}">> Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + <<var;name="bullet";original="6.";match=".{0,20}">> Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + <<var;name="bullet";original="7.";match=".{0,20}">> Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + <<var;name="bullet";original="8.";match=".{0,20}">> Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + <<var;name="bullet";original="9.";match=".{0,20}">> Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.<<beginOptional>> END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright <<var;name="copyright";original="[yyyy] [name of copyright owner]";match=".+">> + +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. + +<<endOptional>> + This license was released January 2004 + Apache License 2.0 + + <p>Copyright <var class="replacable-license-text"> [yyyy] [name of copyright owner]</var></p> + + <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); + <br /> + +you may not use this file except in compliance with the License. + <br /> + +You may obtain a copy of the License at + </p> + + <p>http://www.apache.org/licenses/LICENSE-2.0</p> + + <p>Unless required by applicable law or agreed to in writing, software + <br /> + +distributed under the License is distributed on an &quot;AS IS&quot; BASIS, + <br /> + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + <br /> + +See the License for the specific language governing permissions and + <br /> + +limitations under the License. + </p> + + + https://www.apache.org/licenses/LICENSE-2.0 + Copyright [yyyy] [name of copyright owner] + +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. + + + Copyright <<var;name="copyright";original="[yyyy] [name of copyright owner]";match=".+">> + +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. + + + + <div class="optional-license-text"> + <p>Apache License + <br /> + +Version 2.0, January 2004 + <br /> + +http://www.apache.org/licenses/ + </p> + + </div> + <div class="optional-license-text"> + <p>TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION</p> + + </div> + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> 1.</var> + Definitions. + +<ul style="list-style:none"> + +<li> + <p>&quot;License&quot; shall mean the terms and conditions for use, reproduction, and distribution + as defined by Sections 1 through 9 of this document.</p> + + </li> + +<li> + <p>&quot;Licensor&quot; shall mean the copyright owner or entity authorized by the copyright owner + that is granting the License.</p> + + </li> + +<li> + <p>&quot;Legal Entity&quot; shall mean the union of the acting entity and all other entities that + control, are controlled by, or are under common control with that entity. For the purposes of + this definition, &quot;control&quot; means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or otherwise, or (ii) ownership of + fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such + entity.</p> + + </li> + +<li> + <p>&quot;You&quot; (or &quot;Your&quot;) shall mean an individual or Legal Entity exercising + permissions granted by this License.</p> + + </li> + +<li> + <p>&quot;Source&quot; form shall mean the preferred form for making modifications, including but not + limited to software source code, documentation source, and configuration files.</p> + + </li> + +<li> + <p>&quot;Object&quot; form shall mean any form resulting from mechanical transformation or + translation of a Source form, including but not limited to compiled object code, generated + documentation, and conversions to other media types.</p> + + </li> + +<li> + <p>&quot;Work&quot; shall mean the work of authorship, whether in Source or Object form, made + available under the License, as indicated by a copyright notice that is included in or + attached to the work (an example is provided in the Appendix below).</p> + + </li> + +<li> + <p>&quot;Derivative Works&quot; shall mean any work, whether in Source or Object form, that is based + on (or derived from) the Work and for which the editorial revisions, annotations, + elaborations, or other modifications represent, as a whole, an original work of authorship. + For the purposes of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative + Works thereof.</p> + + </li> + +<li> + <p>&quot;Contribution&quot; shall mean any work of authorship, including the original version of the + Work and any modifications or additions to that Work or Derivative Works thereof, that is + intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an + individual or Legal Entity authorized to submit on behalf of the copyright owner. For the + purposes of this definition, &quot;submitted&quot; means any form of electronic, verbal, or + written communication sent to the Licensor or its representatives, including but not limited + to communication on electronic mailing lists, source code control systems, and issue tracking + systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and + improving the Work, but excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as &quot;Not a Contribution.&quot;</p> + + </li> + +<li> + <p>&quot;Contributor&quot; shall mean Licensor and any individual or Legal Entity on behalf of whom + a Contribution has been received by Licensor and subsequently incorporated within the + Work.</p> + + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 2.</var> + Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor + hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or + Object form. + </li> + +<li> + <var class="replacable-license-text"> 3.</var> + Grant of Patent License. Subject to the terms and conditions of this License, each Contributor + hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + irrevocable (except as stated in this section) patent license to make, have made, use, offer + to sell, sell, import, and otherwise transfer the Work, where such license applies only to + those patent claims licensable by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) with the Work to which such + Contribution(s) was submitted. If You institute patent litigation against any entity + (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a + Contribution incorporated within the Work constitutes direct or contributory patent + infringement, then any patent licenses granted to You under this License for that Work shall + terminate as of the date such litigation is filed. + </li> + +<li> + <var class="replacable-license-text"> 4.</var> + Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof + in any medium, with or without modifications, and in Source or Object form, provided that You + meet the following conditions: + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> (a)</var> + You must give any other recipients of the Work or Derivative Works a copy of this License; and + </li> + +<li> + <var class="replacable-license-text"> (b)</var> + You must cause any modified files to carry prominent notices stating that You changed the files; and + </li> + +<li> + <var class="replacable-license-text"> (c)</var> + You must retain, in the Source form of any Derivative Works that You distribute, all + copyright, patent, trademark, and attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of the Derivative Works; and + </li> + +<li> + <var class="replacable-license-text"> (d)</var> + If the Work includes a &quot;NOTICE&quot; text file as part of its distribution, then any + Derivative Works that You distribute must include a readable copy of the attribution + notices contained within such NOTICE file, excluding those notices that do not pertain to + any part of the Derivative Works, in at least one of the following places: within a NOTICE + text file distributed as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, within a display generated + by the Derivative Works, if and wherever such third-party notices normally appear. The + contents of the NOTICE file are for informational purposes only and do not modify the + License. You may add Your own attribution notices within Derivative Works that You + distribute, alongside or as an addendum to the NOTICE text from the Work, provided that + such additional attribution notices cannot be construed as modifying the License. + <p>You may add Your own copyright statement to Your modifications and may provide additional or + different license terms and conditions for use, reproduction, or distribution of Your + modifications, or for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with the conditions stated + in this License.</p> + + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 5.</var> + Submission of Contributions. Unless You explicitly state otherwise, any Contribution + intentionally submitted for inclusion in the Work by You to the Licensor shall be under the + terms and conditions of this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate + license agreement you may have executed with Licensor regarding such Contributions. + </li> + +<li> + <var class="replacable-license-text"> 6.</var> + Trademarks. This License does not grant permission to use the trade names, trademarks, service + marks, or product names of the Licensor, except as required for reasonable and customary use + in describing the origin of the Work and reproducing the content of the NOTICE file. + </li> + +<li> + <var class="replacable-license-text"> 7.</var> + Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor + provides the Work (and each Contributor provides its Contributions) on an &quot;AS IS&quot; + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, + without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, + or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any risks associated with Your + exercise of permissions under this License. + </li> + +<li> + <var class="replacable-license-text"> 8.</var> + Limitation of Liability. In no event and under no legal theory, whether in tort (including + negligence), contract, or otherwise, unless required by applicable law (such as deliberate and + grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for + damages, including any direct, indirect, special, incidental, or consequential damages of any + character arising as a result of this License or out of the use or inability to use the Work + (including but not limited to damages for loss of goodwill, work stoppage, computer failure or + malfunction, or any and all other commercial damages or losses), even if such Contributor has + been advised of the possibility of such damages. + </li> + +<li> + <var class="replacable-license-text"> 9.</var> + Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works + thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, + indemnity, or other liability obligations and/or rights consistent with this License. However, + in accepting such obligations, You may act only on Your own behalf and on Your sole + responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability incurred by, or claims asserted + against, such Contributor by reason of your accepting any such warranty or additional + liability. + </li> + +</ul> + + <div class="optional-license-text"> + <p>END OF TERMS AND CONDITIONS</p> + + <p>APPENDIX: How to apply the Apache License to your work.</p> + + <p>To apply the Apache License to your work, attach the following boilerplate notice, with the fields + enclosed by brackets &quot;[]&quot; replaced with your own identifying information. (Don&apos;t + include the brackets!) The text should be enclosed in the appropriate comment syntax for the file + format. We also recommend that a file or class name and description of purpose be included on the same + &quot;printed page&quot; as the copyright notice for easier identification within third-party + archives.</p> + + <p>Copyright <var class="replacable-license-text"> [yyyy] [name of copyright owner]</var></p> + + <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); + <br /> + +you may not use this file except in compliance with the License. + <br /> + +You may obtain a copy of the License at + </p> + + <p>http://www.apache.org/licenses/LICENSE-2.0</p> + + <p>Unless required by applicable law or agreed to in writing, software + <br /> + +distributed under the License is distributed on an &quot;AS IS&quot; BASIS, + <br /> + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + <br /> + +See the License for the specific language governing permissions and + <br /> + +limitations under the License. + </p> + + </div> + + true + true + https://opensource.org/licenses/Apache-2.0 + + + 1 + 2022-08-12T00:16:54Z + https://opensource.org/licenses/Apache-2.0 + N/A + false + true + false + + + + + 0 + 2022-08-12T00:16:53Z + https://www.apache.org/licenses/LICENSE-2.0 + true + false + true + true + + + false + Apache-2.0 + Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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. + + + + Protecode Inc. + + + + + + + <<beginOptional>>GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +<<endOptional>> + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. <<var;name="incComma";original="";match=",|">> + +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<<beginOptional>>, <<endOptional>> USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +<<var;name="termsTitle";original="";match="GNU GENERAL PUBLIC LICENSE|">> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + <<var;name="bullet";original="0.";match=".{0,20}">> This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + + <<var;name="bullet";original="1.";match=".{0,20}">> You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + + You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + + <<var;name="bullet";original="2.";match=".{0,20}">> You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + <<var;name="bullet";original="a)";match=".{0,20}">> You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + <<var;name="bullet";original="b)";match=".{0,20}">> You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + <<var;name="bullet";original="c)";match=".{0,20}">> If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + + <<var;name="bullet";original="3.";match=".{0,20}">> You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + <<var;name="bullet";original="a)";match=".{0,20}">> Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + <<var;name="bullet";original="b)";match=".{0,20}">> Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + <<var;name="bullet";original="c)";match=".{0,20}">> Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + + If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + + <<var;name="bullet";original="4.";match=".{0,20}">> You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + + <<var;name="bullet";original="5.";match=".{0,20}">> You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + + <<var;name="bullet";original="6.";match=".{0,20}">> Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + + <<var;name="bullet";original="7.";match=".{0,20}">> If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + + <<var;name="bullet";original="8.";match=".{0,20}">> If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + + <<var;name="bullet";original="9.";match=".{0,20}">> The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + + <<var;name="bullet";original="10.";match=".{0,20}">> If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + <<var;name="bullet";original="11.";match=".{0,20}">> BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + <<var;name="bullet";original="12.";match=".{0,20}">> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.<<beginOptional>> END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +<<beginOptional>><<<endOptional>>one line to give the program's name and <<var;name="ideaArticle";original="an";match="a brief|an">> idea of what it does.<<beginOptional>>><<endOptional>> + +Copyright (C)<<beginOptional>><<<endOptional>> <<var;name="templateYear";original="yyyy";match="yyyy|year">><<beginOptional>>> <<endOptional>><<beginOptional>> <<<endOptional>>name of author<<beginOptional>>><<endOptional>> + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<<beginOptional>>, <<endOptional>> USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +<<beginOptional>><<<endOptional>>signature of Ty Coon<<beginOptional>> ><<endOptional>>, 1 April 1989 Ty Coon, President of Vice + +<<endOptional>><<beginOptional>> This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. + +<<endOptional>> + https://opensource.org/licenses/GPL-2.0 + This license was released: June 1991. This license identifier refers to the choice to use the code under GPL-2.0-only, as distinguished from use of code under GPL-2.0-or-later (i.e., GPL-2.0 or some later version). The license notice (as seen in the Standard License Header field below) states which of these applies to the code in the file. The example in the exhibit to the license shows the license notice for the "or later" approach. + GPL-2.0-only + https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + true + + + 1 + 2022-08-12T00:23:31Z + https://opensource.org/licenses/GPL-2.0 + N/A + false + true + false + + + Copyright (C) <<var;name="copyright";original="yyyy name of author";match=".+">> + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<<beginOptional>>, <<endOptional>> USA. + + + false + GNU General Public License v2.0 only + + <div class="optional-license-text"> + <p> + GNU GENERAL PUBLIC LICENSE<br /> + + Version 2, June 1991 + </p> + + </div> + <p> + Copyright (C) 1989, 1991 Free Software Foundation, Inc.<var class="replacable-license-text"> </var><br /> + + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<var class="optional-license-text">, </var> + USA + </p> + + <p> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + </p> + + <p> + Preamble + </p> + + <p> + The licenses for most software are designed to take away your freedom + to share and change it. By contrast, the GNU General Public License is + intended to guarantee your freedom to share and change free software--to + make sure the software is free for all its users. This General Public + License applies to most of the Free Software Foundation&apos;s software + and to any other program whose authors commit to using it. (Some other + Free Software Foundation software is covered by the GNU Lesser General + Public License instead.) You can apply it to your programs, too. + </p> + + <p> + When we speak of free software, we are referring to freedom, not price. + Our General Public Licenses are designed to make sure that you have + the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get + it if you want it, that you can change the software or use pieces of + it in new free programs; and that you know you can do these things. + </p> + + <p> + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the + rights. These restrictions translate to certain responsibilities for + you if you distribute copies of the software, or if you modify it. + </p> + + <p> + For example, if you distribute copies of such a program, whether gratis + or for a fee, you must give the recipients all the rights that you + have. You must make sure that they, too, receive or can get the source + code. And you must show them these terms so they know their rights. + </p> + + <p> + We protect your rights with two steps: (1) copyright the + software, and (2) offer you this license which gives you legal + permission to copy, distribute and/or modify the software. + </p> + + <p> + Also, for each author&apos;s protection and ours, we want to make + certain that everyone understands that there is no warranty for + this free software. If the software is modified by someone else + and passed on, we want its recipients to know that what they + have is not the original, so that any problems introduced by + others will not reflect on the original authors&apos; reputations. + </p> + + <p> + Finally, any free program is threatened constantly by software patents. + We wish to avoid the danger that redistributors of a free program + will individually obtain patent licenses, in effect making the program + proprietary. To prevent this, we have made it clear that any patent + must be licensed for everyone&apos;s free use or not licensed at all. + </p> + + <p> + The precise terms and conditions for copying, + distribution and modification follow. + </p> + + <p> + <var class="replacable-license-text"> </var> + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + </p> + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> 0.</var> + This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The &quot;Program&quot;, below, + refers to any such program or work, and a &quot;work based on the Program&quot; + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation + in the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;. + <p> + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act + of running the Program is not restricted, and the output from the + Program is covered only if its contents constitute a work based + on the Program (independent of having been made by running the + Program). Whether that is true depends on what the Program does. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 1.</var> + You may copy and distribute verbatim copies of the Program&apos;s source + code as you receive it, in any medium, provided that you conspicuously + and appropriately publish on each copy an appropriate copyright notice + and disclaimer of warranty; keep intact all the notices that refer to + this License and to the absence of any warranty; and give any other + recipients of the Program a copy of this License along with the Program. + <p> + You may charge a fee for the physical act of + transferring a copy, and you may at your option + offer warranty protection in exchange for a fee. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 2.</var> + You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section + 1 above, provided that you also meet all of these conditions: + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> a)</var> + You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + </li> + +<li> + <var class="replacable-license-text"> b)</var> + You must cause any work that you distribute or publish, + that in whole or in part contains or is derived from the + Program or any part thereof, to be licensed as a whole at no + charge to all third parties under the terms of this License. + </li> + +<li> + <var class="replacable-license-text"> c)</var> + If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display + an announcement including an appropriate copyright notice and + a notice that there is no warranty (or else, saying that you + provide a warranty) and that users may redistribute the program + under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive + but does not normally print such an announcement, your work + based on the Program is not required to print an announcement.) + </li> + +</ul> + <p> + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Program, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not + apply to those sections when you distribute them as separate + works. But when you distribute the same sections as part of a + whole which is a work based on the Program, the distribution + of the whole must be on the terms of this License, whose + permissions for other licensees extend to the entire whole, + and thus to each and every part regardless of who wrote it. + </p> + + <p> + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, + the intent is to exercise the right to control the distribution + of derivative or collective works based on the Program. + </p> + + <p> + In addition, mere aggregation of another work not based on + the Program with the Program (or with a work based on the + Program) on a volume of a storage or distribution medium does + not bring the other work under the scope of this License. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 3.</var> + You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> a)</var> + Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and + 2 above on a medium customarily used for software interchange; or, + </li> + +<li> + <var class="replacable-license-text"> b)</var> + Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to + be distributed under the terms of Sections 1 and 2 above + on a medium customarily used for software interchange; or, + </li> + +<li> + <var class="replacable-license-text"> c)</var> + Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative + is allowed only for noncommercial distribution and only if + you received the program in object code or executable form + with such an offer, in accord with Subsection b above.) + </li> + +</ul> + <p> + The source code for a work means the preferred form of the work + for making modifications to it. For an executable work, complete + source code means all the source code for all modules it contains, + plus any associated interface definition files, plus the scripts + used to control compilation and installation of the executable. + However, as a special exception, the source code distributed + need not include anything that is normally distributed (in either + source or binary form) with the major components (compiler, + kernel, and so on) of the operating system on which the executable + runs, unless that component itself accompanies the executable. + </p> + + <p> + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are + not compelled to copy the source along with the object code. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 4.</var> + You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program + is void, and will automatically terminate your rights under + this License. However, parties who have received copies, or + rights, from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + </li> + +<li> + <var class="replacable-license-text"> 5.</var> + You are not required to accept this License, since you have + not signed it. However, nothing else grants you permission to + modify or distribute the Program or its derivative works. These + actions are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Program (or any + work based on the Program), you indicate your acceptance of this + License to do so, and all its terms and conditions for copying, + distributing or modifying the Program or works based on it. + </li> + +<li> + <var class="replacable-license-text"> 6.</var> + Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further restrictions + on the recipients&apos; exercise of the rights granted herein. You are not + responsible for enforcing compliance by third parties to this License. + </li> + +<li> + <var class="replacable-license-text"> 7.</var> + If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement + or otherwise) that contradict the conditions of this License, + they do not excuse you from the conditions of this License. If you + cannot distribute so as to satisfy simultaneously your obligations + under this License and any other pertinent obligations, then as a + consequence you may not distribute the Program at all. For example, + if a patent license would not permit royalty-free redistribution of + the Program by all those who receive copies directly or indirectly + through you, then the only way you could satisfy both it and this + License would be to refrain entirely from distribution of the Program. + <p> + If any portion of this section is held invalid or + unenforceable under any particular circumstance, the + balance of the section is intended to apply and the section + as a whole is intended to apply in other circumstances. + </p> + + <p> + It is not the purpose of this section to induce you to infringe + any patents or other property right claims or to contest + validity of any such claims; this section has the sole purpose + of protecting the integrity of the free software distribution + system, which is implemented by public license practices. Many + people have made generous contributions to the wide range of + software distributed through that system in reliance on consistent + application of that system; it is up to the author/donor to + decide if he or she is willing to distribute software through + any other system and a licensee cannot impose that choice. + </p> + + <p> + This section is intended to make thoroughly clear what is + believed to be a consequence of the rest of this License. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 8.</var> + If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Program under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this License + incorporates the limitation as if written in the body of this License. + </li> + +<li> + <var class="replacable-license-text"> 9.</var> + The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such + new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + <p> + Each version is given a distinguishing version number. If the + Program specifies a version number of this License which applies + to it and &quot;any later version&quot;, you have the option of following + the terms and conditions either of that version or of any later + version published by the Free Software Foundation. If the Program + does not specify a version number of this License, you may choose + any version ever published by the Free Software Foundation. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 10.</var> + If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted by the + Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + <p> + NO WARRANTY + </p> + + </li> + +<li> + <var class="replacable-license-text"> 11.</var> + BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT + WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER + PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, + EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF + THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU + ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + </li> + +<li> + <var class="replacable-license-text"> 12.</var> + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF + THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER + OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + </li> + +</ul> + <div class="optional-license-text"> + <p> + END OF TERMS AND CONDITIONS + </p> + + <p> + How to Apply These Terms to Your New Programs + </p> + + <p> + If you develop a new program, and you want it to be + of the greatest possible use to the public, the best + way to achieve this is to make it free software which + everyone can redistribute and change under these terms. + </p> + + <p> + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least + the &quot;copyright&quot; line and a pointer to where the full notice is found. + </p> + + <p> + <var class="optional-license-text">&lt;</var>one line to give the program&apos;s name and <var class="replacable-license-text"> an</var> idea of what it does.<var class="optional-license-text">&gt;</var> + <br /> + + Copyright (C) + <var class="optional-license-text">&lt;</var><var class="replacable-license-text"> yyyy</var><var class="optional-license-text">&gt; </var> + <var class="optional-license-text"> &lt;</var>name of author<var class="optional-license-text">&gt;</var> + </p> + + <p> + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version. + </p> + + <p> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more details. + </p> + + <p> + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<var class="optional-license-text">, </var> + USA. + </p> + + <p> + Also add information on how to + contact you by electronic and paper mail. + </p> + + <p> + If the program is interactive, make it output a short + notice like this when it starts in an interactive mode: + </p> + + <p> + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details + type `show w&apos;. This is free software, and you are welcome to + redistribute it under certain conditions; type `show c&apos; for details. + </p> + + <p> + The hypothetical commands `show w&apos; and `show c&apos; should show the + appropriate parts of the General Public License. Of course, the commands + you use may be called something other than `show w&apos; and `show c&apos;; they + could even be mouse-clicks or menu items--whatever suits your program. + </p> + + <p> + You should also get your employer (if you work as a programmer) + or your school, if any, to sign a &quot;copyright disclaimer&quot; for + the program, if necessary. Here is a sample; alter the names: + </p> + + <p> + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision&apos; (which makes passes at compilers) written by James Hacker. + </p> + + <p> + <var class="optional-license-text">&lt;</var>signature of Ty Coon<var class="optional-license-text"> &gt;</var>, + 1 April 1989 Ty Coon, President of Vice + </p> + + </div> + <div class="optional-license-text"> + <p> + This General Public License does not permit incorporating your program into + proprietary programs. If your program is a subroutine library, you may + consider it more useful to permit linking proprietary applications with the + library. If this is what you want to do, use the GNU Lesser General + Public License instead of this License. + </p> + + </div> + + + + 0 + 2022-08-12T00:23:30Z + https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + true + false + true + true + + + true + GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice + + Copyright (C) yyyy name of author + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + + + Copyright (C) <var class="replacable-license-text"> yyyy name of author</var> + <p> + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2. + </p> + + <p> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more details. + </p> + + <p> + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<var class="optional-license-text">, </var> + USA. + </p> + + + + + + + + + + 420 + + + + + + 310 + + + + + + + + + + 23 + + + + + + 5 + + + + + + This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. + + + + + This package has been shipped in source and binary form. The binaries were created with gcc 4.5.1 and expect to link to compatible system run time libraries. + 2010-01-29T18:30:22Z + Person: Jane Doe () + Organization: ExampleCodeInspect () + Tool: LicenseFind-1.0 + 3.17 + + + + + Person: Suzanne Reviewer + Another example reviewer. + + 2011-03-13T00:00:00Z + + + + + Person: Jane Doe () + Document level annotation + + 2010-01-29T18:30:22Z + + + + + false + true + <<beginOptional>><<beginOptional>>Creative Commons<<beginOptional>> Legal Code<<endOptional>> + +<<endOptional>> + +CC0 1.0 Universal + +<<endOptional>><<beginOptional>> CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. + +<<endOptional>> + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. + + <<var;name="bullet";original="1.";match=".{0,20}">> Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: + + <<var;name="bullet";original="i.";match=".{0,20}">> the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + + <<var;name="bullet";original="ii.";match=".{0,20}">> moral rights retained by the original author(s) and/or performer(s); + + <<var;name="bullet";original="iii.";match=".{0,20}">> publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; + + <<var;name="bullet";original="iv.";match=".{0,20}">> rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; + + <<var;name="bullet";original="v.";match=".{0,20}">> rights protecting the extraction, dissemination, use and reuse of data in a Work; + + <<var;name="bullet";original="vi.";match=".{0,20}">> database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and + + <<var;name="bullet";original="vii.";match=".{0,20}">> other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. + + <<var;name="bullet";original="2.";match=".{0,20}">> Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. + + <<var;name="bullet";original="3.";match=".{0,20}">> Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. + + <<var;name="bullet";original="4.";match=".{0,20}">> Limitations and Disclaimers. + + <<var;name="bullet";original="a.";match=".{0,20}">> No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. + + <<var;name="bullet";original="b.";match=".{0,20}">> Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. + + <<var;name="bullet";original="c.";match=".{0,20}">> Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. + + <<var;name="bullet";original="d.";match=".{0,20}">> Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.<<beginOptional>> <<var;name="upstreamLink";original="";match="For more information, please see <http://creativecommons.org/publicdomain/zero/1.0/>">><<endOptional>> + + <div class="optional-license-text"> + <div class="optional-license-text"> + <p>Creative Commons<var class="optional-license-text"> Legal Code</var></p> + + </div> + <p>CC0 1.0 Universal</p> + + </div> + <div class="optional-license-text"> + <p>CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS + DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION + ON AN &quot;AS-IS&quot; BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT + OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE + USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.</p> + + </div> + + <p>Statement of Purpose</p> + + <p>The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related + Rights (defined below) upon the creator and subsequent owner(s) (each and all, an &quot;owner&quot;) + of an original work of authorship and/or a database (each, a &quot;Work&quot;).</p> + + <p>Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a + commons of creative, cultural and scientific works (&quot;Commons&quot;) that the public can reliably + and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse + and redistribute as freely as possible in any form whatsoever and for any purposes, including without + limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a + free culture and the further production of creative, cultural and scientific works, or to gain + reputation or greater distribution for their Work in part through the use and efforts of others.</p> + + <p>For these and/or other purposes and motivations, and without any expectation of additional consideration + or compensation, the person associating CC0 with a Work (the &quot;Affirmer&quot;), to the extent that + he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to + the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and + Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.</p> + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> 1.</var> + Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and + related or neighboring rights (&quot;Copyright and Related Rights&quot;). Copyright and + Related Rights include, but are not limited to, the following: + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> i.</var> + the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + </li> + +<li> + <var class="replacable-license-text"> ii.</var> + moral rights retained by the original author(s) and/or performer(s); + </li> + +<li> + <var class="replacable-license-text"> iii.</var> + publicity and privacy rights pertaining to a person&apos;s image or likeness depicted in a Work; + </li> + +<li> + <var class="replacable-license-text"> iv.</var> + rights protecting against unfair competition in regards to a Work, subject to the limitations + in paragraph 4(a), below; + </li> + +<li> + <var class="replacable-license-text"> v.</var> + rights protecting the extraction, dissemination, use and reuse of data in a Work; + </li> + +<li> + <var class="replacable-license-text"> vi.</var> + database rights (such as those arising under Directive 96/9/EC of the European Parliament and + of the Council of 11 March 1996 on the legal protection of databases, and under any + national implementation thereof, including any amended or successor version of such + directive); and + </li> + +<li> + <var class="replacable-license-text"> vii.</var> + other similar, equivalent or corresponding rights throughout the world based on applicable + law or treaty, and any national implementations thereof. + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 2.</var> + Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, + Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, + and surrenders all of Affirmer&apos;s Copyright and Related Rights and associated claims and + causes of action, whether now known or unknown (including existing as well as future claims + and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum + duration provided by applicable law or treaty (including future time extensions), (iii) in any + current or future medium and for any number of copies, and (iv) for any purpose whatsoever, + including without limitation commercial, advertising or promotional purposes (the + &quot;Waiver&quot;). Affirmer makes the Waiver for the benefit of each member of the public at + large and to the detriment of Affirmer&apos;s heirs and successors, fully intending that such + Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other + legal or equitable action to disrupt the quiet enjoyment of the Work by the public as + contemplated by Affirmer&apos;s express Statement of Purpose. + </li> + +<li> + <var class="replacable-license-text"> 3.</var> + Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid + or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent + permitted taking into account Affirmer&apos;s express Statement of Purpose. In addition, to + the extent the Waiver is so judged Affirmer hereby grants to each affected person a + royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and + unconditional license to exercise Affirmer&apos;s Copyright and Related Rights in the Work (i) + in all territories worldwide, (ii) for the maximum duration provided by applicable law or + treaty (including future time extensions), (iii) in any current or future medium and for any + number of copies, and (iv) for any purpose whatsoever, including without limitation + commercial, advertising or promotional purposes (the &quot;License&quot;). The License shall + be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of + the License for any reason be judged legally invalid or ineffective under applicable law, such + partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and + in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her + remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and + causes of action with respect to the Work, in either case contrary to Affirmer&apos;s express + Statement of Purpose. + </li> + +<li> + <var class="replacable-license-text"> 4.</var> + Limitations and Disclaimers. + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> a.</var> + No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed + or otherwise affected by this document. + </li> + +<li> + <var class="replacable-license-text"> b.</var> + Affirmer offers the Work as-is and makes no representations or warranties of any kind + concerning the Work, express, implied, statutory or otherwise, including without + limitation warranties of title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or the present or + absence of errors, whether or not discoverable, all to the greatest extent permissible + under applicable law. + </li> + +<li> + <var class="replacable-license-text"> c.</var> + Affirmer disclaims responsibility for clearing rights of other persons that may apply to the + Work or any use thereof, including without limitation any person&apos;s Copyright and + Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any + necessary consents, permissions or other rights required for any use of the Work. + </li> + +<li> + <var class="replacable-license-text"> d.</var> + Affirmer understands and acknowledges that Creative Commons is not a party to this document + and has no duty or obligation with respect to this CC0 or use of the Work. + </li> + +</ul> + </li> + +</ul> + <var class="optional-license-text"> <var class="replacable-license-text"> </var></var> + + false + + + 0 + 2022-08-12T00:19:24Z + https://creativecommons.org/publicdomain/zero/1.0/legalcode + false + false + true + true + + + Creative Commons Zero v1.0 Universal + CC0-1.0 + Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + + https://creativecommons.org/publicdomain/zero/1.0/legalcode + + + + + http://justasample.url.com + http://people.apache.org/~andyc/neko/LICENSE + LicenseRef-3 + This is tye CyperNeko License + The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + CyberNeko License + + + + + http://people.freebsd.org/~phk/ + LicenseRef-Beerware-4.2 + The beerware license has a couple of other standard variants. + "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp + Beer-Ware License (Version 42) + + + + + + + + + d6a770ba38583ed4bb4525bd96e50461655d2759 + + + DocumentRef-spdx-tool-1.2 + + + + + LicenseRef-4 + /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + + + LicenseRef-2 + This package includes the GRDDL parser developed by Hewlett Packard under the following license: +© Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + SPDX-2.3 + + + + + + + + + + GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1991 Free Software Foundation, Inc. +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. + +This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. + +Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. + +Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. + +The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. + +Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. + +However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. + +The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. + +Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". + +A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. + +1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. + +(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. + +Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the Library into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. + +5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. + +However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. + +When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. + +If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. + +6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. + +You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: + + a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. + + d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. + + b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. + +14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). + +To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the library's name and an idea of what it does. + Copyright (C) year name of author + + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in +the library `Frob' (a library for tweaking knobs) written +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 +Ty Coon, President of Vice + +That's all there is to it! + LGPL-2.0-only + https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html + false + + <div class="optional-license-text"> + <p> + GNU LIBRARY GENERAL PUBLIC LICENSE + </p> + + <p> + Version 2, June 1991 + </p> + + </div> + <div class="replacable-license-text"> + <p> + Copyright (C) 1991 Free Software Foundation, Inc.<br /> + + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + </p> + + </div> + <p> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + </p> + + <p> + [This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + </p> + + <p> + Preamble + </p> + + <p> + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + Licenses are intended to guarantee your freedom to share and change + free software--to make sure the software is free for all its users. + </p> + + <p> + This license, the Library General Public License, applies + to some specially designated Free Software Foundation + software, and to any other libraries whose authors + decide to use it. You can use it for your libraries, too. + </p> + + <p> + When we speak of free software, we are referring to freedom, not price. + Our General Public Licenses are designed to make sure that you have + the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get + it if you want it, that you can change the software or use pieces of + it in new free programs; and that you know you can do these things. + </p> + + <p> + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the + rights. These restrictions translate to certain responsibilities for + you if you distribute copies of the library, or if you modify it. + </p> + + <p> + For example, if you distribute copies of the library, whether gratis + or for a fee, you must give the recipients all the rights that we + gave you. You must make sure that they, too, receive or can get the + source code. If you link a program with the library, you must provide + complete object files to the recipients so that they can relink them + with the library, after making changes to the library and recompiling + it. And you must show them these terms so they know their rights. + </p> + + <p> + Our method of protecting your rights has two steps: (1) copyright + the library, and (2) offer you this license which gives you + legal permission to copy, distribute and/or modify the library. + </p> + + <p> + Also, for each distributor&apos;s protection, we want to make certain + that everyone understands that there is no warranty for this + free library. If the library is modified by someone else and + passed on, we want its recipients to know that what they have + is not the original version, so that any problems introduced by + others will not reflect on the original authors&apos; reputations. + </p> + + <p> + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that companies distributing + free software will individually obtain patent licenses, thus + in effect transforming the program into proprietary software. + To prevent this, we have made it clear that any patent must + be licensed for everyone&apos;s free use or not licensed at all. + </p> + + <p> + Most GNU software, including some libraries, is covered by the + ordinary GNU General Public License, which was designed for utility + programs. This license, the GNU Library General Public License, + applies to certain designated libraries. This license is quite + different from the ordinary one; be sure to read it in full, and don&apos;t + assume that anything in it is the same as in the ordinary license. + </p> + + <p> + The reason we have a separate public license for some libraries is + that they blur the distinction we usually make between modifying + or adding to a program and simply using it. Linking a program with + a library, without changing the library, is in some sense simply + using the library, and is analogous to running a utility program + or application program. However, in a textual and legal sense, the + linked executable is a combined work, a derivative of the original + library, and the ordinary General Public License treats it as such. + </p> + + <p> + Because of this blurred distinction, using the ordinary General + Public License for libraries did not effectively promote software + sharing, because most developers did not use the libraries. We + concluded that weaker conditions might promote sharing better. + </p> + + <p> + However, unrestricted linking of non-free programs would deprive the + users of those programs of all benefit from the free status of the + libraries themselves. This Library General Public License is intended + to permit developers of non-free programs to use free libraries, while + preserving your freedom as a user of such programs to change the free + libraries that are incorporated in them. (We have not seen how to + achieve this as regards changes in header files, but we have achieved + it as regards changes in the actual functions of the Library.) The + hope is that this will lead to faster development of free libraries. + </p> + + <p> + The precise terms and conditions for copying, distribution + and modification follow. Pay close attention to the difference + between a &quot;work based on the library&quot; and a &quot;work that uses + the library&quot;. The former contains code derived from the + library, while the latter only works together with the library. + </p> + + <p> + Note that it is possible for a library to be covered by the + ordinary General Public License rather than by this special one. + </p> + + <p> + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + </p> + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> 0.</var> + This License Agreement applies to any software library + which contains a notice placed by the copyright holder or + other authorized party saying it may be distributed under + the terms of this Library General Public License (also + called &quot;this License&quot;). Each licensee is addressed as &quot;you&quot;. + <p> + A &quot;library&quot; means a collection of software functions and/or data + prepared so as to be conveniently linked with application programs + (which use some of those functions and data) to form executables. + </p> + + <p> + The &quot;Library&quot;, below, refers to any such software library or work + which has been distributed under these terms. A &quot;work based on + the Library&quot; means either the Library or any derivative work under + copyright law: that is to say, a work containing the Library or a + portion of it, either verbatim or with modifications and/or translated + straightforwardly into another language. (Hereinafter, translation + is included without limitation in the term &quot;modification&quot;.) + </p> + + <p> + &quot;Source code&quot; for a work means the preferred form of the work + for making modifications to it. For a library, complete source + code means all the source code for all modules it contains, + plus any associated interface definition files, plus the scripts + used to control compilation and installation of the library. + </p> + + <p> + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act of + running a program using the Library is not restricted, and output + from such a program is covered only if its contents constitute a + work based on the Library (independent of the use of the Library + in a tool for writing it). Whether that is true depends on what + the Library does and what the program that uses the Library does. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 1.</var> + You may copy and distribute verbatim copies of the Library&apos;s complete + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any warranty; + and distribute a copy of this License along with the Library. + <p> + You may charge a fee for the physical act of + transferring a copy, and you may at your option + offer warranty protection in exchange for a fee. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 2.</var> + You may modify your copy or copies of the Library or any portion + of it, thus forming a work based on the Library, and copy and + distribute such modifications or work under the terms of Section + 1 above, provided that you also meet all of these conditions: + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> a)</var> + The modified work must itself be a software library. + </li> + +<li> + <var class="replacable-license-text"> b)</var> + You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + </li> + +<li> + <var class="replacable-license-text"> c)</var> + You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + </li> + +<li> + <var class="replacable-license-text"> d)</var> + If a facility in the modified Library refers to a function + or a table of data to be supplied by an application program + that uses the facility, other than as an argument passed + when the facility is invoked, then you must make a good faith + effort to ensure that, in the event an application does not + supply such function or table, the facility still operates, + and performs whatever part of its purpose remains meaningful. + <p> + (For example, a function in a library to compute square roots + has a purpose that is entirely well-defined independent of + the application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function + must be optional: if the application does not supply it, + the square root function must still compute square roots.) + </p> + + </li> + +</ul> + <p> + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Library, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not + apply to those sections when you distribute them as separate + works. But when you distribute the same sections as part of a + whole which is a work based on the Library, the distribution + of the whole must be on the terms of this License, whose + permissions for other licensees extend to the entire whole, + and thus to each and every part regardless of who wrote it. + </p> + + <p> + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, + the intent is to exercise the right to control the distribution + of derivative or collective works based on the Library. + </p> + + <p> + In addition, mere aggregation of another work not based on + the Library with the Library (or with a work based on the + Library) on a volume of a storage or distribution medium does + not bring the other work under the scope of this License. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 3.</var> + You may opt to apply the terms of the ordinary GNU General + Public License instead of this License to a given copy of the + Library. To do this, you must alter all the notices that refer + to this License, so that they refer to the ordinary GNU General + Public License, version 2, instead of to this License. (If a + newer version than version 2 of the ordinary GNU General Public + License has appeared, then you can specify that version instead + if you wish.) Do not make any other change in these notices. + <p> + Once this change is made in a given copy, it is irreversible for + that copy, so the ordinary GNU General Public License applies to + all subsequent copies and derivative works made from that copy. + </p> + + <p> + This option is useful when you wish to copy part of the + code of the Library into a program that is not a library. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 4.</var> + You may copy and distribute the Library (or a portion or derivative + of it, under Section 2) in object code or executable form under + the terms of Sections 1 and 2 above provided that you accompany + it with the complete corresponding machine-readable source code, + which must be distributed under the terms of Sections 1 and 2 + above on a medium customarily used for software interchange. + <p> + If distribution of object code is made by offering access to copy + from a designated place, then offering equivalent access to copy + the source code from the same place satisfies the requirement + to distribute the source code, even though third parties are + not compelled to copy the source along with the object code. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 5.</var> + A program that contains no derivative of any portion of the + Library, but is designed to work with the Library by being compiled + or linked with it, is called a &quot;work that uses the Library&quot;. + Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License. + <p> + However, linking a &quot;work that uses the Library&quot; with the Library + creates an executable that is a derivative of the Library (because + it contains portions of the Library), rather than a &quot;work that uses + the library&quot;. The executable is therefore covered by this License. + Section 6 states terms for distribution of such executables. + </p> + + <p> + When a &quot;work that uses the Library&quot; uses material from a header + file that is part of the Library, the object code for the work may + be a derivative work of the Library even though the source code is + not. Whether this is true is especially significant if the work can + be linked without the Library, or if the work is itself a library. + The threshold for this to be true is not precisely defined by law. + </p> + + <p> + If such an object file uses only numerical parameters, data + structure layouts and accessors, and small macros and small inline + functions (ten lines or less in length), then the use of the + object file is unrestricted, regardless of whether it is legally + a derivative work. (Executables containing this object code + plus portions of the Library will still fall under Section 6.) + </p> + + <p> + Otherwise, if the work is a derivative of the Library, you may + distribute the object code for the work under the terms of Section + 6. Any executables containing that work also fall under Section 6, + whether or not they are linked directly with the Library itself. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 6.</var> + As an exception to the Sections above, you may also compile or + link a &quot;work that uses the Library&quot; with the Library to produce + a work containing portions of the Library, and distribute + that work under terms of your choice, provided that the terms + permit modification of the work for the customer&apos;s own use + and reverse engineering for debugging such modifications. + <p> + You must give prominent notice with each copy of the work + that the Library is used in it and that the Library and its + use are covered by this License. You must supply a copy of + this License. If the work during execution displays copyright + notices, you must include the copyright notice for the Library + among them, as well as a reference directing the user to the + copy of this License. Also, you must do one of these things: + </p> + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> a)</var> + Accompany the work with the complete corresponding machine-readable + source code for the Library including whatever changes were used in + the work (which must be distributed under Sections 1 and 2 above); + and, if the work is an executable linked with the Library, with the + complete machine-readable &quot;work that uses the Library&quot;, as object + code and/or source code, so that the user can modify the Library + and then relink to produce a modified executable containing the + modified Library. (It is understood that the user who changes the + contents of definitions files in the Library will not necessarily be + able to recompile the application to use the modified definitions.) + </li> + +<li> + <var class="replacable-license-text"> b)</var> + Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no + more than the cost of performing this distribution. + </li> + +<li> + <var class="replacable-license-text"> c)</var> + If distribution of the work is made by offering access to + copy from a designated place, offer equivalent access to + copy the above specified materials from the same place. + </li> + +<li> + <var class="replacable-license-text"> d)</var> + Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + </li> + +</ul> + <p> + For an executable, the required form of the &quot;work that uses + the Library&quot; must include any data and utility programs needed + for reproducing the executable from it. However, as a special + exception, the source code distributed need not include + anything that is normally distributed (in either source or + binary form) with the major components (compiler, kernel, + and so on) of the operating system on which the executable + runs, unless that component itself accompanies the executable. + </p> + + <p> + It may happen that this requirement contradicts the + license restrictions of other proprietary libraries that + do not normally accompany the operating system. Such + a contradiction means you cannot use both them and the + Library together in an executable that you distribute. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 7.</var> + You may place library facilities that are a work based on the + Library side-by-side in a single library together with other library + facilities not covered by this License, and distribute such a + combined library, provided that the separate distribution of the + work based on the Library and of the other library facilities is + otherwise permitted, and provided that you do these two things: + </li> + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> a)</var> + Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities. + This must be distributed under the terms of the Sections above. + </li> + +<li> + <var class="replacable-license-text"> b)</var> + Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + </li> + +</ul> + +<li> + <var class="replacable-license-text"> 8.</var> + You may not copy, modify, sublicense, link with, or distribute the + Library except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, link with, or distribute + the Library is void, and will automatically terminate your rights + under this License. However, parties who have received copies, or + rights, from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + </li> + +<li> + <var class="replacable-license-text"> 9.</var> + You are not required to accept this License, since you have + not signed it. However, nothing else grants you permission to + modify or distribute the Library or its derivative works. These + actions are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Library (or any + work based on the Library), you indicate your acceptance of this + License to do so, and all its terms and conditions for copying, + distributing or modifying the Library or works based on it. + </li> + +<li> + <var class="replacable-license-text"> 10.</var> + Each time you redistribute the Library (or any work based on + the Library), the recipient automatically receives a license + from the original licensor to copy, distribute, link with or + modify the Library subject to these terms and conditions. You + may not impose any further restrictions on the recipients&apos; + exercise of the rights granted herein. You are not responsible + for enforcing compliance by third parties to this License. + </li> + +<li> + <var class="replacable-license-text"> 11.</var> + If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement + or otherwise) that contradict the conditions of this License, + they do not excuse you from the conditions of this License. If you + cannot distribute so as to satisfy simultaneously your obligations + under this License and any other pertinent obligations, then as a + consequence you may not distribute the Library at all. For example, + if a patent license would not permit royalty-free redistribution of + the Library by all those who receive copies directly or indirectly + through you, then the only way you could satisfy both it and this + License would be to refrain entirely from distribution of the Library. + <p> + If any portion of this section is held invalid or + unenforceable under any particular circumstance, the + balance of the section is intended to apply, and the section + as a whole is intended to apply in other circumstances. + </p> + + <p> + It is not the purpose of this section to induce you to infringe + any patents or other property right claims or to contest + validity of any such claims; this section has the sole purpose + of protecting the integrity of the free software distribution + system which is implemented by public license practices. Many + people have made generous contributions to the wide range of + software distributed through that system in reliance on consistent + application of that system; it is up to the author/donor to + decide if he or she is willing to distribute software through + any other system and a licensee cannot impose that choice. + </p> + + <p> + This section is intended to make thoroughly clear what is + believed to be a consequence of the rest of this License. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 12.</var> + If the distribution and/or use of the Library is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Library under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this License + incorporates the limitation as if written in the body of this License. + </li> + +<li> + <var class="replacable-license-text"> 13.</var> + The Free Software Foundation may publish revised and/or new versions + of the Library General Public License from time to time. Such + new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + <p> + Each version is given a distinguishing version number. If + the Library specifies a version number of this License which + applies to it and &quot;any later version&quot;, you have the option of + following the terms and conditions either of that version or of + any later version published by the Free Software Foundation. If + the Library does not specify a license version number, you may + choose any version ever published by the Free Software Foundation. + </p> + + </li> + +<li> + <var class="replacable-license-text"> 14.</var> + If you wish to incorporate parts of the Library into other free programs + whose distribution conditions are incompatible with these, write to + the author to ask for permission. For software which is copyrighted by + the Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + <p> + NO WARRANTY + </p> + + </li> + +<li> + <var class="replacable-license-text"> 15.</var> + BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT + WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER + PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, + EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF + THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU + ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + </li> + +<li> + <var class="replacable-license-text"> 16.</var> + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF + THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER + OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + </li> + +</ul> + <div class="optional-license-text"> + <p> + END OF TERMS AND CONDITIONS + </p> + + <p> + How to Apply These Terms to Your New Libraries + </p> + + <p> + If you develop a new library, and you want it to be of the greatest + possible use to the public, we recommend making it free software + that everyone can redistribute and change. You can do so by + permitting redistribution under these terms (or, alternatively, + under the terms of the ordinary General Public License). + </p> + + <p> + To apply these terms, attach the following notices to the + library. It is safest to attach them to the start of each + source file to most effectively convey the exclusion of + warranty; and each file should have at least the &quot;copyright&quot; + line and a pointer to where the full notice is found. + </p> + + <p> + one line to give the library&apos;s name + and an idea of what it does.<br /> + + Copyright (C) year name of author + </p> + + <p> + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + </p> + + <p> + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + the GNU Library General Public License for more details. + </p> + + <p> + You should have received a copy of the GNU Library + General Public License along with this library; if + not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + </p> + + <p> + Also add information on how to contact you by electronic and paper mail. + </p> + + <p> + You should also get your employer (if you work as a programmer) + or your school, if any, to sign a &quot;copyright disclaimer&quot; for + the library, if necessary. Here is a sample; alter the names: + </p> + + <p> + Yoyodyne, Inc., hereby disclaims all copyright interest in<br /> + + the library `Frob&apos; (a library for tweaking knobs) written<br /> + + by James Random Hacker. + </p> + + <p> + signature of Ty Coon, 1 April 1990<br /> + + Ty Coon, President of Vice + </p> + + <p> + That&apos;s all there is to it! + </p> + + </div> + + true + Copyright (C) year name of author + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + + + + + 0 + 2022-08-12T00:25:56Z + https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html + true + false + true + true + + + <<beginOptional>>GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +<<endOptional>> <<var;name="copyright";original="Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ";match=".{0,5000}">> + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. + +This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. + +Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. + +Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. + +The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. + +Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. + +However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. + +The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. + +Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + <<var;name="bullet";original="0.";match=".{0,20}">> This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. + + Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. + + <<var;name="bullet";original="1.";match=".{0,20}">> You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. + + You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + + <<var;name="bullet";original="2.";match=".{0,20}">> You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + <<var;name="bullet";original="a)";match=".{0,20}">> The modified work must itself be a software library. + + <<var;name="bullet";original="b)";match=".{0,20}">> You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. + + <<var;name="bullet";original="c)";match=".{0,20}">> You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. + + <<var;name="bullet";original="d)";match=".{0,20}">> If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. + + (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) + + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. + + In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + + <<var;name="bullet";original="3.";match=".{0,20}">> You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. + + Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of the Library into a program that is not a library. + + <<var;name="bullet";original="4.";match=".{0,20}">> You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. + + <<var;name="bullet";original="5.";match=".{0,20}">> A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. + + <<var;name="bullet";original="6.";match=".{0,20}">> As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: + + <<var;name="bullet";original="a)";match=".{0,20}">> Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) + + <<var;name="bullet";original="b)";match=".{0,20}">> Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. + + <<var;name="bullet";original="c)";match=".{0,20}">> If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. + + <<var;name="bullet";original="d)";match=".{0,20}">> Verify that the user has already received a copy of these materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + + It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. + + <<var;name="bullet";original="7.";match=".{0,20}">> You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: + + <<var;name="bullet";original="a)";match=".{0,20}">> Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. + + <<var;name="bullet";original="b)";match=".{0,20}">> Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + + <<var;name="bullet";original="8.";match=".{0,20}">> You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + + <<var;name="bullet";original="9.";match=".{0,20}">> You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. + + <<var;name="bullet";original="10.";match=".{0,20}">> Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + + <<var;name="bullet";original="11.";match=".{0,20}">> If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. + + If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + + <<var;name="bullet";original="12.";match=".{0,20}">> If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + + <<var;name="bullet";original="13.";match=".{0,20}">> The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. + + <<var;name="bullet";original="14.";match=".{0,20}">> If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + <<var;name="bullet";original="15.";match=".{0,20}">> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + <<var;name="bullet";original="16.";match=".{0,20}">> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.<<beginOptional>> END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). + +To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +one line to give the library's name and an idea of what it does. + +Copyright (C) year name of author + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in + +the library `Frob' (a library for tweaking knobs) written + +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 + +Ty Coon, President of Vice + +That's all there is to it! + +<<endOptional>> + This license was released: June 1991. This license has been superseded by LGPL-2.1. This license identifier refers to the choice to use the code under LGPL-2.0-only, as distinguished from use of code under LGPL-2.0-or-later (i.e., LGPL-2.0 or some later version). The license notice (as seen in the Standard License Header field below) states which of these applies to the code in the file. The example in the exhibit to the license shows the license notice for the "or later" approach. + GNU Library General Public License v2 only + Copyright (C) <<var;name="copyright";original="year name of author";match=".+">> + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + + + + Copyright (C) <var class="replacable-license-text"> year name of author</var> + <p>This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; version 2.</p> + + <p>This library is distributed + in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU Library General Public License for more details.</p> + + <p>You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + </p> + + + + + + + http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz + + + Person: Package Commenter + Package level annotation + + 2011-01-29T18:30:22Z + + + 2.11.1 + + + + + + Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) + + + + c2b4e1c67a2d28fced849ee1bb76e7391b93f125 + + + + + Apache Software Foundation + + + + + + + ./lib-source/commons-lang3-3.1-sources.jar + Copyright 2001-2011 The Apache Software Foundation + This file is used by Jena + + + + + + + + + + This is the external ref for Acme + + acmecorp/acmenator/4.1.3-alpha + + + true + + + + 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd + + + + + + + + + LicenseRef-1 + /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + This license is used by Jena + Hewlett Packard Inc. + + (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + Apache Software Foundation + + This file belongs to Jena + + + + 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 + + + ./lib-source/jena-2.6.3-sources.jar + + + + + + + + + + + + + The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. + + + + aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706 + + + + + + 85ed0817af83a24ad8da68c2b5094de69833983c + + + + + + + Saxon + + + + 85ed0817af83a24ad8da68c2b5094de69833983c + + + The Saxon package is a collection of tools for processing XML documents. + http://saxon.sourceforge.net/ + 8.8 + Other versions available for a commercial license + https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download + saxonB-8.8.zip + + + https://opensource.org/licenses/MPL-1.0 + + + 1 + 2022-08-12T00:25:48Z + https://opensource.org/licenses/MPL-1.0 + N/A + false + true + false + + + MOZILLA PUBLIC LICENSE +Version 1.0 + +1. Definitions. + + 1.1. ``Contributor'' means each entity that creates or contributes to the creation of Modifications. + + 1.2. ``Contributor Version'' means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. + + 1.3. ``Covered Code'' means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. + + 1.4. ``Electronic Distribution Mechanism'' means a mechanism generally accepted in the software development community for the electronic transfer of data. + + 1.5. ``Executable'' means Covered Code in any form other than Source Code. + + 1.6. ``Initial Developer'' means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. + + 1.7. ``Larger Work'' means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. + + 1.8. ``License'' means this document. + + 1.9. ``Modifications'' means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: + + A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or previous Modifications. + + 1.10. ``Original Code'' means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. + + 1.11. ``Source Code'' means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. + + 1.12. ``You'' means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, ``You'' includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, ``control'' means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. +The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + (a) to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and + + (b) under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell (``Utilize'') the Original Code (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + + 2.2. Contributor Grant. +Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + (a) to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and + + (b) under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + + (a) Third Party Claims. + If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled ``LEGAL'' which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. +If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. + +5. Application of this License. +This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation (``Netscape'') may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. + + 6.3. Derivative Works. + If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases ``Mozilla'', ``MOZILLAPL'', ``MOZPL'', ``Netscape'', ``NPL'' or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) + +7. DISCLAIMER OF WARRANTY. +COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN ``AS IS'' BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. +This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. + +9. LIMITATION OF LIABILITY. +UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. +The Covered Code is a ``commercial item,'' as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of ``commercial computer software'' and ``commercial computer software documentation,'' as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. + +11. MISCELLANEOUS. +This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the United States of America: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Santa Clara County, California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. + +12. RESPONSIBILITY FOR CLAIMS. +Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute responsibility on an equitable basis. + +EXHIBIT A. + +``The contents of this file are subject to the Mozilla Public License Version 1.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.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is ______________________________________. + +The Initial Developer of the Original Code is ________________________. Portions created by ______________________ are Copyright (C) ______ _______________________. All Rights Reserved. + +Contributor(s): ______________________________________.'' + + + 0 + 2022-08-12T00:25:47Z + http://www.mozilla.org/MPL/MPL-1.0.html + true + false + true + true + + + This license has been superseded by v1.1 + http://www.mozilla.org/MPL/MPL-1.0.html + Mozilla Public License 1.0 + "The contents of this file are subject to the Mozilla Public License Version 1.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.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is _____ . The Initial Developer of the Original Code is _____ . Portions created by _____ are Copyright (C) _____ . All Rights Reserved. Contributor(s): _____ ." + + + <<beginOptional>>"<<endOptional>>The contents of this file are subject to the Mozilla Public License Version 1.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.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is <<var;name="code";original="_____";match=".+">> . The Initial Developer of the Original Code is <<var;name="InitialDeveloper";original="_____";match=".+">> . Portions created by <<var;name="createdby";original="_____";match=".+">> are Copyright (C) <<var;name="copyright";original="_____";match=".+">> . All Rights Reserved. Contributor(s): <<var;name="contributor";original="_____";match=".+">> .<<beginOptional>>"<<endOptional>> + + + <<beginOptional>>MOZILLA PUBLIC LICENSE + +Version 1.0 + +<<endOptional>> + + <<var;name="bullet";original="1.";match=".{0,20}">> Definitions. + + <<var;name="bullet";original="1.1.";match=".{0,20}">> "Contributor" means each entity that creates or contributes to the creation of Modifications. + + <<var;name="bullet";original="1.2.";match=".{0,20}">> "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. + + <<var;name="bullet";original="1.3.";match=".{0,20}">> "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. + + <<var;name="bullet";original="1.4.";match=".{0,20}">> "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. + + <<var;name="bullet";original="1.5.";match=".{0,20}">> "Executable" means Covered Code in any form other than Source Code. + + <<var;name="bullet";original="1.6.";match=".{0,20}">> "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. + + <<var;name="bullet";original="1.7.";match=".{0,20}">> "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. + + <<var;name="bullet";original="1.8.";match=".{0,20}">> "License" means this document. + + <<var;name="bullet";original="1.9.";match=".{0,20}">> "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: + + <<var;name="bullet";original="A.";match=".{0,20}">> Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. + + <<var;name="bullet";original="B.";match=".{0,20}">> Any new file that contains any part of the Original Code or previous Modifications. + + <<var;name="bullet";original="1.10.";match=".{0,20}">> "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. + + <<var;name="bullet";original="1.11.";match=".{0,20}">> "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. + + <<var;name="bullet";original="1.12.";match=".{0,20}">> "You" means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. + + <<var;name="bullet";original="2.";match=".{0,20}">> Source Code License. + + <<var;name="bullet";original="2.1.";match=".{0,20}">> The Initial Developer Grant. + + The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + <<var;name="bullet";original="(a)";match=".{0,20}">> to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and + + <<var;name="bullet";original="(b)";match=".{0,20}">> under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell ("Utilize") the Original Code (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + + <<var;name="bullet";original="2.2.";match=".{0,20}">> Contributor Grant. + + Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + <<var;name="bullet";original="(a)";match=".{0,20}">> to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and + + <<var;name="bullet";original="(b)";match=".{0,20}">> under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + + <<var;name="bullet";original="3.";match=".{0,20}">> Distribution Obligations. + + <<var;name="bullet";original="3.1.";match=".{0,20}">> Application of License. + + The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. + + <<var;name="bullet";original="3.2.";match=".{0,20}">> Availability of Source Code. + + Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. + + <<var;name="bullet";original="3.3.";match=".{0,20}">> Description of Modifications. + + You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. + + <<var;name="bullet";original="3.4.";match=".{0,20}">> Intellectual Property Matters + + <<var;name="bullet";original="(a)";match=".{0,20}">> Third Party Claims. + + If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. + + <<var;name="bullet";original="(b)";match=".{0,20}">> Contributor APIs. + + If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file. + + <<var;name="bullet";original="3.5.";match=".{0,20}">> Required Notices. + + You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. + + <<var;name="bullet";original="3.6.";match=".{0,20}">> Distribution of Executable Versions. + + You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. + + <<var;name="bullet";original="3.7.";match=".{0,20}">> Larger Works. + + You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. + + <<var;name="bullet";original="4.";match=".{0,20}">> Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. + + <<var;name="bullet";original="5.";match=".{0,20}">> Application of this License. + + This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code. + + <<var;name="bullet";original="6.";match=".{0,20}">> Versions of the License. + + <<var;name="bullet";original="6.1.";match=".{0,20}">> New Versions. + + Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. + + <<var;name="bullet";original="6.2.";match=".{0,20}">> Effect of New Versions. + + Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. + + <<var;name="bullet";original="6.3.";match=".{0,20}">> Derivative Works. + + If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "NPL" or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) + + <<var;name="bullet";original="7.";match=".{0,20}">> DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + + <<var;name="bullet";original="8.";match=".{0,20}">> TERMINATION. + + This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. + + <<var;name="bullet";original="9.";match=".{0,20}">> LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + + <<var;name="bullet";original="10.";match=".{0,20}">> U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. + + <<var;name="bullet";original="11.";match=".{0,20}">> MISCELLANEOUS. + + This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the United States of America: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Santa Clara County, California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. + + <<var;name="bullet";original="12.";match=".{0,20}">> RESPONSIBILITY FOR CLAIMS. + + Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute responsibility on an equitable basis.<<beginOptional>> EXHIBIT A. + +<<beginOptional>>"<<endOptional>>The contents of this file are subject to the Mozilla Public License Version 1.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.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is <<var;name="code";original="_____";match=".+">> . The Initial Developer of the Original Code is <<var;name="InitialDeveloper";original="_____";match=".+">> . Portions created by <<var;name="createdby";original="_____";match=".+">> are Copyright (C) <<var;name="copyright";original="_____";match=".+">> . All Rights Reserved. Contributor(s): <<var;name="contributor";original="_____";match=".+">> .<<beginOptional>>"<<endOptional>> + +<<endOptional>> + true + + <p><var class="optional-license-text">&quot;</var>The contents of this file are subject to the Mozilla Public License Version 1.0 (the + &quot;License&quot;); you may not use this file except in compliance with the License. You may obtain + a copy of the License at http://www.mozilla.org/MPL/</p> + + <p>Software distributed under the License is distributed on an &quot;AS IS&quot; basis, WITHOUT WARRANTY OF + ANY KIND, either express or implied. See the License for the specific language governing rights and + limitations under the License.</p> + + <p>The Original Code is + <var class="replacable-license-text"> _____</var>. The Initial Developer of the Original Code is + <var class="replacable-license-text"> _____</var>. Portions created by + <var class="replacable-license-text"> _____</var> are Copyright (C) + <var class="replacable-license-text"> _____</var>. All Rights Reserved. Contributor(s): + <var class="replacable-license-text"> _____</var>.<var class="optional-license-text">&quot;</var> + </p> + + + false + + <div class="optional-license-text"> + <p>MOZILLA PUBLIC LICENSE + <br /> + +Version 1.0 + </p> + + </div> + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> 1.</var> + Definitions. + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> 1.1.</var> + &quot;Contributor&quot; means each entity that creates or contributes to the creation of + Modifications. + </li> + +<li> + <var class="replacable-license-text"> 1.2.</var> + &quot;Contributor Version&quot; means the combination of the Original Code, prior + Modifications used by a Contributor, and the Modifications made by that particular + Contributor. + </li> + +<li> + <var class="replacable-license-text"> 1.3.</var> + &quot;Covered Code&quot; means the Original Code or Modifications or the combination of the + Original Code and Modifications, in each case including portions thereof. + </li> + +<li> + <var class="replacable-license-text"> 1.4.</var> + &quot;Electronic Distribution Mechanism&quot; means a mechanism generally accepted in the + software development community for the electronic transfer of data. + </li> + +<li> + <var class="replacable-license-text"> 1.5.</var> + &quot;Executable&quot; means Covered Code in any form other than Source Code. + </li> + +<li> + <var class="replacable-license-text"> 1.6.</var> + &quot;Initial Developer&quot; means the individual or entity identified as the Initial + Developer in the Source Code notice required by Exhibit A. + </li> + +<li> + <var class="replacable-license-text"> 1.7.</var> + &quot;Larger Work&quot; means a work which combines Covered Code or portions thereof with + code not governed by the terms of this License. + </li> + +<li> + <var class="replacable-license-text"> 1.8.</var> + &quot;License&quot; means this document. + </li> + +<li> + <var class="replacable-license-text"> 1.9.</var> + &quot;Modifications&quot; means any addition to or deletion from the substance or structure + of either the Original Code or any previous Modifications. When Covered Code is released + as a series of files, a Modification is: + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> A.</var> + Any addition to or deletion from the contents of a file containing Original Code or + previous Modifications. + </li> + +<li> + <var class="replacable-license-text"> B.</var> + Any new file that contains any part of the Original Code or previous Modifications. + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 1.10.</var> + &quot;Original Code&quot; means Source Code of computer software code which is described in + the Source Code notice required by Exhibit A as Original Code, and which, at the time of + its release under this License is not already Covered Code governed by this License. + </li> + +<li> + <var class="replacable-license-text"> 1.11.</var> + &quot;Source Code&quot; means the preferred form of the Covered Code for making + modifications to it, including all modules it contains, plus any associated interface + definition files, scripts used to control compilation and installation of an Executable, + or a list of source code differential comparisons against either the Original Code or + another well known, available Covered Code of the Contributor&apos;s choice. The Source + Code can be in a compressed or archival form, provided the appropriate decompression or + de-archiving software is widely available for no charge. + </li> + +<li> + <var class="replacable-license-text"> 1.12.</var> + &quot;You&quot; means an individual or a legal entity exercising rights under, and + complying with all of the terms of, this License or a future version of this License + issued under Section 6.1. For legal entities, &quot;You&quot; includes any entity which + controls, is controlled by, or is under common control with You. For purposes of this + definition, &quot;control&quot; means (a) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or otherwise, or (b) ownership + of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such + entity. + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 2.</var> + Source Code License. + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> 2.1.</var> + The Initial Developer Grant. + <br /> + + The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive + license, subject to third party intellectual property claims: + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> (a)</var> + to use, reproduce, modify, display, perform, sublicense and distribute the Original Code + (or portions thereof) with or without Modifications, or as part of a Larger Work; + and + </li> + +<li> + <var class="replacable-license-text"> (b)</var> + under patents now or hereafter owned or controlled by Initial Developer, to make, have + made, use and sell (&quot;Utilize&quot;) the Original Code (or portions thereof), + but solely to the extent that any such patent is reasonably necessary to enable You to + Utilize the Original Code (or portions thereof) and not to any greater extent that may + be necessary to Utilize further Modifications or combinations. + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 2.2.</var> + Contributor Grant. + <br /> + + Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, + subject to third party intellectual property claims: + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> (a)</var> + to use, reproduce, modify, display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an unmodified basis, with + other Modifications, as Covered Code or as part of a Larger Work; and + </li> + +<li> + <var class="replacable-license-text"> (b)</var> + under patents now or hereafter owned or controlled by Contributor, to Utilize the + Contributor Version (or portions thereof), but solely to the extent that any such + patent is reasonably necessary to enable You to Utilize the Contributor Version (or + portions thereof), and not to any greater extent that may be necessary to Utilize + further Modifications or combinations. + </li> + +</ul> + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 3.</var> + Distribution Obligations. + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> 3.1.</var> + Application of License. + <br /> + + The Modifications which You create or to which You contribute are governed by the terms + of this License, including without limitation Section 2.2. The Source Code version + of Covered Code may be distributed only under the terms of this License or a + future version of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You distribute. You may + not offer or impose any terms on any Source Code version that alters or restricts + the applicable version of this License or the recipients&apos; rights hereunder. + However, You may include an additional document offering the additional rights + described in Section 3.5. + + </li> + +<li> + <var class="replacable-license-text"> 3.2.</var> + Availability of Source Code. + <br /> + + Any Modification which You create or to which You contribute must be made available in + Source Code form under the terms of this License either on the same media as an + Executable version or via an accepted Electronic Distribution Mechanism to anyone + to whom you made an Executable version available; and if made available via + Electronic Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six (6) months + after a subsequent version of that particular Modification has been made available + to such recipients. You are responsible for ensuring that the Source Code version + remains available even if the Electronic Distribution Mechanism is maintained by a + third party. + + </li> + +<li> + <var class="replacable-license-text"> 3.3.</var> + Description of Modifications. + <br /> + + You must cause all Covered Code to which you contribute to contain a file documenting + the changes You made to create that Covered Code and the date of any change. You + must include a prominent statement that the Modification is derived, directly or + indirectly, from Original Code provided by the Initial Developer and including the + name of the Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the origin or + ownership of the Covered Code. + + </li> + +<li> + <var class="replacable-license-text"> 3.4.</var> + Intellectual Property Matters + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> (a)</var> + Third Party Claims. + <br /> + + If You have knowledge that a party claims an intellectual property right in + particular functionality or code (or its utilization under this License), you + must include a text file with the source code distribution titled + &quot;LEGAL&quot; which describes the claim and the party making the claim + in sufficient detail that a recipient will know whom to contact. If you obtain + such knowledge after You make Your Modification available as described in + Section 3.2, You shall promptly modify the LEGAL file in all copies You make + available thereafter and shall take other steps (such as notifying appropriate + mailing lists or newsgroups) reasonably calculated to inform those who + received the Covered Code that new knowledge has been obtained. + + </li> + +<li> + <var class="replacable-license-text"> (b)</var> + Contributor APIs. + <br /> + + If Your Modification is an application programming interface and You own or control + patents which are reasonably necessary to implement that API, you must also + include this information in the LEGAL file. + + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 3.5.</var> + Required Notices. + <br /> + + You must duplicate the notice in Exhibit A in each file of the Source Code, and this + License in any documentation for the Source Code, where You describe + recipients&apos; rights relating to Covered Code. If You created one or more + Modification(s), You may add your name as a Contributor to the notice described in + Exhibit A. If it is not possible to put such notice in a particular Source Code + file due to its structure, then you must include such notice in a location (such + as a relevant directory file) where a user would be likely to look for such a + notice. You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered Code. + However, You may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than any such + warranty, support, indemnity or liability obligation is offered by You alone, and + You hereby agree to indemnify the Initial Developer and every Contributor for any + liability incurred by the Initial Developer or such Contributor as a result of + warranty, support, indemnity or liability terms You offer. + + </li> + +<li> + <var class="replacable-license-text"> 3.6.</var> + Distribution of Executable Versions. + <br /> + + You may distribute Covered Code in Executable form only if the requirements of Section + 3.1-3.5 have been met for that Covered Code, and if You include a notice stating + that the Source Code version of the Covered Code is available under the terms of + this License, including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included in any + notice in an Executable version, related documentation or collateral in which You + describe recipients&apos; rights relating to the Covered Code. You may distribute + the Executable version of Covered Code under a license of Your choice, which may + contain terms different from this License, provided that You are in compliance + with the terms of this License and that the license for the Executable version + does not attempt to limit or alter the recipient&apos;s rights in the Source Code + version from the rights set forth in this License. If You distribute the + Executable version under a different license You must make it absolutely clear + that any terms which differ from this License are offered by You alone, not by the + Initial Developer or any Contributor. You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the Initial + Developer or such Contributor as a result of any such terms You offer. + + </li> + +<li> + <var class="replacable-license-text"> 3.7.</var> + Larger Works. + <br /> + + You may create a Larger Work by combining Covered Code with other code not governed by + the terms of this License and distribute the Larger Work as a single product. In + such a case, You must make sure the requirements of this License are fulfilled for + the Covered Code. + + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 4.</var> + Inability to Comply Due to Statute or Regulation. + <br /> + + If it is impossible for You to comply with any of the terms of this License with respect to + some or all of the Covered Code due to statute or regulation then You must: (a) comply + with the terms of this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be included in the LEGAL + file described in Section 3.4 and must be included with all distributions of the + Source Code. Except to the extent prohibited by statute or regulation, such + description must be sufficiently detailed for a recipient of ordinary skill to be able + to understand it. + + </li> + +<li> + <var class="replacable-license-text"> 5.</var> + Application of this License. + <br /> + + This License applies to code to which the Initial Developer has attached the notice in + Exhibit A, and to related Covered Code. + + </li> + +<li> + <var class="replacable-license-text"> 6.</var> + Versions of the License. + +<ul style="list-style:none"> + +<li> + <var class="replacable-license-text"> 6.1.</var> + New Versions. + <br /> + + Netscape Communications Corporation (&quot;Netscape&quot;) may publish revised and/or + new versions of the License from time to time. Each version will be given a + distinguishing version number. + + </li> + +<li> + <var class="replacable-license-text"> 6.2.</var> + Effect of New Versions. + <br /> + + Once Covered Code has been published under a particular version of the License, You may + always continue to use it under the terms of that version. You may also choose to + use such Covered Code under the terms of any subsequent version of the License + published by Netscape. No one other than Netscape has the right to modify the + terms applicable to Covered Code created under this License. + + </li> + +<li> + <var class="replacable-license-text"> 6.3.</var> + Derivative Works. + <br /> + + If you create or use a modified version of this License (which you may only do in order + to apply it to code which is not already Covered Code governed by this License), + you must (a) rename Your license so that the phrases &quot;Mozilla&quot;, + &quot;MOZILLAPL&quot;, &quot;MOZPL&quot;, &quot;Netscape&quot;, + &quot;NPL&quot; or any confusingly similar phrase do not appear anywhere in your + license and (b) otherwise make it clear that your version of the license contains + terms which differ from the Mozilla Public License and Netscape Public License. + (Filling in the name of the Initial Developer, Original Code or Contributor in the + notice described in Exhibit A shall not of themselves be deemed to be + modifications of this License.) + + </li> + +</ul> + </li> + +<li> + <var class="replacable-license-text"> 7.</var> + DISCLAIMER OF WARRANTY. + <br /> + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN &quot;AS IS&quot; BASIS, WITHOUT + WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, + WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A + PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND + PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE + IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY + CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS + AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + + </li> + +<li> + <var class="replacable-license-text"> 8.</var> + TERMINATION. + <br /> + + This License and the rights granted hereunder will terminate automatically if You fail to + comply with terms herein and fail to cure such breach within 30 days of becoming aware + of the breach. All sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their nature, must + remain in effect beyond the termination of this License shall survive. + + </li> + +<li> + <var class="replacable-license-text"> 9.</var> + LIMITATION OF LIABILITY. + <br /> + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), + CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY + DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU + OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF + ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK + STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR + LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH + DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR + PERSONAL INJURY RESULTING FROM SUCH PARTY&apos;S NEGLIGENCE TO THE EXTENT APPLICABLE + LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR + LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION + MAY NOT APPLY TO YOU. + + </li> + +<li> + <var class="replacable-license-text"> 10.</var> + U.S. GOVERNMENT END USERS. + <br /> + + The Covered Code is a &quot;commercial item,&quot; as that term is defined in 48 C.F.R. + 2.101 (Oct. 1995), consisting of &quot;commercial computer software&quot; and + &quot;commercial computer software documentation,&quot; as such terms are used in 48 + C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 + through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code + with only those rights set forth herein. + + </li> + +<li> + <var class="replacable-license-text"> 11.</var> + MISCELLANEOUS. + <br /> + + This License represents the complete agreement concerning subject matter hereof. If any + provision of this License is held to be unenforceable, such provision shall be + reformed only to the extent necessary to make it enforceable. This License shall be + governed by California law provisions (except to the extent applicable law, if any, + provides otherwise), excluding its conflict-of-law provisions. With respect to + disputes in which at least one party is a citizen of, or an entity chartered or + registered to do business in, the United States of America: (a) unless otherwise + agreed in writing, all disputes relating to this License (excepting any dispute + relating to intellectual property rights) shall be subject to final and binding + arbitration, with the losing party paying all costs of arbitration; (b) any + arbitration relating to this Agreement shall be held in Santa Clara County, + California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to + this Agreement shall be subject to the jurisdiction of the Federal Courts of the + Northern District of California, with venue lying in Santa Clara County, California, + with the losing party responsible for costs, including without limitation, court costs + and reasonable attorneys fees and expenses. The application of the United Nations + Convention on Contracts for the International Sale of Goods is expressly excluded. Any + law or regulation which provides that the language of a contract shall be construed + against the drafter shall not apply to this License. + + </li> + +<li> + <var class="replacable-license-text"> 12.</var> + RESPONSIBILITY FOR CLAIMS. + <br /> + + Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for + damages arising, directly or indirectly, out of Your utilization of rights under this License, based + on the number of copies of Covered Code you made available, the revenues you received from utilizing + such rights, and other relevant factors. You agree to work with affected parties to distribute + responsibility on an equitable basis. + </li> + +</ul> + <div class="optional-license-text"> + <p>EXHIBIT A.</p> + + <p><var class="optional-license-text">&quot;</var>The contents of this file are subject to the Mozilla Public License Version 1.0 (the + &quot;License&quot;); you may not use this file except in compliance with the License. You may obtain + a copy of the License at http://www.mozilla.org/MPL/</p> + + <p>Software distributed under the License is distributed on an &quot;AS IS&quot; basis, WITHOUT WARRANTY OF + ANY KIND, either express or implied. See the License for the specific language governing rights and + limitations under the License.</p> + + <p>The Original Code is + <var class="replacable-license-text"> _____</var>. The Initial Developer of the Original Code is + <var class="replacable-license-text"> _____</var>. Portions created by + <var class="replacable-license-text"> _____</var> are Copyright (C) + <var class="replacable-license-text"> _____</var>. All Rights Reserved. Contributor(s): + <var class="replacable-license-text"> _____</var>.<var class="optional-license-text">&quot;</var> + </p> + + </div> + + MPL-1.0 + + + false + Copyright Saxonica Ltd + + + + + + + http://ftp.gnu.org/gnu/glibc + glibc + 2011-01-29T18:30:22Z + + + + + + + + + + + 624c1abb3664f4b35547e7c73864ad24 + + + Person: Jane Doe (jane.doe@example.com) + The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. + Organization: ExampleCodeInspect (contact@example.com) + + + + + + + + + + + http://www.openjena.org/ + + + + + pkg:maven/org.apache.jena/apache-jena@3.12.0 + + + 3.12.0 + https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz + Jena + false + + + + + + Specification Documentation + + + + fff4e1c67a2d28fced849ee1bb76e7391b93f125 + + + ./docs/myspec.pdf + + + + + + 2012-01-29T18:30:22Z + uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. + glibc-2.11.1.tar.gz + 2014-01-29T18:30:22Z + + + + + + + GNU C library. + + + d6a770ba38583ed4bb4525bd96e50461655d2758 + ./package.spdx + + + + + + + cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* + + + Copyright 2008-2010 John Smith + The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. + + + + + + This document was created using SPDX 2.0 using licenses from the web site. + + + + + + + + + + + ./package/foo.c + The concluded license was taken from the package level that the file was included in. + + + + + + + + + Person: File Commenter + File level annotation + + 2011-01-29T18:30:22Z + + + + + + + + 624c1abb3664f4b35547e7c73864ad24 + + + + + + d6a770ba38583ed4bb4525bd96e50461655d2758 + + + Copyright 2008-2010 John Smith + The Regents of the University of California + Modified by Paul Mundt lethal@linux-sh.org + + + + + + + + IBM Corporation + Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. + + + + + + SPDX-Tools-v2.0 + + + Person: Joe Reviewer + This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses + + 2010-02-10T00:00:00Z + + + + + + + + + + + + http://commons.apache.org/proper/commons-lang/ + NOASSERTION + + NOASSERTION + Apache Commons Lang + + false + + diff --git a/tests/spdx/data/SPDXTagExample-UTF-16.spdx b/tests/spdx/data/SPDXTagExample-UTF-16.spdx new file mode 100644 index 000000000..72682949b Binary files /dev/null and b/tests/spdx/data/SPDXTagExample-UTF-16.spdx differ diff --git a/tests/spdx/data/SPDXTagExample-v2.2.spdx b/tests/spdx/data/SPDXTagExample-v2.2.spdx new file mode 100644 index 000000000..e8f32ebfd --- /dev/null +++ b/tests/spdx/data/SPDXTagExample-v2.2.spdx @@ -0,0 +1,329 @@ +SPDXVersion: SPDX-2.2 +DataLicense: CC0-1.0 +DocumentNamespace: http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 +DocumentName: SPDX-Tools-v2.0 +SPDXID: SPDXRef-DOCUMENT +DocumentComment: This document was created using SPDX 2.0 using licenses from the web site. + +## External Document References +ExternalDocumentRef: DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759 +## Creation Information +Creator: Tool: LicenseFind-1.0 +Creator: Organization: ExampleCodeInspect () +Creator: Person: Jane Doe () +Created: 2010-01-29T18:30:22Z +CreatorComment: This package has been shipped in source and binary form. +The binaries were created with gcc 4.5.1 and expect to link to +compatible system run time libraries. +LicenseListVersion: 3.9 +## Annotations +Annotator: Person: Jane Doe () +AnnotationDate: 2010-01-29T18:30:22Z +AnnotationComment: Document level annotation +AnnotationType: OTHER +SPDXREF: SPDXRef-DOCUMENT +Annotator: Person: Joe Reviewer +AnnotationDate: 2010-02-10T00:00:00Z +AnnotationComment: This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses +AnnotationType: REVIEW +SPDXREF: SPDXRef-DOCUMENT +Annotator: Person: Suzanne Reviewer +AnnotationDate: 2011-03-13T00:00:00Z +AnnotationComment: Another example reviewer. +AnnotationType: REVIEW +SPDXREF: SPDXRef-DOCUMENT +## Relationships +Relationship: SPDXRef-DOCUMENT CONTAINS SPDXRef-Package +Relationship: SPDXRef-DOCUMENT COPY_OF DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement +Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-File +Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package + +FileName: ./package/foo.c +SPDXID: SPDXRef-File +FileComment: The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. +FileType: SOURCE +FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2758 +FileChecksum: MD5: 624c1abb3664f4b35547e7c73864ad24 +LicenseConcluded: (LGPL-2.0-only OR LicenseRef-2) +LicenseInfoInFile: GPL-2.0-only +LicenseInfoInFile: LicenseRef-2 +LicenseComments: The concluded license was taken from the package level that the file was included in. +FileCopyrightText: Copyright 2008-2010 John Smith +FileNotice: Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the �Software�), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED �AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +FileContributor: The Regents of the University of California +FileContributor: Modified by Paul Mundt lethal@linux-sh.org +FileContributor: IBM Corporation +## Annotations +Annotator: Person: File Commenter +AnnotationDate: 2011-01-29T18:30:22Z +AnnotationComment: File level annotation +AnnotationType: OTHER +SPDXREF: SPDXRef-File +## Relationships +Relationship: SPDXRef-File GENERATED_FROM SPDXRef-fromDoap-0 +## Package Information +PackageName: glibc +SPDXID: SPDXRef-Package +PackageVersion: 2.11.1 +PackageFileName: glibc-2.11.1.tar.gz +PackageSupplier: Person: Jane Doe (jane.doe@example.com) +PackageOriginator: Organization: ExampleCodeInspect (contact@example.com) +PackageDownloadLocation: http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz +PackageVerificationCode: d6a770ba38583ed4bb4525bd96e50461655d2758(./package.spdx) +PackageChecksum: MD5: 624c1abb3664f4b35547e7c73864ad24 +PackageChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c +PackageChecksum: SHA256: 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd +PackageHomePage: http://ftp.gnu.org/gnu/glibc +PackageSourceInfo: uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. +PackageLicenseConcluded: (LGPL-2.0-only OR LicenseRef-3) +## License information from files +PackageLicenseInfoFromFiles: GPL-2.0-only +PackageLicenseInfoFromFiles: LicenseRef-2 +PackageLicenseInfoFromFiles: LicenseRef-1 +PackageLicenseDeclared: (LGPL-2.0-only AND LicenseRef-3) +PackageLicenseComments: The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. +PackageCopyrightText: Copyright 2008-2010 John Smith +PackageSummary: GNU C library. +PackageDescription: The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. +PackageAttributionText: The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. +ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* +ExternalRef: OTHER LocationRef-acmeforge acmecorp/acmenator/4.1.3-alpha +ExternalRefComment: This is the external ref for Acme +## Annotations +Annotator: Person: Package Commenter +AnnotationDate: 2011-01-29T18:30:22Z +AnnotationComment: Package level annotation +AnnotationType: OTHER +SPDXREF: SPDXRef-Package +## Relationships +Relationship: SPDXRef-Package CONTAINS SPDXRef-JenaLib +Relationship: SPDXRef-Package DYNAMIC_LINK SPDXRef-Saxon + +## File Information +FileName: ./lib-source/commons-lang3-3.1-sources.jar +SPDXID: SPDXRef-CommonsLangSrc +FileComment: This file is used by Jena +FileType: ARCHIVE +FileChecksum: SHA1: c2b4e1c67a2d28fced849ee1bb76e7391b93f125 +LicenseConcluded: Apache-2.0 +LicenseInfoInFile: Apache-2.0 +FileCopyrightText: Copyright 2001-2011 The Apache Software Foundation +FileNotice: Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) +FileContributor: Apache Software Foundation +## Relationships +Relationship: SPDXRef-CommonsLangSrc GENERATED_FROM NOASSERTION + +FileName: ./lib-source/jena-2.6.3-sources.jar +SPDXID: SPDXRef-JenaLib +FileComment: This file belongs to Jena +FileType: ARCHIVE +FileChecksum: SHA1: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 +LicenseConcluded: LicenseRef-1 +LicenseInfoInFile: LicenseRef-1 +LicenseComments: This license is used by Jena +FileCopyrightText: (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP +FileContributor: Apache Software Foundation +FileContributor: Hewlett Packard Inc. +## Relationships +Relationship: SPDXRef-JenaLib CONTAINS SPDXRef-Package + +FileName: ./src/org/spdx/parser/DOAPProject.java +SPDXID: SPDXRef-DoapSource +FileType: SOURCE +FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 +LicenseConcluded: Apache-2.0 +LicenseInfoInFile: Apache-2.0 +FileCopyrightText: Copyright 2010, 2011 Source Auditor Inc. +FileContributor: Protecode Inc. +FileContributor: SPDX Technical Team Members +FileContributor: Open Logic Inc. +FileContributor: Source Auditor Inc. +FileContributor: Black Duck Software In.c + +## Package Information +PackageName: Apache Commons Lang +SPDXID: SPDXRef-fromDoap-1 +PackageDownloadLocation: NOASSERTION +PackageHomePage: http://commons.apache.org/proper/commons-lang/ +PackageLicenseConcluded: NOASSERTION +PackageLicenseDeclared: NOASSERTION +PackageCopyrightText: NOASSERTION +FilesAnalyzed: false + +## Package Information +PackageName: Jena +SPDXID: SPDXRef-fromDoap-0 +PackageVersion: 3.12.0 +PackageDownloadLocation: https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz +PackageHomePage: http://www.openjena.org/ +PackageLicenseConcluded: NOASSERTION +PackageLicenseDeclared: NOASSERTION +PackageCopyrightText: NOASSERTION +ExternalRef: PACKAGE-MANAGER purl pkg:maven/org.apache.jena/apache-jena@3.12.0 +FilesAnalyzed: false + +## Package Information +PackageName: Saxon +SPDXID: SPDXRef-Saxon +PackageVersion: 8.8 +PackageFileName: saxonB-8.8.zip +PackageDownloadLocation: https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download +PackageChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c +PackageHomePage: http://saxon.sourceforge.net/ +PackageLicenseConcluded: MPL-1.0 +PackageLicenseDeclared: MPL-1.0 +PackageLicenseComments: Other versions available for a commercial license +PackageCopyrightText: Copyright Saxonica Ltd +PackageDescription: The Saxon package is a collection of tools for processing XML documents. +FilesAnalyzed: false + +## Snippet Information +SnippetSPDXID: SPDXRef-Snippet +SnippetFromFileSPDXID: SPDXRef-DoapSource +SnippetByteRange: 310:420 +SnippetLineRange: 5:23 +SnippetLicenseConcluded: GPL-2.0-only +LicenseInfoInSnippet: GPL-2.0-only +SnippetLicenseComments: The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. +SnippetCopyrightText: Copyright 2008-2010 John Smith +SnippetComment: This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. +SnippetName: from linux kernel + + +## License Information +LicenseID: LicenseRef-1 +ExtractedText: /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +LicenseID: LicenseRef-2 +ExtractedText: This package includes the GRDDL parser developed by Hewlett Packard under the following license: +� Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +LicenseID: LicenseRef-4 +ExtractedText: /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +LicenseID: LicenseRef-Beerware-4.2 +ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp +LicenseName: Beer-Ware License (Version 42) +LicenseCrossReference: http://people.freebsd.org/~phk/ +LicenseComment: The beerware license has a couple of other standard variants. + +LicenseID: LicenseRef-3 +ExtractedText: The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +LicenseName: CyberNeko License +LicenseCrossReference: http://people.apache.org/~andyc/neko/LICENSE, http://justasample.url.com +LicenseComment: This is tye CyperNeko License + diff --git a/tests/spdx/data/SPDXTagExample-v2.3.spdx b/tests/spdx/data/SPDXTagExample-v2.3.spdx new file mode 100644 index 000000000..b84a97a76 --- /dev/null +++ b/tests/spdx/data/SPDXTagExample-v2.3.spdx @@ -0,0 +1,340 @@ +SPDXVersion: SPDX-2.3 +DataLicense: CC0-1.0 +DocumentNamespace: http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 +DocumentName: SPDX-Tools-v2.0 +SPDXID: SPDXRef-DOCUMENT +DocumentComment: This document was created using SPDX 2.0 using licenses from the web site. + +## External Document References +ExternalDocumentRef: DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759 +## Creation Information +Creator: Tool: LicenseFind-1.0 +Creator: Organization: ExampleCodeInspect () +Creator: Person: Jane Doe () +Created: 2010-01-29T18:30:22Z +CreatorComment: This package has been shipped in source and binary form. +The binaries were created with gcc 4.5.1 and expect to link to +compatible system run time libraries. +LicenseListVersion: 3.17 +## Annotations +Annotator: Person: Jane Doe () +AnnotationDate: 2010-01-29T18:30:22Z +AnnotationComment: Document level annotation +AnnotationType: OTHER +SPDXREF: SPDXRef-DOCUMENT +Annotator: Person: Joe Reviewer +AnnotationDate: 2010-02-10T00:00:00Z +AnnotationComment: This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses +AnnotationType: REVIEW +SPDXREF: SPDXRef-DOCUMENT +Annotator: Person: Suzanne Reviewer +AnnotationDate: 2011-03-13T00:00:00Z +AnnotationComment: Another example reviewer. +AnnotationType: REVIEW +SPDXREF: SPDXRef-DOCUMENT +## Relationships +Relationship: SPDXRef-DOCUMENT CONTAINS SPDXRef-Package +Relationship: SPDXRef-DOCUMENT COPY_OF DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement +Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-File +Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package + +FileName: ./package/foo.c +SPDXID: SPDXRef-File +FileComment: The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. +FileType: SOURCE +FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2758 +FileChecksum: MD5: 624c1abb3664f4b35547e7c73864ad24 +LicenseConcluded: (LGPL-2.0-only OR LicenseRef-2) +LicenseInfoInFile: GPL-2.0-only +LicenseInfoInFile: LicenseRef-2 +LicenseComments: The concluded license was taken from the package level that the file was included in. +FileCopyrightText: Copyright 2008-2010 John Smith +FileNotice: Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +FileContributor: The Regents of the University of California +FileContributor: Modified by Paul Mundt lethal@linux-sh.org +FileContributor: IBM Corporation +## Annotations +Annotator: Person: File Commenter +AnnotationDate: 2011-01-29T18:30:22Z +AnnotationComment: File level annotation +AnnotationType: OTHER +SPDXREF: SPDXRef-File +## Relationships +Relationship: SPDXRef-File GENERATED_FROM SPDXRef-fromDoap-0 +## Package Information +PackageName: glibc +SPDXID: SPDXRef-Package +PackageVersion: 2.11.1 +PackageFileName: glibc-2.11.1.tar.gz +PackageSupplier: Person: Jane Doe (jane.doe@example.com) +PackageOriginator: Organization: ExampleCodeInspect (contact@example.com) +PackageDownloadLocation: http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz +PackageVerificationCode: d6a770ba38583ed4bb4525bd96e50461655d2758(./package.spdx) +PackageChecksum: MD5: 624c1abb3664f4b35547e7c73864ad24 +PackageChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c +PackageChecksum: SHA256: 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd +PackageChecksum: BLAKE2b-384: aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706 +PackageHomePage: http://ftp.gnu.org/gnu/glibc +PackageSourceInfo: uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. +PrimaryPackagePurpose: SOURCE +BuiltDate: 2011-01-29T18:30:22Z +ReleaseDate: 2012-01-29T18:30:22Z +ValidUntilDate: 2014-01-29T18:30:22Z +PackageLicenseConcluded: (LGPL-2.0-only OR LicenseRef-3) +## License information from files +PackageLicenseInfoFromFiles: GPL-2.0-only +PackageLicenseInfoFromFiles: LicenseRef-2 +PackageLicenseInfoFromFiles: LicenseRef-1 +PackageLicenseDeclared: (LGPL-2.0-only AND LicenseRef-3) +PackageLicenseComments: The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. +PackageCopyrightText: Copyright 2008-2010 John Smith +PackageSummary: GNU C library. +PackageDescription: The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. +PackageAttributionText: The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. +ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* +ExternalRef: OTHER LocationRef-acmeforge acmecorp/acmenator/4.1.3-alpha +ExternalRefComment: This is the external ref for Acme +## Annotations +Annotator: Person: Package Commenter +AnnotationDate: 2011-01-29T18:30:22Z +AnnotationComment: Package level annotation +AnnotationType: OTHER +SPDXREF: SPDXRef-Package +## Relationships +Relationship: SPDXRef-Package CONTAINS SPDXRef-JenaLib +Relationship: SPDXRef-Package DYNAMIC_LINK SPDXRef-Saxon + +## File Information +FileName: ./docs/myspec.pdf +SPDXID: SPDXRef-Specification +FileComment: Specification Documentation +FileType: DOCUMENTATION +FileChecksum: SHA1: fff4e1c67a2d28fced849ee1bb76e7391b93f125 +Relationship: SPDXRef-Specification SPECIFICATION_FOR SPDXRef-fromDoap-0 + +## File Information +FileName: ./lib-source/commons-lang3-3.1-sources.jar +SPDXID: SPDXRef-CommonsLangSrc +FileComment: This file is used by Jena +FileType: ARCHIVE +FileChecksum: SHA1: c2b4e1c67a2d28fced849ee1bb76e7391b93f125 +LicenseConcluded: Apache-2.0 +LicenseInfoInFile: Apache-2.0 +FileCopyrightText: Copyright 2001-2011 The Apache Software Foundation +FileNotice: Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) +FileContributor: Apache Software Foundation +## Relationships +Relationship: SPDXRef-CommonsLangSrc GENERATED_FROM NOASSERTION + +FileName: ./lib-source/jena-2.6.3-sources.jar +SPDXID: SPDXRef-JenaLib +FileComment: This file belongs to Jena +FileType: ARCHIVE +FileChecksum: SHA1: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 +LicenseConcluded: LicenseRef-1 +LicenseInfoInFile: LicenseRef-1 +LicenseComments: This license is used by Jena +FileCopyrightText: (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP +FileContributor: Apache Software Foundation +FileContributor: Hewlett Packard Inc. +## Relationships +Relationship: SPDXRef-JenaLib CONTAINS SPDXRef-Package + +FileName: ./src/org/spdx/parser/DOAPProject.java +SPDXID: SPDXRef-DoapSource +FileType: SOURCE +FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 +LicenseConcluded: Apache-2.0 +LicenseInfoInFile: Apache-2.0 +FileCopyrightText: Copyright 2010, 2011 Source Auditor Inc. +FileContributor: Protecode Inc. +FileContributor: SPDX Technical Team Members +FileContributor: Open Logic Inc. +FileContributor: Source Auditor Inc. +FileContributor: Black Duck Software In.c + +## Package Information +PackageName: Apache Commons Lang +SPDXID: SPDXRef-fromDoap-1 +PackageDownloadLocation: NOASSERTION +PackageHomePage: http://commons.apache.org/proper/commons-lang/ +PackageLicenseConcluded: NOASSERTION +PackageLicenseDeclared: NOASSERTION +PackageCopyrightText: NOASSERTION +FilesAnalyzed: false + +## Package Information +PackageName: Jena +SPDXID: SPDXRef-fromDoap-0 +PackageVersion: 3.12.0 +PackageDownloadLocation: https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz +PackageHomePage: http://www.openjena.org/ +ExternalRef: PACKAGE-MANAGER purl pkg:maven/org.apache.jena/apache-jena@3.12.0 +FilesAnalyzed: false + +## Package Information +PackageName: Saxon +SPDXID: SPDXRef-Saxon +PackageVersion: 8.8 +PackageFileName: saxonB-8.8.zip +PackageDownloadLocation: https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download +PackageChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c +PackageHomePage: http://saxon.sourceforge.net/ +PackageLicenseConcluded: MPL-1.0 +PackageLicenseDeclared: MPL-1.0 +PackageLicenseComments: Other versions available for a commercial license +PackageCopyrightText: Copyright Saxonica Ltd +PackageDescription: The Saxon package is a collection of tools for processing XML documents. +FilesAnalyzed: false + +## Snippet Information +SnippetSPDXID: SPDXRef-Snippet +SnippetFromFileSPDXID: SPDXRef-DoapSource +SnippetByteRange: 310:420 +SnippetLineRange: 5:23 +SnippetLicenseConcluded: GPL-2.0-only +LicenseInfoInSnippet: GPL-2.0-only +SnippetLicenseComments: The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. +SnippetCopyrightText: Copyright 2008-2010 John Smith +SnippetComment: This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. +SnippetName: from linux kernel + + +## License Information +LicenseID: LicenseRef-1 +ExtractedText: /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +LicenseID: LicenseRef-2 +ExtractedText: This package includes the GRDDL parser developed by Hewlett Packard under the following license: +© Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +LicenseID: LicenseRef-4 +ExtractedText: /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +LicenseID: LicenseRef-Beerware-4.2 +ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp +LicenseName: Beer-Ware License (Version 42) +LicenseCrossReference: http://people.freebsd.org/~phk/ +LicenseComment: The beerware license has a couple of other standard variants. + +LicenseID: LicenseRef-3 +ExtractedText: The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +LicenseName: CyberNeko License +LicenseCrossReference: http://people.apache.org/~andyc/neko/LICENSE +LicenseCrossReference: http://justasample.url.com +LicenseComment: This is tye CyperNeko License + diff --git a/tests/spdx/data/SPDXXMLExample-UTF-16.spdx.xml b/tests/spdx/data/SPDXXMLExample-UTF-16.spdx.xml new file mode 100644 index 000000000..9e417c69a Binary files /dev/null and b/tests/spdx/data/SPDXXMLExample-UTF-16.spdx.xml differ diff --git a/tests/spdx/data/SPDXXMLExample-v2.2.spdx.xml b/tests/spdx/data/SPDXXMLExample-v2.2.spdx.xml new file mode 100644 index 000000000..80e0527a2 --- /dev/null +++ b/tests/spdx/data/SPDXXMLExample-v2.2.spdx.xml @@ -0,0 +1,443 @@ + + + SPDXRef-DOCUMENT + SPDX-2.2 + + This package has been shipped in source and binary form. +The binaries were created with gcc 4.5.1 and expect to link to +compatible system run time libraries. + 2010-01-29T18:30:22Z + Tool: LicenseFind-1.0 + Organization: ExampleCodeInspect () + Person: Jane Doe () + 3.9 + + SPDX-Tools-v2.0 + CC0-1.0 + This document was created using SPDX 2.0 using licenses from the web site. + + DocumentRef-spdx-tool-1.2 + + SHA1 + d6a770ba38583ed4bb4525bd96e50461655d2759 + + http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 + + + LicenseRef-1 + /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + LicenseRef-2 + This package includes the GRDDL parser developed by Hewlett Packard under the following license: +� Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + LicenseRef-4 + /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + LicenseRef-Beerware-4.2 + The beerware license has a couple of other standard variants. + "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp + Beer-Ware License (Version 42) + http://people.freebsd.org/~phk/ + + + LicenseRef-3 + This is tye CyperNeko License + The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + CyberNeko License + http://people.apache.org/~andyc/neko/LICENSE + http://justasample.url.com + + + 2010-01-29T18:30:22Z + OTHER + Person: Jane Doe () + Document level annotation + + + 2010-02-10T00:00:00Z + REVIEW + Person: Joe Reviewer + This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses + + + 2011-03-13T00:00:00Z + REVIEW + Person: Suzanne Reviewer + Another example reviewer. + + http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 + SPDXRef-File + SPDXRef-Package + + SPDXRef-Package + + 2011-01-29T18:30:22Z + OTHER + Person: Package Commenter + Package level annotation + + The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. + + MD5 + 624c1abb3664f4b35547e7c73864ad24 + + + SHA1 + 85ed0817af83a24ad8da68c2b5094de69833983c + + + SHA256 + 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd + + Copyright 2008-2010 John Smith + The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. + http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz + + SECURITY + cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* + cpe23Type + + + This is the external ref for Acme + OTHER + acmecorp/acmenator/4.1.3-alpha + http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge + + true + SPDXRef-CommonsLangSrc + SPDXRef-JenaLib + SPDXRef-DoapSource + http://ftp.gnu.org/gnu/glibc + The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. + (LGPL-2.0-only OR LicenseRef-3) + (LGPL-2.0-only AND LicenseRef-3) + GPL-2.0-only + LicenseRef-2 + LicenseRef-1 + glibc + Organization: ExampleCodeInspect (contact@example.com) + glibc-2.11.1.tar.gz + + ./package.spdx + d6a770ba38583ed4bb4525bd96e50461655d2758 + + uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. + GNU C library. + Person: Jane Doe (jane.doe@example.com) + 2.11.1 + + + SPDXRef-fromDoap-1 + NOASSERTION + NOASSERTION + false + http://commons.apache.org/proper/commons-lang/ + NOASSERTION + NOASSERTION + Apache Commons Lang + + + SPDXRef-fromDoap-0 + NOASSERTION + https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz + + PACKAGE_MANAGER + pkg:maven/org.apache.jena/apache-jena@3.12.0 + purl + + false + http://www.openjena.org/ + NOASSERTION + NOASSERTION + Jena + 3.12.0 + + + SPDXRef-Saxon + + SHA1 + 85ed0817af83a24ad8da68c2b5094de69833983c + + Copyright Saxonica Ltd + The Saxon package is a collection of tools for processing XML documents. + https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download + false + http://saxon.sourceforge.net/ + Other versions available for a commercial license + MPL-1.0 + MPL-1.0 + Saxon + saxonB-8.8.zip + 8.8 + + + SPDXRef-DoapSource + + SHA1 + 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 + + Copyright 2010, 2011 Source Auditor Inc. + Protecode Inc. + SPDX Technical Team Members + Open Logic Inc. + Source Auditor Inc. + Black Duck Software In.c + ./src/org/spdx/parser/DOAPProject.java + SOURCE + Apache-2.0 + Apache-2.0 + + + SPDXRef-CommonsLangSrc + + SHA1 + c2b4e1c67a2d28fced849ee1bb76e7391b93f125 + + This file is used by Jena + Copyright 2001-2011 The Apache Software Foundation + Apache Software Foundation + ./lib-source/commons-lang3-3.1-sources.jar + ARCHIVE + Apache-2.0 + Apache-2.0 + Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) + + + SPDXRef-JenaLib + + SHA1 + 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 + + This file belongs to Jena + (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + Apache Software Foundation + Hewlett Packard Inc. + ./lib-source/jena-2.6.3-sources.jar + ARCHIVE + This license is used by Jena + LicenseRef-1 + LicenseRef-1 + + + SPDXRef-File + + 2011-01-29T18:30:22Z + OTHER + Person: File Commenter + File level annotation + + + SHA1 + d6a770ba38583ed4bb4525bd96e50461655d2758 + + + MD5 + 624c1abb3664f4b35547e7c73864ad24 + + The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. + Copyright 2008-2010 John Smith + The Regents of the University of California + Modified by Paul Mundt lethal@linux-sh.org + IBM Corporation + ./package/foo.c + SOURCE + The concluded license was taken from the package level that the file was included in. + (LGPL-2.0-only OR LicenseRef-2) + GPL-2.0-only + LicenseRef-2 + Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the �Software�), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED �AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + SPDXRef-Snippet + This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. + Copyright 2008-2010 John Smith + The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. + GPL-2.0-only + GPL-2.0-only + from linux kernel + + + 420 + SPDXRef-DoapSource + + + 310 + SPDXRef-DoapSource + + + + + 23 + SPDXRef-DoapSource + + + 5 + SPDXRef-DoapSource + + + SPDXRef-DoapSource + + + SPDXRef-DOCUMENT + SPDXRef-Package + CONTAINS + + + SPDXRef-DOCUMENT + DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement + COPY_OF + + + SPDXRef-DOCUMENT + SPDXRef-File + DESCRIBES + + + SPDXRef-DOCUMENT + SPDXRef-Package + DESCRIBES + + + SPDXRef-Package + SPDXRef-JenaLib + CONTAINS + + + SPDXRef-Package + SPDXRef-Saxon + DYNAMIC_LINK + + + SPDXRef-CommonsLangSrc + NOASSERTION + GENERATED_FROM + + + SPDXRef-JenaLib + SPDXRef-Package + CONTAINS + + + SPDXRef-File + SPDXRef-fromDoap-0 + GENERATED_FROM + + diff --git a/tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml b/tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml new file mode 100644 index 000000000..ce25dbc09 --- /dev/null +++ b/tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml @@ -0,0 +1,460 @@ + + + SPDXRef-DOCUMENT + SPDX-2.3 + + This package has been shipped in source and binary form. +The binaries were created with gcc 4.5.1 and expect to link to +compatible system run time libraries. + 2010-01-29T18:30:22Z + Tool: LicenseFind-1.0 + Organization: ExampleCodeInspect () + Person: Jane Doe () + 3.17 + + SPDX-Tools-v2.0 + CC0-1.0 + This document was created using SPDX 2.0 using licenses from the web site. + + DocumentRef-spdx-tool-1.2 + + SHA1 + d6a770ba38583ed4bb4525bd96e50461655d2759 + + http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 + + + LicenseRef-1 + /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + LicenseRef-2 + This package includes the GRDDL parser developed by Hewlett Packard under the following license: +© Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + LicenseRef-4 + /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + LicenseRef-Beerware-4.2 + The beerware license has a couple of other standard variants. + "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp + Beer-Ware License (Version 42) + http://people.freebsd.org/~phk/ + + + LicenseRef-3 + This is tye CyperNeko License + The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + CyberNeko License + http://people.apache.org/~andyc/neko/LICENSE + http://justasample.url.com + + + 2010-01-29T18:30:22Z + OTHER + Person: Jane Doe () + Document level annotation + + + 2010-02-10T00:00:00Z + REVIEW + Person: Joe Reviewer + This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses + + + 2011-03-13T00:00:00Z + REVIEW + Person: Suzanne Reviewer + Another example reviewer. + + SPDXRef-File + SPDXRef-File + SPDXRef-Package + http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 + + SPDXRef-Package + + 2011-01-29T18:30:22Z + OTHER + Person: Package Commenter + Package level annotation + + The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. + 2011-01-29T18:30:22Z + + MD5 + 624c1abb3664f4b35547e7c73864ad24 + + + SHA1 + 85ed0817af83a24ad8da68c2b5094de69833983c + + + SHA256 + 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd + + + BLAKE2b-384 + aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706 + + Copyright 2008-2010 John Smith + The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. + http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz + + SECURITY + cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* + cpe23Type + + + This is the external ref for Acme + OTHER + acmecorp/acmenator/4.1.3-alpha + http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge + + true + http://ftp.gnu.org/gnu/glibc + The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. + (LGPL-2.0-only OR LicenseRef-3) + (LGPL-2.0-only AND LicenseRef-3) + GPL-2.0-only + LicenseRef-2 + LicenseRef-1 + glibc + Organization: ExampleCodeInspect (contact@example.com) + glibc-2.11.1.tar.gz + + ./package.spdx + d6a770ba38583ed4bb4525bd96e50461655d2758 + + SOURCE + SPDXRef-Specification + SPDXRef-Specification + SPDXRef-CommonsLangSrc + SPDXRef-Specification + SPDXRef-CommonsLangSrc + SPDXRef-JenaLib + SPDXRef-Specification + SPDXRef-CommonsLangSrc + SPDXRef-JenaLib + SPDXRef-DoapSource + SPDXRef-Specification + SPDXRef-CommonsLangSrc + SPDXRef-JenaLib + SPDXRef-DoapSource + 2012-01-29T18:30:22Z + uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. + GNU C library. + Person: Jane Doe (jane.doe@example.com) + 2014-01-29T18:30:22Z + 2.11.1 + + + SPDXRef-fromDoap-1 + NOASSERTION + NOASSERTION + false + http://commons.apache.org/proper/commons-lang/ + NOASSERTION + NOASSERTION + Apache Commons Lang + + + SPDXRef-fromDoap-0 + https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz + + PACKAGE-MANAGER + pkg:maven/org.apache.jena/apache-jena@3.12.0 + purl + + false + http://www.openjena.org/ + Jena + 3.12.0 + + + SPDXRef-Saxon + + SHA1 + 85ed0817af83a24ad8da68c2b5094de69833983c + + Copyright Saxonica Ltd + The Saxon package is a collection of tools for processing XML documents. + https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download + false + http://saxon.sourceforge.net/ + Other versions available for a commercial license + MPL-1.0 + MPL-1.0 + Saxon + saxonB-8.8.zip + 8.8 + + + SPDXRef-DoapSource + + SHA1 + 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 + + Copyright 2010, 2011 Source Auditor Inc. + Protecode Inc. + SPDX Technical Team Members + Open Logic Inc. + Source Auditor Inc. + Black Duck Software In.c + ./src/org/spdx/parser/DOAPProject.java + SOURCE + Apache-2.0 + Apache-2.0 + + + SPDXRef-CommonsLangSrc + + SHA1 + c2b4e1c67a2d28fced849ee1bb76e7391b93f125 + + This file is used by Jena + Copyright 2001-2011 The Apache Software Foundation + Apache Software Foundation + ./lib-source/commons-lang3-3.1-sources.jar + ARCHIVE + Apache-2.0 + Apache-2.0 + Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) + + + SPDXRef-JenaLib + + SHA1 + 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 + + This file belongs to Jena + (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + Apache Software Foundation + Hewlett Packard Inc. + ./lib-source/jena-2.6.3-sources.jar + ARCHIVE + This license is used by Jena + LicenseRef-1 + LicenseRef-1 + + + SPDXRef-Specification + + SHA1 + fff4e1c67a2d28fced849ee1bb76e7391b93f125 + + Specification Documentation + ./docs/myspec.pdf + DOCUMENTATION + + + SPDXRef-File + + 2011-01-29T18:30:22Z + OTHER + Person: File Commenter + File level annotation + + + SHA1 + d6a770ba38583ed4bb4525bd96e50461655d2758 + + + MD5 + 624c1abb3664f4b35547e7c73864ad24 + + The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. + Copyright 2008-2010 John Smith + The Regents of the University of California + Modified by Paul Mundt lethal@linux-sh.org + IBM Corporation + ./package/foo.c + SOURCE + The concluded license was taken from the package level that the file was included in. + (LGPL-2.0-only OR LicenseRef-2) + GPL-2.0-only + LicenseRef-2 + Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + SPDXRef-Snippet + This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. + Copyright 2008-2010 John Smith + The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. + GPL-2.0-only + GPL-2.0-only + from linux kernel + + + 420 + SPDXRef-DoapSource + + + 310 + SPDXRef-DoapSource + + + + + 23 + SPDXRef-DoapSource + + + 5 + SPDXRef-DoapSource + + + SPDXRef-DoapSource + + + SPDXRef-DOCUMENT + CONTAINS + SPDXRef-Package + + + SPDXRef-DOCUMENT + COPY_OF + DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement + + + SPDXRef-Package + DYNAMIC_LINK + SPDXRef-Saxon + + + SPDXRef-CommonsLangSrc + GENERATED_FROM + NOASSERTION + + + SPDXRef-JenaLib + CONTAINS + SPDXRef-Package + + + SPDXRef-Specification + SPECIFICATION_FOR + SPDXRef-fromDoap-0 + + + SPDXRef-File + GENERATED_FROM + SPDXRef-fromDoap-0 + + diff --git a/tests/spdx/data/SPDXYAMLExample-UTF-16.spdx.yaml b/tests/spdx/data/SPDXYAMLExample-UTF-16.spdx.yaml new file mode 100644 index 000000000..d951651c7 Binary files /dev/null and b/tests/spdx/data/SPDXYAMLExample-UTF-16.spdx.yaml differ diff --git a/tests/spdx/data/SPDXYAMLExample-v2.2.spdx.yaml b/tests/spdx/data/SPDXYAMLExample-v2.2.spdx.yaml new file mode 100644 index 000000000..d58cf229c --- /dev/null +++ b/tests/spdx/data/SPDXYAMLExample-v2.2.spdx.yaml @@ -0,0 +1,390 @@ +--- +SPDXID: "SPDXRef-DOCUMENT" +spdxVersion: "SPDX-2.2" +creationInfo: + comment: "This package has been shipped in source and binary form.\nThe binaries\ + \ were created with gcc 4.5.1 and expect to link to\ncompatible system run time\ + \ libraries." + created: "2010-01-29T18:30:22Z" + creators: + - "Tool: LicenseFind-1.0" + - "Organization: ExampleCodeInspect ()" + - "Person: Jane Doe ()" + licenseListVersion: "3.9" +name: "SPDX-Tools-v2.0" +dataLicense: "CC0-1.0" +comment: "This document was created using SPDX 2.0 using licenses from the web site." +externalDocumentRefs: +- externalDocumentId: "DocumentRef-spdx-tool-1.2" + checksum: + algorithm: "SHA1" + checksumValue: "d6a770ba38583ed4bb4525bd96e50461655d2759" + spdxDocument: "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301" +hasExtractedLicensingInfos: +- licenseId: "LicenseRef-1" + extractedText: "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,\ + \ 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n\ + \ *\n * Redistribution and use in source and binary forms, with or without\n *\ + \ modification, are permitted provided that the following conditions\n * are met:\n\ + \ * 1. Redistributions of source code must retain the above copyright\n * notice,\ + \ this list of conditions and the following disclaimer.\n * 2. Redistributions\ + \ in binary form must reproduce the above copyright\n * notice, this list of\ + \ conditions and the following disclaimer in the\n * documentation and/or other\ + \ materials provided with the distribution.\n * 3. The name of the author may\ + \ not be used to endorse or promote products\n * derived from this software\ + \ without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED\ + \ BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS\ + \ FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE\ + \ LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\ + \ DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\ + \ OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\ + \ CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\ + \ OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ + \ USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ + */" +- licenseId: "LicenseRef-2" + extractedText: "This package includes the GRDDL parser developed by Hewlett Packard\ + \ under the following license:\n� Copyright 2007 Hewlett-Packard Development Company,\ + \ LP\n\nRedistribution and use in source and binary forms, with or without modification,\ + \ are permitted provided that the following conditions are met: \n\nRedistributions\ + \ of source code must retain the above copyright notice, this list of conditions\ + \ and the following disclaimer. \nRedistributions in binary form must reproduce\ + \ the above copyright notice, this list of conditions and the following disclaimer\ + \ in the documentation and/or other materials provided with the distribution.\ + \ \nThe name of the author may not be used to endorse or promote products derived\ + \ from this software without specific prior written permission. \nTHIS SOFTWARE\ + \ IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\ + \ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE\ + \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\ + \ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\ + \ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\ + \ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\ + \ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\ + \ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +- licenseId: "LicenseRef-4" + extractedText: "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n\ + \ *\n * Redistribution and use in source and binary forms, with or without\n *\ + \ modification, are permitted provided that the following conditions\n * are met:\n\ + \ * 1. Redistributions of source code must retain the above copyright\n * notice,\ + \ this list of conditions and the following disclaimer.\n * 2. Redistributions\ + \ in binary form must reproduce the above copyright\n * notice, this list of\ + \ conditions and the following disclaimer in the\n * documentation and/or other\ + \ materials provided with the distribution.\n * 3. The name of the author may\ + \ not be used to endorse or promote products\n * derived from this software\ + \ without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED\ + \ BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS\ + \ FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE\ + \ LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\ + \ DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\ + \ OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\ + \ CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\ + \ OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ + \ USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ + */" +- licenseId: "LicenseRef-Beerware-4.2" + comment: "The beerware license has a couple of other standard variants." + extractedText: "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote\ + \ this file. As long as you retain this notice you\ncan do whatever you want with\ + \ this stuff. If we meet some day, and you think this stuff is worth it, you can\ + \ buy me a beer in return Poul-Henning Kamp" + name: "Beer-Ware License (Version 42)" + seeAlsos: + - "http://people.freebsd.org/~phk/" +- licenseId: "LicenseRef-3" + comment: "This is tye CyperNeko License" + extractedText: "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright\ + \ 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source\ + \ and binary forms, with or without\nmodification, are permitted provided that\ + \ the following conditions\nare met:\n\n1. Redistributions of source code must\ + \ retain the above copyright\n notice, this list of conditions and the following\ + \ disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n\ + \ notice, this list of conditions and the following disclaimer in\n the documentation\ + \ and/or other materials provided with the\n distribution.\n\n3. The end-user\ + \ documentation included with the redistribution,\n if any, must include the\ + \ following acknowledgment: \n \"This product includes software developed\ + \ by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software\ + \ itself,\n if and wherever such third-party acknowledgments normally appear.\n\ + \n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n \ + \ or promote products derived from this software without prior \n written permission.\ + \ For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products\ + \ derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\"\ + \ appear in their name, without prior written\n permission of the author.\n\n\ + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES,\ + \ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND\ + \ FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR\ + \ OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\ + \ EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\ + \ \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS\ + \ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT,\ + \ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY\ + \ WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF\ + \ SUCH DAMAGE." + name: "CyberNeko License" + seeAlsos: + - "http://people.apache.org/~andyc/neko/LICENSE" + - "http://justasample.url.com" +annotations: +- annotationDate: "2010-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: Jane Doe ()" + comment: "Document level annotation" +- annotationDate: "2010-02-10T00:00:00Z" + annotationType: "REVIEW" + annotator: "Person: Joe Reviewer" + comment: "This is just an example. Some of the non-standard licenses look like\ + \ they are actually BSD 3 clause licenses" +- annotationDate: "2011-03-13T00:00:00Z" + annotationType: "REVIEW" + annotator: "Person: Suzanne Reviewer" + comment: "Another example reviewer." +documentNamespace: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" +documentDescribes: +- "SPDXRef-File" +- "SPDXRef-Package" +packages: +- SPDXID: "SPDXRef-Package" + annotations: + - annotationDate: "2011-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: Package Commenter" + comment: "Package level annotation" + attributionTexts: + - "The GNU C Library is free software. See the file COPYING.LIB for copying conditions,\ + \ and LICENSES for notices about a few contributions that require these additional\ + \ notices to be distributed. License copyright years may be listed using range\ + \ notation, e.g., 1996-2015, indicating that every year in the range, inclusive,\ + \ is a copyrightable year that would otherwise be listed individually." + checksums: + - algorithm: "MD5" + checksumValue: "624c1abb3664f4b35547e7c73864ad24" + - algorithm: "SHA1" + checksumValue: "85ed0817af83a24ad8da68c2b5094de69833983c" + - algorithm: "SHA256" + checksumValue: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd" + copyrightText: "Copyright 2008-2010 John Smith" + description: "The GNU C Library defines functions that are specified by the ISO\ + \ C standard, as well as additional features specific to POSIX and other derivatives\ + \ of the Unix operating system, and extensions specific to GNU systems." + downloadLocation: "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz" + externalRefs: + - referenceCategory: "SECURITY" + referenceLocator: "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*" + referenceType: "cpe23Type" + - comment: "This is the external ref for Acme" + referenceCategory: "OTHER" + referenceLocator: "acmecorp/acmenator/4.1.3-alpha" + referenceType: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge" + filesAnalyzed: true + hasFiles: + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-JenaLib" + - "SPDXRef-DoapSource" + homepage: "http://ftp.gnu.org/gnu/glibc" + licenseComments: "The license for this project changed with the release of version\ + \ x.y. The version of the project included here post-dates the license change." + licenseConcluded: "(LGPL-2.0-only OR LicenseRef-3)" + licenseDeclared: "(LGPL-2.0-only AND LicenseRef-3)" + licenseInfoFromFiles: + - "GPL-2.0-only" + - "LicenseRef-2" + - "LicenseRef-1" + name: "glibc" + originator: "Organization: ExampleCodeInspect (contact@example.com)" + packageFileName: "glibc-2.11.1.tar.gz" + packageVerificationCode: + packageVerificationCodeExcludedFiles: + - "./package.spdx" + packageVerificationCodeValue: "d6a770ba38583ed4bb4525bd96e50461655d2758" + sourceInfo: "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git." + summary: "GNU C library." + supplier: "Person: Jane Doe (jane.doe@example.com)" + versionInfo: "2.11.1" +- SPDXID: "SPDXRef-fromDoap-1" + copyrightText: "NOASSERTION" + downloadLocation: "NOASSERTION" + filesAnalyzed: false + homepage: "http://commons.apache.org/proper/commons-lang/" + licenseConcluded: "NOASSERTION" + licenseDeclared: "NOASSERTION" + name: "Apache Commons Lang" +- SPDXID: "SPDXRef-fromDoap-0" + copyrightText: "NOASSERTION" + downloadLocation: "https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz" + externalRefs: + - referenceCategory: "PACKAGE_MANAGER" + referenceLocator: "pkg:maven/org.apache.jena/apache-jena@3.12.0" + referenceType: "purl" + filesAnalyzed: false + homepage: "http://www.openjena.org/" + licenseConcluded: "NOASSERTION" + licenseDeclared: "NOASSERTION" + name: "Jena" + versionInfo: "3.12.0" +- SPDXID: "SPDXRef-Saxon" + checksums: + - algorithm: "SHA1" + checksumValue: "85ed0817af83a24ad8da68c2b5094de69833983c" + copyrightText: "Copyright Saxonica Ltd" + description: "The Saxon package is a collection of tools for processing XML documents." + downloadLocation: "https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download" + filesAnalyzed: false + homepage: "http://saxon.sourceforge.net/" + licenseComments: "Other versions available for a commercial license" + licenseConcluded: "MPL-1.0" + licenseDeclared: "MPL-1.0" + name: "Saxon" + packageFileName: "saxonB-8.8.zip" + versionInfo: "8.8" +files: +- SPDXID: "SPDXRef-DoapSource" + checksums: + - algorithm: "SHA1" + checksumValue: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" + copyrightText: "Copyright 2010, 2011 Source Auditor Inc." + fileContributors: + - "Protecode Inc." + - "SPDX Technical Team Members" + - "Open Logic Inc." + - "Source Auditor Inc." + - "Black Duck Software In.c" + fileName: "./src/org/spdx/parser/DOAPProject.java" + fileTypes: + - "SOURCE" + licenseConcluded: "Apache-2.0" + licenseInfoInFiles: + - "Apache-2.0" +- SPDXID: "SPDXRef-CommonsLangSrc" + checksums: + - algorithm: "SHA1" + checksumValue: "c2b4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "This file is used by Jena" + copyrightText: "Copyright 2001-2011 The Apache Software Foundation" + fileContributors: + - "Apache Software Foundation" + fileName: "./lib-source/commons-lang3-3.1-sources.jar" + fileTypes: + - "ARCHIVE" + licenseConcluded: "Apache-2.0" + licenseInfoInFiles: + - "Apache-2.0" + noticeText: "Apache Commons Lang\nCopyright 2001-2011 The Apache Software Foundation\n\ + \nThis product includes software developed by\nThe Apache Software Foundation\ + \ (http://www.apache.org/).\n\nThis product includes software from the Spring\ + \ Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())" +- SPDXID: "SPDXRef-JenaLib" + checksums: + - algorithm: "SHA1" + checksumValue: "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "This file belongs to Jena" + copyrightText: "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,\ + \ 2009 Hewlett-Packard Development Company, LP" + fileContributors: + - "Apache Software Foundation" + - "Hewlett Packard Inc." + fileName: "./lib-source/jena-2.6.3-sources.jar" + fileTypes: + - "ARCHIVE" + licenseComments: "This license is used by Jena" + licenseConcluded: "LicenseRef-1" + licenseInfoInFiles: + - "LicenseRef-1" +- SPDXID: "SPDXRef-File" + annotations: + - annotationDate: "2011-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: File Commenter" + comment: "File level annotation" + checksums: + - algorithm: "SHA1" + checksumValue: "d6a770ba38583ed4bb4525bd96e50461655d2758" + - algorithm: "MD5" + checksumValue: "624c1abb3664f4b35547e7c73864ad24" + comment: "The concluded license was taken from the package level that the file was\ + \ included in.\nThis information was found in the COPYING.txt file in the xyz\ + \ directory." + copyrightText: "Copyright 2008-2010 John Smith" + fileContributors: + - "The Regents of the University of California" + - "Modified by Paul Mundt lethal@linux-sh.org" + - "IBM Corporation" + fileName: "./package/foo.c" + fileTypes: + - "SOURCE" + licenseComments: "The concluded license was taken from the package level that the\ + \ file was included in." + licenseConcluded: "(LGPL-2.0-only OR LicenseRef-2)" + licenseInfoInFiles: + - "GPL-2.0-only" + - "LicenseRef-2" + noticeText: "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is\ + \ hereby granted, free of charge, to any person obtaining a copy of this software\ + \ and associated documentation files (the �Software�), to deal in the Software\ + \ without restriction, including without limitation the rights to use, copy, modify,\ + \ merge, publish, distribute, sublicense, and/or sell copies of the Software,\ + \ and to permit persons to whom the Software is furnished to do so, subject to\ + \ the following conditions: \nThe above copyright notice and this permission notice\ + \ shall be included in all copies or substantial portions of the Software.\n\n\ + THE SOFTWARE IS PROVIDED �AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\ + \ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR\ + \ A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\ + \ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\ + \ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\ + \ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." +snippets: +- SPDXID: "SPDXRef-Snippet" + comment: "This snippet was identified as significant and highlighted in this Apache-2.0\ + \ file, when a commercial scanner identified it as being derived from file foo.c\ + \ in package xyz which is licensed under GPL-2.0." + copyrightText: "Copyright 2008-2010 John Smith" + licenseComments: "The concluded license was taken from package xyz, from which the\ + \ snippet was copied into the current file. The concluded license information\ + \ was found in the COPYING.txt file in package xyz." + licenseConcluded: "GPL-2.0-only" + licenseInfoInSnippets: + - "GPL-2.0-only" + name: "from linux kernel" + ranges: + - endPointer: + offset: 420 + reference: "SPDXRef-DoapSource" + startPointer: + offset: 310 + reference: "SPDXRef-DoapSource" + - endPointer: + lineNumber: 23 + reference: "SPDXRef-DoapSource" + startPointer: + lineNumber: 5 + reference: "SPDXRef-DoapSource" + snippetFromFile: "SPDXRef-DoapSource" +relationships: +- spdxElementId: "SPDXRef-DOCUMENT" + relatedSpdxElement: "SPDXRef-Package" + relationshipType: "CONTAINS" +- spdxElementId: "SPDXRef-DOCUMENT" + relatedSpdxElement: "DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement" + relationshipType: "COPY_OF" +- spdxElementId: "SPDXRef-DOCUMENT" + relatedSpdxElement: "SPDXRef-File" + relationshipType: "DESCRIBES" +- spdxElementId: "SPDXRef-DOCUMENT" + relatedSpdxElement: "SPDXRef-Package" + relationshipType: "DESCRIBES" +- spdxElementId: "SPDXRef-Package" + relatedSpdxElement: "SPDXRef-JenaLib" + relationshipType: "CONTAINS" +- spdxElementId: "SPDXRef-Package" + relatedSpdxElement: "SPDXRef-Saxon" + relationshipType: "DYNAMIC_LINK" +- spdxElementId: "SPDXRef-CommonsLangSrc" + relatedSpdxElement: "NOASSERTION" + relationshipType: "GENERATED_FROM" +- spdxElementId: "SPDXRef-JenaLib" + relatedSpdxElement: "SPDXRef-Package" + relationshipType: "CONTAINS" +- spdxElementId: "SPDXRef-File" + relatedSpdxElement: "SPDXRef-fromDoap-0" + relationshipType: "GENERATED_FROM" diff --git a/tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml b/tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml new file mode 100644 index 000000000..9770f71dd --- /dev/null +++ b/tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml @@ -0,0 +1,406 @@ +--- +SPDXID: "SPDXRef-DOCUMENT" +spdxVersion: "SPDX-2.3" +creationInfo: + comment: "This package has been shipped in source and binary form.\nThe binaries\ + \ were created with gcc 4.5.1 and expect to link to\ncompatible system run time\ + \ libraries." + created: "2010-01-29T18:30:22Z" + creators: + - "Tool: LicenseFind-1.0" + - "Organization: ExampleCodeInspect ()" + - "Person: Jane Doe ()" + licenseListVersion: "3.17" +name: "SPDX-Tools-v2.0" +dataLicense: "CC0-1.0" +comment: "This document was created using SPDX 2.0 using licenses from the web site." +externalDocumentRefs: +- externalDocumentId: "DocumentRef-spdx-tool-1.2" + checksum: + algorithm: "SHA1" + checksumValue: "d6a770ba38583ed4bb4525bd96e50461655d2759" + spdxDocument: "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301" +hasExtractedLicensingInfos: +- licenseId: "LicenseRef-1" + extractedText: "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,\ + \ 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n\ + \ *\n * Redistribution and use in source and binary forms, with or without\n *\ + \ modification, are permitted provided that the following conditions\n * are met:\n\ + \ * 1. Redistributions of source code must retain the above copyright\n * notice,\ + \ this list of conditions and the following disclaimer.\n * 2. Redistributions\ + \ in binary form must reproduce the above copyright\n * notice, this list of\ + \ conditions and the following disclaimer in the\n * documentation and/or other\ + \ materials provided with the distribution.\n * 3. The name of the author may\ + \ not be used to endorse or promote products\n * derived from this software\ + \ without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED\ + \ BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS\ + \ FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE\ + \ LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\ + \ DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\ + \ OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\ + \ CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\ + \ OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ + \ USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ + */" +- licenseId: "LicenseRef-2" + extractedText: "This package includes the GRDDL parser developed by Hewlett Packard\ + \ under the following license:\n© Copyright 2007 Hewlett-Packard Development Company,\ + \ LP\n\nRedistribution and use in source and binary forms, with or without modification,\ + \ are permitted provided that the following conditions are met: \n\nRedistributions\ + \ of source code must retain the above copyright notice, this list of conditions\ + \ and the following disclaimer. \nRedistributions in binary form must reproduce\ + \ the above copyright notice, this list of conditions and the following disclaimer\ + \ in the documentation and/or other materials provided with the distribution.\ + \ \nThe name of the author may not be used to endorse or promote products derived\ + \ from this software without specific prior written permission. \nTHIS SOFTWARE\ + \ IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\ + \ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE\ + \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\ + \ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\ + \ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\ + \ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\ + \ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\ + \ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +- licenseId: "LicenseRef-4" + extractedText: "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n\ + \ *\n * Redistribution and use in source and binary forms, with or without\n *\ + \ modification, are permitted provided that the following conditions\n * are met:\n\ + \ * 1. Redistributions of source code must retain the above copyright\n * notice,\ + \ this list of conditions and the following disclaimer.\n * 2. Redistributions\ + \ in binary form must reproduce the above copyright\n * notice, this list of\ + \ conditions and the following disclaimer in the\n * documentation and/or other\ + \ materials provided with the distribution.\n * 3. The name of the author may\ + \ not be used to endorse or promote products\n * derived from this software\ + \ without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED\ + \ BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS\ + \ FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE\ + \ LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\ + \ DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\ + \ OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\ + \ CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\ + \ OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ + \ USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ + */" +- licenseId: "LicenseRef-Beerware-4.2" + comment: "The beerware license has a couple of other standard variants." + extractedText: "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote\ + \ this file. As long as you retain this notice you\ncan do whatever you want with\ + \ this stuff. If we meet some day, and you think this stuff is worth it, you can\ + \ buy me a beer in return Poul-Henning Kamp" + name: "Beer-Ware License (Version 42)" + seeAlsos: + - "http://people.freebsd.org/~phk/" +- licenseId: "LicenseRef-3" + comment: "This is tye CyperNeko License" + extractedText: "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright\ + \ 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source\ + \ and binary forms, with or without\nmodification, are permitted provided that\ + \ the following conditions\nare met:\n\n1. Redistributions of source code must\ + \ retain the above copyright\n notice, this list of conditions and the following\ + \ disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n\ + \ notice, this list of conditions and the following disclaimer in\n the documentation\ + \ and/or other materials provided with the\n distribution.\n\n3. The end-user\ + \ documentation included with the redistribution,\n if any, must include the\ + \ following acknowledgment: \n \"This product includes software developed\ + \ by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software\ + \ itself,\n if and wherever such third-party acknowledgments normally appear.\n\ + \n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n \ + \ or promote products derived from this software without prior \n written permission.\ + \ For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products\ + \ derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\"\ + \ appear in their name, without prior written\n permission of the author.\n\n\ + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES,\ + \ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND\ + \ FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR\ + \ OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\ + \ EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\ + \ \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS\ + \ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT,\ + \ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY\ + \ WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF\ + \ SUCH DAMAGE." + name: "CyberNeko License" + seeAlsos: + - "http://people.apache.org/~andyc/neko/LICENSE" + - "http://justasample.url.com" +annotations: +- annotationDate: "2010-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: Jane Doe ()" + comment: "Document level annotation" +- annotationDate: "2010-02-10T00:00:00Z" + annotationType: "REVIEW" + annotator: "Person: Joe Reviewer" + comment: "This is just an example. Some of the non-standard licenses look like\ + \ they are actually BSD 3 clause licenses" +- annotationDate: "2011-03-13T00:00:00Z" + annotationType: "REVIEW" + annotator: "Person: Suzanne Reviewer" + comment: "Another example reviewer." +documentDescribes: +- "SPDXRef-File" +- "SPDXRef-Package" +documentNamespace: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" +packages: +- SPDXID: "SPDXRef-Package" + annotations: + - annotationDate: "2011-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: Package Commenter" + comment: "Package level annotation" + attributionTexts: + - "The GNU C Library is free software. See the file COPYING.LIB for copying conditions,\ + \ and LICENSES for notices about a few contributions that require these additional\ + \ notices to be distributed. License copyright years may be listed using range\ + \ notation, e.g., 1996-2015, indicating that every year in the range, inclusive,\ + \ is a copyrightable year that would otherwise be listed individually." + builtDate: "2011-01-29T18:30:22Z" + checksums: + - algorithm: "MD5" + checksumValue: "624c1abb3664f4b35547e7c73864ad24" + - algorithm: "SHA1" + checksumValue: "85ed0817af83a24ad8da68c2b5094de69833983c" + - algorithm: "SHA256" + checksumValue: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd" + - algorithm: "BLAKE2b-384" + checksumValue: "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706" + copyrightText: "Copyright 2008-2010 John Smith" + description: "The GNU C Library defines functions that are specified by the ISO\ + \ C standard, as well as additional features specific to POSIX and other derivatives\ + \ of the Unix operating system, and extensions specific to GNU systems." + downloadLocation: "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz" + externalRefs: + - referenceCategory: "SECURITY" + referenceLocator: "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*" + referenceType: "cpe23Type" + - comment: "This is the external ref for Acme" + referenceCategory: "OTHER" + referenceLocator: "acmecorp/acmenator/4.1.3-alpha" + referenceType: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge" + filesAnalyzed: true + homepage: "http://ftp.gnu.org/gnu/glibc" + licenseComments: "The license for this project changed with the release of version\ + \ x.y. The version of the project included here post-dates the license change." + licenseConcluded: "(LGPL-2.0-only OR LicenseRef-3)" + licenseDeclared: "(LGPL-2.0-only AND LicenseRef-3)" + licenseInfoFromFiles: + - "GPL-2.0-only" + - "LicenseRef-2" + - "LicenseRef-1" + name: "glibc" + originator: "Organization: ExampleCodeInspect (contact@example.com)" + packageFileName: "glibc-2.11.1.tar.gz" + packageVerificationCode: + packageVerificationCodeExcludedFiles: + - "./package.spdx" + packageVerificationCodeValue: "d6a770ba38583ed4bb4525bd96e50461655d2758" + primaryPackagePurpose: "SOURCE" + hasFiles: + - "SPDXRef-Specification" + - "SPDXRef-Specification" + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-Specification" + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-JenaLib" + - "SPDXRef-Specification" + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-JenaLib" + - "SPDXRef-DoapSource" + - "SPDXRef-Specification" + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-JenaLib" + - "SPDXRef-DoapSource" + releaseDate: "2012-01-29T18:30:22Z" + sourceInfo: "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git." + summary: "GNU C library." + supplier: "Person: Jane Doe (jane.doe@example.com)" + validUntilDate: "2014-01-29T18:30:22Z" + versionInfo: "2.11.1" +- SPDXID: "SPDXRef-fromDoap-1" + copyrightText: "NOASSERTION" + downloadLocation: "NOASSERTION" + filesAnalyzed: false + homepage: "http://commons.apache.org/proper/commons-lang/" + licenseConcluded: "NOASSERTION" + licenseDeclared: "NOASSERTION" + name: "Apache Commons Lang" +- SPDXID: "SPDXRef-fromDoap-0" + downloadLocation: "https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz" + externalRefs: + - referenceCategory: "PACKAGE-MANAGER" + referenceLocator: "pkg:maven/org.apache.jena/apache-jena@3.12.0" + referenceType: "purl" + filesAnalyzed: false + homepage: "http://www.openjena.org/" + name: "Jena" + versionInfo: "3.12.0" +- SPDXID: "SPDXRef-Saxon" + checksums: + - algorithm: "SHA1" + checksumValue: "85ed0817af83a24ad8da68c2b5094de69833983c" + copyrightText: "Copyright Saxonica Ltd" + description: "The Saxon package is a collection of tools for processing XML documents." + downloadLocation: "https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download" + filesAnalyzed: false + homepage: "http://saxon.sourceforge.net/" + licenseComments: "Other versions available for a commercial license" + licenseConcluded: "MPL-1.0" + licenseDeclared: "MPL-1.0" + name: "Saxon" + packageFileName: "saxonB-8.8.zip" + versionInfo: "8.8" +files: +- SPDXID: "SPDXRef-DoapSource" + checksums: + - algorithm: "SHA1" + checksumValue: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" + copyrightText: "Copyright 2010, 2011 Source Auditor Inc." + fileContributors: + - "Protecode Inc." + - "SPDX Technical Team Members" + - "Open Logic Inc." + - "Source Auditor Inc." + - "Black Duck Software In.c" + fileName: "./src/org/spdx/parser/DOAPProject.java" + fileTypes: + - "SOURCE" + licenseConcluded: "Apache-2.0" + licenseInfoInFiles: + - "Apache-2.0" +- SPDXID: "SPDXRef-CommonsLangSrc" + checksums: + - algorithm: "SHA1" + checksumValue: "c2b4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "This file is used by Jena" + copyrightText: "Copyright 2001-2011 The Apache Software Foundation" + fileContributors: + - "Apache Software Foundation" + fileName: "./lib-source/commons-lang3-3.1-sources.jar" + fileTypes: + - "ARCHIVE" + licenseConcluded: "Apache-2.0" + licenseInfoInFiles: + - "Apache-2.0" + noticeText: "Apache Commons Lang\nCopyright 2001-2011 The Apache Software Foundation\n\ + \nThis product includes software developed by\nThe Apache Software Foundation\ + \ (http://www.apache.org/).\n\nThis product includes software from the Spring\ + \ Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())" +- SPDXID: "SPDXRef-JenaLib" + checksums: + - algorithm: "SHA1" + checksumValue: "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "This file belongs to Jena" + copyrightText: "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,\ + \ 2009 Hewlett-Packard Development Company, LP" + fileContributors: + - "Apache Software Foundation" + - "Hewlett Packard Inc." + fileName: "./lib-source/jena-2.6.3-sources.jar" + fileTypes: + - "ARCHIVE" + licenseComments: "This license is used by Jena" + licenseConcluded: "LicenseRef-1" + licenseInfoInFiles: + - "LicenseRef-1" +- SPDXID: "SPDXRef-Specification" + checksums: + - algorithm: "SHA1" + checksumValue: "fff4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "Specification Documentation" + fileName: "./docs/myspec.pdf" + fileTypes: + - "DOCUMENTATION" +- SPDXID: "SPDXRef-File" + annotations: + - annotationDate: "2011-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: File Commenter" + comment: "File level annotation" + checksums: + - algorithm: "SHA1" + checksumValue: "d6a770ba38583ed4bb4525bd96e50461655d2758" + - algorithm: "MD5" + checksumValue: "624c1abb3664f4b35547e7c73864ad24" + comment: "The concluded license was taken from the package level that the file was\ + \ included in.\nThis information was found in the COPYING.txt file in the xyz\ + \ directory." + copyrightText: "Copyright 2008-2010 John Smith" + fileContributors: + - "The Regents of the University of California" + - "Modified by Paul Mundt lethal@linux-sh.org" + - "IBM Corporation" + fileName: "./package/foo.c" + fileTypes: + - "SOURCE" + licenseComments: "The concluded license was taken from the package level that the\ + \ file was included in." + licenseConcluded: "(LGPL-2.0-only OR LicenseRef-2)" + licenseInfoInFiles: + - "GPL-2.0-only" + - "LicenseRef-2" + noticeText: "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is\ + \ hereby granted, free of charge, to any person obtaining a copy of this software\ + \ and associated documentation files (the \"Software\"), to deal in the Software\ + \ without restriction, including without limitation the rights to use, copy, modify,\ + \ merge, publish, distribute, sublicense, and/or sell copies of the Software,\ + \ and to permit persons to whom the Software is furnished to do so, subject to\ + \ the following conditions: \nThe above copyright notice and this permission notice\ + \ shall be included in all copies or substantial portions of the Software.\n\n\ + THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\ + \ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR\ + \ A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\ + \ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\ + \ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\ + \ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." +snippets: +- SPDXID: "SPDXRef-Snippet" + comment: "This snippet was identified as significant and highlighted in this Apache-2.0\ + \ file, when a commercial scanner identified it as being derived from file foo.c\ + \ in package xyz which is licensed under GPL-2.0." + copyrightText: "Copyright 2008-2010 John Smith" + licenseComments: "The concluded license was taken from package xyz, from which the\ + \ snippet was copied into the current file. The concluded license information\ + \ was found in the COPYING.txt file in package xyz." + licenseConcluded: "GPL-2.0-only" + licenseInfoInSnippets: + - "GPL-2.0-only" + name: "from linux kernel" + ranges: + - endPointer: + offset: 420 + reference: "SPDXRef-DoapSource" + startPointer: + offset: 310 + reference: "SPDXRef-DoapSource" + - endPointer: + lineNumber: 23 + reference: "SPDXRef-DoapSource" + startPointer: + lineNumber: 5 + reference: "SPDXRef-DoapSource" + snippetFromFile: "SPDXRef-DoapSource" +relationships: +- spdxElementId: "SPDXRef-DOCUMENT" + relationshipType: "CONTAINS" + relatedSpdxElement: "SPDXRef-Package" +- spdxElementId: "SPDXRef-DOCUMENT" + relationshipType: "COPY_OF" + relatedSpdxElement: "DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement" +- spdxElementId: "SPDXRef-Package" + relationshipType: "DYNAMIC_LINK" + relatedSpdxElement: "SPDXRef-Saxon" +- spdxElementId: "SPDXRef-CommonsLangSrc" + relationshipType: "GENERATED_FROM" + relatedSpdxElement: "NOASSERTION" +- spdxElementId: "SPDXRef-JenaLib" + relationshipType: "CONTAINS" + relatedSpdxElement: "SPDXRef-Package" +- spdxElementId: "SPDXRef-Specification" + relationshipType: "SPECIFICATION_FOR" + relatedSpdxElement: "SPDXRef-fromDoap-0" +- spdxElementId: "SPDXRef-File" + relationshipType: "GENERATED_FROM" + relatedSpdxElement: "SPDXRef-fromDoap-0" diff --git a/tests/spdx/data/circleConversionTestInitialDocument.json b/tests/spdx/data/circleConversionTestInitialDocument.json new file mode 100644 index 000000000..40e61a19c --- /dev/null +++ b/tests/spdx/data/circleConversionTestInitialDocument.json @@ -0,0 +1,433 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "spdxVersion": "SPDX-2.3", + "creationInfo": { + "comment": "This package has been shipped in source and binary form.\nThe binaries were created with gcc 4.5.1 and expect to link to\ncompatible system run time libraries.", + "created": "2010-01-29T18:30:22Z", + "creators": [ + "Tool: LicenseFind-1.0", + "Organization: ExampleCodeInspect", + "Person: Jane Doe" + ], + "licenseListVersion": "3.17" + }, + "name": "SPDX-Tools-v2.0", + "dataLicense": "CC0-1.0", + "comment": "This document was created using SPDX 2.0 using licenses from the web site.", + "externalDocumentRefs": [ + { + "externalDocumentId": "DocumentRef-spdx-tool-1.2", + "checksum": { + "algorithm": "SHA1", + "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759" + }, + "spdxDocument": "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301" + } + ], + "hasExtractedLicensingInfos": [ + { + "licenseId": "LicenseRef-1", + "extractedText": "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/" + }, + { + "licenseId": "LicenseRef-2", + "extractedText": "This package includes the GRDDL parser developed by Hewlett Packard under the following license:\n© Copyright 2007 Hewlett-Packard Development Company, LP\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: \n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \nThe name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + }, + { + "licenseId": "LicenseRef-4", + "extractedText": "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/" + }, + { + "licenseId": "LicenseRef-Beerware-4.2", + "comment": "The beerware license has a couple of other standard variants.", + "extractedText": "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "name": "Beer-Ware License (Version 42)", + "seeAlsos": [ + "http://people.freebsd.org/~phk/" + ] + }, + { + "licenseId": "LicenseRef-3", + "comment": "This is tye CyperNeko License", + "extractedText": "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the\n distribution.\n\n3. The end-user documentation included with the redistribution,\n if any, must include the following acknowledgment: \n \"This product includes software developed by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software itself,\n if and wherever such third-party acknowledgments normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n or promote products derived from this software without prior \n written permission. For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", + "name": "CyberNeko License", + "seeAlsos": [ + "http://people.apache.org/~andyc/neko/LICENSE", + "http://justasample.url.com" + ] + } + ], + "annotations": [ + { + "annotationDate": "2010-01-29T18:30:22Z", + "annotationType": "OTHER", + "annotator": "Person: Jane Doe", + "comment": "Document level annotation" + }, + { + "annotationDate": "2010-02-10T00:00:00Z", + "annotationType": "REVIEW", + "annotator": "Person: Joe Reviewer", + "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses" + }, + { + "annotationDate": "2011-03-13T00:00:00Z", + "annotationType": "REVIEW", + "annotator": "Person: Suzanne Reviewer", + "comment": "Another example reviewer." + } + ], + "documentNamespace": "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9B0C-0305E82C3301", + "packages": [ + { + "SPDXID": "SPDXRef-Package", + "annotations": [ + { + "annotationDate": "2011-01-29T18:30:22Z", + "annotationType": "OTHER", + "annotator": "Person: Package Commenter", + "comment": "Package level annotation" + } + ], + "attributionTexts": [ + "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually." + ], + "builtDate": "2011-01-29T18:30:22Z", + "checksums": [ + { + "algorithm": "MD5", + "checksumValue": "624c1abb3664f4b35547e7c73864ad24" + }, + { + "algorithm": "SHA1", + "checksumValue": "85ed0817af83a24ad8da68c2b5094de69833983c" + }, + { + "algorithm": "SHA256", + "checksumValue": "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd" + }, + { + "algorithm": "BLAKE2b-384", + "checksumValue": "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706" + } + ], + "copyrightText": "Copyright 2008-2010 John Smith", + "description": "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems.", + "downloadLocation": "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "comment": "This is the external ref for Acme", + "referenceCategory": "OTHER", + "referenceLocator": "acmecorp/acmenator/4.1.3-alpha", + "referenceType": "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge" + } + ], + "filesAnalyzed": true, + "homepage": "http://ftp.gnu.org/gnu/glibc", + "licenseComments": "The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change.", + "licenseConcluded": "LGPL-2.0-only", + "licenseDeclared": "LicenseRef-3", + "licenseInfoFromFiles": [ + "GPL-2.0-only", + "LicenseRef-2", + "LicenseRef-1" + ], + "name": "glibc", + "originator": "Organization: ExampleCodeInspect (contact@example.com)", + "packageFileName": "glibc-2.11.1.tar.gz", + "packageVerificationCode": { + "packageVerificationCodeExcludedFiles": [ + "./package.spdx" + ], + "packageVerificationCodeValue": "d6a770ba38583ed4bb4525bd96e50461655d2758" + }, + "primaryPackagePurpose": "SOURCE", + "releaseDate": "2012-01-29T18:30:22Z", + "sourceInfo": "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git.", + "summary": "GNU C library.", + "supplier": "Person: Jane Doe (jane.doe@example.com)", + "validUntilDate": "2014-01-29T18:30:22Z", + "versionInfo": "2.11.1" + }, + { + "SPDXID": "SPDXRef-fromDoap-1", + "copyrightText": "NOASSERTION", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "homepage": "http://commons.apache.org/proper/commons-lang/", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "NOASSERTION", + "name": "Apache Commons Lang" + }, + { + "SPDXID": "SPDXRef-fromDoap-0", + "downloadLocation": "https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz", + "externalRefs": [ + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:maven/org.apache.jena/apache-jena@3.12.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "homepage": "http://www.openjena.org/", + "name": "Jena", + "versionInfo": "3.12.0" + }, + { + "SPDXID": "SPDXRef-Saxon", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "85ed0817af83a24ad8da68c2b5094de69833983c" + } + ], + "copyrightText": "Copyright Saxonica Ltd", + "description": "The Saxon package is a collection of tools for processing XML documents.", + "downloadLocation": "https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download", + "filesAnalyzed": false, + "homepage": "http://saxon.sourceforge.net/", + "licenseComments": "Other versions available for a commercial license", + "licenseConcluded": "MPL-1.0", + "licenseDeclared": "MPL-1.0", + "name": "Saxon", + "packageFileName": "saxonB-8.8.zip", + "versionInfo": "8.8" + } + ], + "files": [ + { + "SPDXID": "SPDXRef-DoapSource", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" + } + ], + "copyrightText": "Copyright 2010, 2011 Source Auditor Inc.", + "fileContributors": [ + "Protecode Inc.", + "SPDX Technical Team Members", + "Open Logic Inc.", + "Source Auditor Inc.", + "Black Duck Software In.c" + ], + "fileName": "./src/org/spdx/parser/DOAPProject.java", + "fileTypes": [ + "SOURCE" + ], + "licenseConcluded": "Apache-2.0", + "licenseInfoInFiles": [ + "Apache-2.0" + ] + }, + { + "SPDXID": "SPDXRef-CommonsLangSrc", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "c2b4e1c67a2d28fced849ee1bb76e7391b93f125" + } + ], + "comment": "This file is used by Jena", + "copyrightText": "Copyright 2001-2011 The Apache Software Foundation", + "fileContributors": [ + "Apache Software Foundation" + ], + "fileName": "./lib-source/commons-lang3-3.1-sources.jar", + "fileTypes": [ + "ARCHIVE" + ], + "licenseConcluded": "Apache-2.0", + "licenseInfoInFiles": [ + "Apache-2.0" + ], + "noticeText": "Apache Commons Lang\nCopyright 2001-2011 The Apache Software Foundation\n\nThis product includes software developed by\nThe Apache Software Foundation (http://www.apache.org/).\n\nThis product includes software from the Spring Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())" + }, + { + "SPDXID": "SPDXRef-JenaLib", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" + } + ], + "comment": "This file belongs to Jena", + "copyrightText": "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP", + "fileContributors": [ + "Apache Software Foundation", + "Hewlett Packard Inc." + ], + "fileName": "./lib-source/jena-2.6.3-sources.jar", + "fileTypes": [ + "ARCHIVE" + ], + "licenseComments": "This license is used by Jena", + "licenseConcluded": "LicenseRef-1", + "licenseInfoInFiles": [ + "LicenseRef-1" + ] + }, + { + "SPDXID": "SPDXRef-Specification", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "fff4e1c67a2d28fced849ee1bb76e7391b93f125" + } + ], + "comment": "Specification Documentation", + "fileName": "./docs/myspec.pdf", + "fileTypes": [ + "DOCUMENTATION" + ] + }, + { + "SPDXID": "SPDXRef-File", + "annotations": [ + { + "annotationDate": "2011-01-29T18:30:22Z", + "annotationType": "OTHER", + "annotator": "Person: File Commenter", + "comment": "File level annotation" + } + ], + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758" + }, + { + "algorithm": "MD5", + "checksumValue": "624c1abb3664f4b35547e7c73864ad24" + } + ], + "comment": "The concluded license was taken from the package level that the file was included in.\nThis information was found in the COPYING.txt file in the xyz directory.", + "copyrightText": "Copyright 2008-2010 John Smith", + "fileContributors": [ + "The Regents of the University of California", + "Modified by Paul Mundt lethal@linux-sh.org", + "IBM Corporation" + ], + "fileName": "./package/foo.c", + "fileTypes": [ + "SOURCE" + ], + "licenseComments": "The concluded license was taken from the package level that the file was included in.", + "licenseConcluded": "LicenseRef-2", + "licenseInfoInFiles": [ + "GPL-2.0-only", + "LicenseRef-2" + ], + "noticeText": "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: \nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + } + ], + "snippets": [ + { + "SPDXID": "SPDXRef-Snippet", + "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0.", + "copyrightText": "Copyright 2008-2010 John Smith", + "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz.", + "licenseConcluded": "GPL-2.0-only", + "licenseInfoInSnippets": [ + "GPL-2.0-only" + ], + "name": "from linux kernel", + "ranges": [ + { + "endPointer": { + "offset": 420, + "reference": "SPDXRef-DoapSource" + }, + "startPointer": { + "offset": 310, + "reference": "SPDXRef-DoapSource" + } + }, + { + "endPointer": { + "lineNumber": 23, + "reference": "SPDXRef-DoapSource" + }, + "startPointer": { + "lineNumber": 5, + "reference": "SPDXRef-DoapSource" + } + } + ], + "snippetFromFile": "SPDXRef-DoapSource" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-Package" + }, + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "DESCRIBES", + "relatedSpdxElement": "SPDXRef-Package" + }, + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "DESCRIBES", + "relatedSpdxElement": "SPDXRef-File" + }, + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "COPY_OF", + "relatedSpdxElement": "DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "DYNAMIC_LINK", + "relatedSpdxElement": "SPDXRef-Saxon" + }, + { + "spdxElementId": "SPDXRef-CommonsLangSrc", + "relationshipType": "GENERATED_FROM", + "relatedSpdxElement": "NOASSERTION" + }, + { + "spdxElementId": "SPDXRef-JenaLib", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-Package" + }, + { + "spdxElementId": "SPDXRef-Specification", + "relationshipType": "SPECIFICATION_FOR", + "relatedSpdxElement": "SPDXRef-fromDoap-0" + }, + { + "spdxElementId": "SPDXRef-File", + "relationshipType": "GENERATED_FROM", + "relatedSpdxElement": "SPDXRef-fromDoap-0" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-Specification" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-CommonsLangSrc" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-JenaLib" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-DoapSource" + } + ] +} diff --git a/tests/spdx/data/invalid/spdx-trivy-vmware_log-intelligence-fluentd-sha256_086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a.json b/tests/spdx/data/invalid/spdx-trivy-vmware_log-intelligence-fluentd-sha256_086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a.json new file mode 100644 index 000000000..3910f2597 --- /dev/null +++ b/tests/spdx/data/invalid/spdx-trivy-vmware_log-intelligence-fluentd-sha256_086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a.json @@ -0,0 +1,13400 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "creationInfo": { + "created": "2022-12-27T23:08:17.349368Z", + "creators": [ + "Tool: trivy", + "Organization: aquasecurity" + ] + }, + "dataLicense": "CC0-1.0", + "documentNamespace": "http://aquasecurity.github.io/trivy/container_image/vmware/log-intelligence-fluentd@sha256:086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a-e79fdb4f-b9ff-45e8-81ac-0f257f75175d", + "files": [ + { + "SPDXID": "SPDXRef-File-14f66e6492118e2b", + "fileName": "usr/local/bundle/specifications/http_parser.rb-0.6.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-163e6167199c70f8", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/webrick-1.4.2.gemspec" + }, + { + "SPDXID": "SPDXRef-File-17e14d81e7f99760", + "fileName": "usr/local/bundle/specifications/webmock-3.4.2.gemspec" + }, + { + "SPDXID": "SPDXRef-File-1a3b2492488dc1bb", + "fileName": "usr/local/bundle/specifications/kubeclient-4.9.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-1b0c1a7abfdf3750", + "fileName": "usr/local/bundle/specifications/fluent-plugin-mysqlslowquery-0.0.9.gemspec" + }, + { + "SPDXID": "SPDXRef-File-21c05387f9618dca", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/rdoc-6.0.1.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-222dda99097b5a4b", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/test-unit-3.2.7.gemspec" + }, + { + "SPDXID": "SPDXRef-File-23b1097f60fe4ff5", + "fileName": "usr/local/bundle/specifications/mime-types-data-3.2021.0225.gemspec" + }, + { + "SPDXID": "SPDXRef-File-283c0fcf1ce181dd", + "fileName": "usr/local/bundle/specifications/term-ansicolor-1.7.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-2a16819592df77af", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/openssl-2.1.2.gemspec" + }, + { + "SPDXID": "SPDXRef-File-2bcbcb8df2c093e9", + "fileName": "usr/local/bundle/specifications/http-parser-1.2.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-2e668632179caf02", + "fileName": "usr/local/bundle/specifications/public_suffix-4.0.6.gemspec" + }, + { + "SPDXID": "SPDXRef-File-300115993e47c841", + "fileName": "usr/local/bundle/specifications/unf-0.1.4.gemspec" + }, + { + "SPDXID": "SPDXRef-File-307750765aca0ebf", + "fileName": "usr/local/bundle/specifications/power_assert-2.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-3e317e1689d57944", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/zlib-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-3e6177586289e490", + "fileName": "usr/local/bundle/specifications/yajl-ruby-1.4.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-445574002859d577", + "fileName": "usr/local/bundle/specifications/fluent-plugin-vmware-log-intelligence-2.0.6.gemspec" + }, + { + "SPDXID": "SPDXRef-File-47a2a1175afee1d0", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/rubygems-update-3.0.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-4c55fead3fb1eacd", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/power_assert-1.1.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-4cc028742b5d3e1c", + "fileName": "usr/local/bundle/specifications/myslog-0.1.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-4f1c92731740d645", + "fileName": "usr/local/bundle/specifications/test-unit-3.1.9.gemspec" + }, + { + "SPDXID": "SPDXRef-File-4fbfe56ebc910a04", + "fileName": "usr/local/bundle/specifications/fluent-plugin-concat-2.4.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-5039b4dd5be61326", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/dbm-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-5088bc45a0077c6e", + "fileName": "usr/local/bundle/specifications/fluentd-1.12.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-515c25dff75d4464", + "fileName": "usr/local/bundle/specifications/fluent-plugin-detect-exceptions-0.0.13.gemspec" + }, + { + "SPDXID": "SPDXRef-File-531b12a9f2cbd18c", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/psych-3.0.2.gemspec" + }, + { + "SPDXID": "SPDXRef-File-5660569c0d42ee26", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/scanf-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-577c438c4a22f8f9", + "fileName": "usr/local/bundle/specifications/netrc-0.11.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-57bc6e693a6ad23f", + "fileName": "usr/local/bundle/specifications/fluent-plugin-kubernetes_metadata_filter-2.6.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-59685867d7685a04", + "fileName": "usr/local/bundle/specifications/http-4.4.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-5a1b4d806d2b1fcc", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/stringio-0.0.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-5a9392b128ab8846", + "fileName": "usr/local/bundle/specifications/crack-0.4.5.gemspec" + }, + { + "SPDXID": "SPDXRef-File-5efcce251a2eeca8", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/fcntl-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-61d8e4625b4e39c5", + "fileName": "usr/local/bundle/specifications/rake-13.0.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-6760d7b3cf399812", + "fileName": "usr/local/lib/ruby/gems/2.5.0/gems/rubygems-update-3.0.3/test/rubygems/specifications/bar-0.0.2.gemspec" + }, + { + "SPDXID": "SPDXRef-File-68d2fc8fa0adeaaa", + "fileName": "usr/local/bundle/specifications/simplecov-html-0.10.2.gemspec" + }, + { + "SPDXID": "SPDXRef-File-691430647dbe2404", + "fileName": "usr/local/bundle/specifications/mime-types-3.3.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-70a9a5b3f7febc19", + "fileName": "usr/local/bundle/specifications/coveralls-0.8.23.gemspec" + }, + { + "SPDXID": "SPDXRef-File-71aed48a0d5cd57c", + "fileName": "usr/local/bundle/specifications/http-cookie-1.0.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-73865f107a591634", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/rake-12.3.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-74355c988cefcec2", + "fileName": "usr/local/bundle/specifications/fluent-plugin-postgres-0.1.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-776c249af65f80a", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/fileutils-1.0.2.gemspec" + }, + { + "SPDXID": "SPDXRef-File-7782e9e66b5721ea", + "fileName": "usr/local/bundle/specifications/bundler-2.2.14.gemspec" + }, + { + "SPDXID": "SPDXRef-File-79506f569f1eaeee", + "fileName": "usr/local/bundle/specifications/pg-1.2.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-79c4e5f2d2818573", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/json-2.1.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-7d050bf79eb943d", + "fileName": "usr/local/bundle/specifications/sync-0.5.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-85b5947892d5c29e", + "fileName": "usr/local/bundle/specifications/thor-1.1.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-87d4b29ad2a1dc0a", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/bundler-1.17.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-8ac1d4512ae3e952", + "fileName": "usr/local/bundle/specifications/http-form_data-2.3.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-90d7f34d5de703a2", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/did_you_mean-1.2.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-9125528db386d007", + "fileName": "usr/local/bundle/specifications/recursive-open-struct-1.1.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-917f29a5996816f9", + "fileName": "usr/local/bundle/specifications/simplecov-0.16.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-985afe51380ffaa0", + "fileName": "usr/local/bundle/specifications/domain_name-0.5.20190701.gemspec" + }, + { + "SPDXID": "SPDXRef-File-9b36710b2dfd3203", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/date-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-a07c3dd5871cfe09", + "fileName": "usr/local/bundle/specifications/concurrent-ruby-1.1.8.gemspec" + }, + { + "SPDXID": "SPDXRef-File-a55f5ee03824e645", + "fileName": "usr/local/bundle/specifications/tzinfo-2.0.4.gemspec" + }, + { + "SPDXID": "SPDXRef-File-a5e5c32506af5d0e", + "fileName": "usr/local/bundle/specifications/rexml-3.2.4.gemspec" + }, + { + "SPDXID": "SPDXRef-File-a654618a3d077029", + "fileName": "usr/local/bundle/specifications/json-2.5.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-a7f3b2ecc0fd3e79", + "fileName": "usr/local/bundle/specifications/cool.io-1.7.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-a8bafe26ee90660e", + "fileName": "usr/local/bundle/specifications/jsonpath-1.1.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-abb34f574c0572d6", + "fileName": "usr/local/bundle/specifications/tins-1.28.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-af446aff14d6d8ff", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/etc-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-b3e0a77f1e8fa3f2", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/gdbm-2.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-b6f4795c10542ff3", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/ipaddr-1.2.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-ba50aee500a585be", + "fileName": "usr/local/bundle/specifications/sigdump-0.2.4.gemspec" + }, + { + "SPDXID": "SPDXRef-File-bab3c735f3519b1d", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/csv-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-bea4fe934e66850", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/cmath-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-c019b46eb3781764", + "fileName": "usr/local/bundle/specifications/ffi-compiler-1.0.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-c37c5b5f82366631", + "fileName": "usr/local/bundle/specifications/tzinfo-data-1.2021.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-c74fcf570b47310a", + "fileName": "usr/local/bundle/specifications/unf_ext-0.0.7.7.gemspec" + }, + { + "SPDXID": "SPDXRef-File-c8b50c4cd74f7167", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/xmlrpc-0.3.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-cbead515ba637924", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/minitest-5.10.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-ccf15d538d702705", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/sdbm-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-cd2dbe4c8627035c", + "fileName": "usr/local/bundle/specifications/addressable-2.7.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-d6e46a3279552a64", + "fileName": "usr/local/bundle/specifications/docile-1.3.5.gemspec" + }, + { + "SPDXID": "SPDXRef-File-d77d5c9a873c5bdd", + "fileName": "usr/local/bundle/specifications/serverengine-2.2.3.gemspec" + }, + { + "SPDXID": "SPDXRef-File-db5f9504237dc6e", + "fileName": "usr/local/bundle/specifications/http-accept-1.7.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-db76a60fb42672e3", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/strscan-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-dda3950a8b6346e", + "fileName": "usr/local/bundle/specifications/multi_json-1.15.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-dec440c01be37d5a", + "fileName": "usr/local/bundle/specifications/msgpack-1.4.2.gemspec" + }, + { + "SPDXID": "SPDXRef-File-df9e5a65f822f58", + "fileName": "usr/local/bundle/specifications/rest-client-2.1.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-e0a269b5adb01415", + "fileName": "usr/local/bundle/specifications/ffi-1.15.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-e10e9d9ae36d17e6", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/net-telnet-0.1.1.gemspec" + }, + { + "SPDXID": "SPDXRef-File-ee8778cf30dbabbd", + "fileName": "usr/local/bundle/specifications/lru_redux-1.1.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-f16aa6f1f336d35a", + "fileName": "usr/local/bundle/specifications/fluent-plugin-multi-format-parser-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-f421ad278fed879", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/fiddle-1.0.0.gemspec" + }, + { + "SPDXID": "SPDXRef-File-f834608e337889d9", + "fileName": "usr/local/lib/ruby/gems/2.5.0/gems/rubygems-update-3.0.3/test/rubygems/specifications/foo-0.0.1-x86-mswin32.gemspec" + }, + { + "SPDXID": "SPDXRef-File-f84eca1df5bb3072", + "fileName": "usr/local/bundle/specifications/strptime-0.2.5.gemspec" + }, + { + "SPDXID": "SPDXRef-File-fa686adffd1942a4", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/io-console-0.4.6.gemspec" + }, + { + "SPDXID": "SPDXRef-File-fc1f948329a3b25b", + "fileName": "usr/local/lib/ruby/gems/2.5.0/specifications/default/bigdecimal-1.3.4.gemspec" + }, + { + "SPDXID": "SPDXRef-File-fcc1819c8e21c5dc", + "fileName": "usr/local/bundle/specifications/hashdiff-1.0.1.gemspec" + } + ], + "name": "vmware/log-intelligence-fluentd@sha256:086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a", + "packages": [ + { + "SPDXID": "SPDXRef-Application-441a648f2aeeee72", + "filesAnalyzed": false, + "name": "gemspec", + "sourceInfo": "Ruby" + }, + { + "SPDXID": "SPDXRef-ContainerImage-83c3ff25d55771a4", + "attributionTexts": [ + "SchemaVersion: 2", + "ImageID: sha256:3fad4228d5f833e47140759b5f4c41cd24c66e6d83968151467628a313632574", + "RepoDigest: vmware/log-intelligence-fluentd@sha256:086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a", + "DiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a", + "DiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d", + "DiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d", + "DiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f", + "DiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c", + "DiffID: sha256:029ceb7fb9a22857102155e598606c38ab1a077ec9dc1ee6660c4f8f87d0455b", + "DiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce", + "DiffID: sha256:0dca9740b579b10bff83784c9845404dccc73c234c75b422630cef153372e479", + "DiffID: sha256:d0b804499a9363d1ec9cbf7d82b717cc3741f55ef68a8c2b7165fbab2296bb01", + "DiffID: sha256:27b731fb6828bdf1901249151f90401590339bbb0531508264bf090586f682f4", + "DiffID: sha256:825479a142734c73c3ea16b9c869c00e31acafa35c61a0c2f3be074649960ad2", + "DiffID: sha256:040c0eb6895da4ab370278f48e6fcc9f78e37771939b9bb0d87dd9cdb68eb00e", + "DiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9", + "DiffID: sha256:8a5bce019193727dd66b821449cd5e3fdef5fd47dfa79e824874bd92b55c08bc", + "DiffID: sha256:156173d99031ef67c96441a022b65bf3ae35ed5d3a0e4cfb1161fa2611eb01d2" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:oci/log-intelligence-fluentd@sha256:086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a?repository_url=index.docker.io%2Fvmware%2Flog-intelligence-fluentd\u0026arch=amd64", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "name": "vmware/log-intelligence-fluentd@sha256:086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a" + }, + { + "SPDXID": "SPDXRef-OperatingSystem-100fd27dbdf9d366", + "filesAnalyzed": false, + "name": "debian", + "versionInfo": "10.8" + }, + { + "SPDXID": "SPDXRef-Package-1041640e30a1c2dd", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcap-ng0@0.7.9-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0, GPL-3.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0, GPL-3.0", + "name": "libcap-ng0", + "sourceInfo": "built package from: libcap-ng 0.7.9-2", + "versionInfo": "0.7.9-2" + }, + { + "SPDXID": "SPDXRef-Package-10e63bb0c8c927e2", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libc6-dev@2.28-10?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libc6-dev", + "sourceInfo": "built package from: glibc 2.28-10", + "versionInfo": "2.28-10" + }, + { + "SPDXID": "SPDXRef-Package-12758e3d4619f1c5", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libtinfo6@6.1+20181013-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, BSD-3-Clause", + "licenseDeclared": "MIT, BSD-3-Clause", + "name": "libtinfo6", + "sourceInfo": "built package from: ncurses 6.1+20181013-2+deb10u2", + "versionInfo": "6.1+20181013-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-13ff46745cf4b557", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgnutls28-dev@3.6.7-4+deb10u6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "The main library is licensed under GNU Lesser, LGPL-3.0, GPL-3.0, GFDL-1.3, CC0 license, The MIT License (MIT), LGPLv3+, GPL-2.0, Apache-2.0", + "licenseDeclared": "The main library is licensed under GNU Lesser, LGPL-3.0, GPL-3.0, GFDL-1.3, CC0 license, The MIT License (MIT), LGPLv3+, GPL-2.0, Apache-2.0", + "name": "libgnutls28-dev", + "sourceInfo": "built package from: gnutls28 3.6.7-4+deb10u6", + "versionInfo": "3.6.7-4+deb10u6" + }, + { + "SPDXID": "SPDXRef-Package-148eb497a15a2ffc", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/binutils-x86-64-linux-gnu@2.31.1-16?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "binutils-x86-64-linux-gnu", + "sourceInfo": "built package from: binutils 2.31.1-16", + "versionInfo": "2.31.1-16" + }, + { + "SPDXID": "SPDXRef-Package-14c00ba4fb0e9bfc", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/bar@0.0.2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-6760d7b3cf399812" + ], + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "bar", + "versionInfo": "0.0.2" + }, + { + "SPDXID": "SPDXRef-Package-14eaab2ee5584e96", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/gdbm@2.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-b3e0a77f1e8fa3f2" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "gdbm", + "versionInfo": "2.0.0" + }, + { + "SPDXID": "SPDXRef-Package-162cb2f66dfde37f", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/g++@4:8.3.0-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "g++", + "sourceInfo": "built package from: gcc-defaults 1.181", + "versionInfo": "4:8.3.0-1" + }, + { + "SPDXID": "SPDXRef-Package-1693791e87e1315b", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgdbm-compat4@1.18.1-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GPL-2.0, GFDL-NIV-1.3+", + "licenseDeclared": "GPL-3.0, GPL-2.0, GFDL-NIV-1.3+", + "name": "libgdbm-compat4", + "sourceInfo": "built package from: gdbm 1.18.1-4", + "versionInfo": "1.18.1-4" + }, + { + "SPDXID": "SPDXRef-Package-172c95e997f6e5d5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libdb5.3-dev@5.3.28+dfsg1-0.5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libdb5.3-dev", + "sourceInfo": "built package from: db5.3 5.3.28+dfsg1-0.5", + "versionInfo": "5.3.28+dfsg1-0.5" + }, + { + "SPDXID": "SPDXRef-Package-17312a987fd5556e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libjbig-dev@2.1-3.1+b2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libjbig-dev", + "sourceInfo": "built package from: jbigkit 2.1-3.1", + "versionInfo": "2.1-3.1+b2" + }, + { + "SPDXID": "SPDXRef-Package-17934a51fb6d7f29", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libltdl-dev@2.4.6-9?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libltdl-dev", + "sourceInfo": "built package from: libtool 2.4.6-9", + "versionInfo": "2.4.6-9" + }, + { + "SPDXID": "SPDXRef-Package-17962f3241de260", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libfdisk1@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "libfdisk1", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-17e1ab7227afecf0", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libssh2-1@1.8.0-2.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD3", + "licenseDeclared": "BSD3", + "name": "libssh2-1", + "sourceInfo": "built package from: libssh2 1.8.0-2.1", + "versionInfo": "1.8.0-2.1" + }, + { + "SPDXID": "SPDXRef-Package-18235d7783e0d31", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/hicolor-icon-theme@0.17-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "hicolor-icon-theme", + "sourceInfo": "built package from: hicolor-icon-theme 0.17-2", + "versionInfo": "0.17-2" + }, + { + "SPDXID": "SPDXRef-Package-1834d15b09e44fa", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpcre32-3@2:8.39-12?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libpcre32-3", + "sourceInfo": "built package from: pcre3 2:8.39-12", + "versionInfo": "2:8.39-12" + }, + { + "SPDXID": "SPDXRef-Package-18fca66e267667e7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/x11proto-dev@2018.4-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, SGI", + "licenseDeclared": "MIT, SGI", + "name": "x11proto-dev", + "sourceInfo": "built package from: xorgproto 2018.4-4", + "versionInfo": "2018.4-4" + }, + { + "SPDXID": "SPDXRef-Package-19bcf5c8e50620f6", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/lru_redux@1.1.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-ee8778cf30dbabbd" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "lru_redux", + "versionInfo": "1.1.0" + }, + { + "SPDXID": "SPDXRef-Package-19e778120eea3982", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libkadm5clnt-mit11@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libkadm5clnt-mit11", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-19f3815bfdada995", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libubsan1@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libubsan1", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-1a2925a178f0527e", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcom-err2@1.44.5-1+deb10u3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libcom-err2", + "sourceInfo": "built package from: e2fsprogs 1.44.5-1+deb10u3", + "versionInfo": "1.44.5-1+deb10u3" + }, + { + "SPDXID": "SPDXRef-Package-1aeecf842515f440", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagic-mgc@1:5.35-4+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-2-Clause-alike, public-domain, BSD-2-Clause-netbsd, BSD-2-Clause-regents, MIT-Old-Style-with-legal-disclaimer-2", + "licenseDeclared": "BSD-2-Clause-alike, public-domain, BSD-2-Clause-netbsd, BSD-2-Clause-regents, MIT-Old-Style-with-legal-disclaimer-2", + "name": "libmagic-mgc", + "sourceInfo": "built package from: file 1:5.35-4+deb10u2", + "versionInfo": "1:5.35-4+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-1be2178063709639", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libdjvulibre-text@3.5.27.1-10?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libdjvulibre-text", + "sourceInfo": "built package from: djvulibre 3.5.27.1-10", + "versionInfo": "3.5.27.1-10" + }, + { + "SPDXID": "SPDXRef-Package-1ca3bdaa6155edce", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libnpth0@1.6-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1", + "licenseDeclared": "LGPL-2.1", + "name": "libnpth0", + "sourceInfo": "built package from: npth 1.6-1", + "versionInfo": "1.6-1" + }, + { + "SPDXID": "SPDXRef-Package-1ccf84255921351", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/subversion@1.10.4-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0, BSD-3-Clause, Utfwidth, Svnwrap, GPL-2.0, GPL-3.0, AFL-3, Expat, Unicode, BSD-2-Clause", + "licenseDeclared": "Apache-2.0, BSD-3-Clause, Utfwidth, Svnwrap, GPL-2.0, GPL-3.0, AFL-3, Expat, Unicode, BSD-2-Clause", + "name": "subversion", + "sourceInfo": "built package from: subversion 1.10.4-1+deb10u1", + "versionInfo": "1.10.4-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-1d4e48b231b2b77b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libthai0@0.1.28-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libthai0", + "sourceInfo": "built package from: libthai 0.1.28-2", + "versionInfo": "0.1.28-2" + }, + { + "SPDXID": "SPDXRef-Package-1db0861ab23e0107", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libffi-dev@3.2.1-9?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libffi-dev", + "sourceInfo": "built package from: libffi 3.2.1-9", + "versionInfo": "3.2.1-9" + }, + { + "SPDXID": "SPDXRef-Package-1e1f1adc637448d5", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/rake@12.3.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-73865f107a591634" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "rake", + "versionInfo": "12.3.3" + }, + { + "SPDXID": "SPDXRef-Package-1ebcb86363fecedc", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/base-files@10.3+deb10u8?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "base-files", + "sourceInfo": "built package from: base-files 10.3+deb10u8", + "versionInfo": "10.3+deb10u8" + }, + { + "SPDXID": "SPDXRef-Package-1f69f215f63bdafe", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/fdisk@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "fdisk", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-1f971eaee71aede5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/pkg-config@0.29-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "pkg-config", + "sourceInfo": "built package from: pkg-config 0.29-6", + "versionInfo": "0.29-6" + }, + { + "SPDXID": "SPDXRef-Package-1fd9ecaa617a5dd5", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/netrc@0.11.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-577c438c4a22f8f9" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "netrc", + "versionInfo": "0.11.0" + }, + { + "SPDXID": "SPDXRef-Package-208da78d723c749b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxcb1-dev@1.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxcb1-dev", + "sourceInfo": "built package from: libxcb 1.13.1-2", + "versionInfo": "1.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-2193304ec9a9d18", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpcrecpp0v5@2:8.39-12?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libpcrecpp0v5", + "sourceInfo": "built package from: pcre3 2:8.39-12", + "versionInfo": "2:8.39-12" + }, + { + "SPDXID": "SPDXRef-Package-22266fb151bc142b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libdb-dev@5.3.1+nmu1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "libdb-dev", + "sourceInfo": "built package from: db-defaults 5.3.1+nmu1", + "versionInfo": "5.3.1+nmu1" + }, + { + "SPDXID": "SPDXRef-Package-225c105bfa9eeef3", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gpgv@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gpgv", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-227c82cff970ce52", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libkdb5-9@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libkdb5-9", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-228999fe3e6baae9", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/cpp-8@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "cpp-8", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-229b952a289327b5", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/csv@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-bab3c735f3519b1d" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "csv", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-22f4ed53809a2f10", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxext-dev@2:1.3.3-1+b2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LicenseRef-C-Ares, MIT", + "licenseDeclared": "LicenseRef-C-Ares, MIT", + "name": "libxext-dev", + "sourceInfo": "built package from: libxext 2:1.3.3-1", + "versionInfo": "2:1.3.3-1+b2" + }, + { + "SPDXID": "SPDXRef-Package-2434a9197c5f8367", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libilmbase-dev@2.2.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ilmbase, boost", + "licenseDeclared": "ilmbase, boost", + "name": "libilmbase-dev", + "sourceInfo": "built package from: ilmbase 2.2.1-2", + "versionInfo": "2.2.1-2" + }, + { + "SPDXID": "SPDXRef-Package-24754988d5349c18", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/autoconf@2.69-11?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GPL-3+ with Autoconf exception, permissive-short-disclaimer, permissive-long-disclaimer, permissive-without-disclaimer, permissive-without-notices-or-disclaimer, GPL-2.0-with-autoconf-exception, GPL-2.0, MIT-X-Consortium, GPL-3+ with Texinfo exception, GFDL-1.3+, GFDL-1.3, no-modification, permissive, other", + "licenseDeclared": "GPL-3.0, GPL-3+ with Autoconf exception, permissive-short-disclaimer, permissive-long-disclaimer, permissive-without-disclaimer, permissive-without-notices-or-disclaimer, GPL-2.0-with-autoconf-exception, GPL-2.0, MIT-X-Consortium, GPL-3+ with Texinfo exception, GFDL-1.3+, GFDL-1.3, no-modification, permissive, other", + "name": "autoconf", + "sourceInfo": "built package from: autoconf 2.69-11", + "versionInfo": "2.69-11" + }, + { + "SPDXID": "SPDXRef-Package-24af159b03559a3", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/psych@3.0.2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-531b12a9f2cbd18c" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "psych", + "versionInfo": "3.0.2" + }, + { + "SPDXID": "SPDXRef-Package-24d87789c23a726c", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/domain_name@0.5.20190701", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-985afe51380ffaa0" + ], + "licenseConcluded": "BSD-2-Clause, BSD-3-Clause, MPL-2.0", + "licenseDeclared": "BSD-2-Clause, BSD-3-Clause, MPL-2.0", + "name": "domain_name", + "versionInfo": "0.5.20190701" + }, + { + "SPDXID": "SPDXRef-Package-24e923697bb40f2d", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gpgconf@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gpgconf", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-24f81198c2b5819f", + "attributionTexts": [ + "LayerDigest: sha256:ef7778ed4c65afb1a1cb2319b38ad8ef211b1705974f751c31b21d58cfb503db", + "LayerDiffID: sha256:d0b804499a9363d1ec9cbf7d82b717cc3741f55ef68a8c2b7165fbab2296bb01" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/nodejs@10.24.0~dfsg-1~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Expat, NTP~MIT, ISC, BSD-3-clause~Google, BSD-1-clause, BSD-2-clause~contributors, BSD-2-clause~author, BSD-3-clause~author, BSD-3-clause~contributors, GPL-3.0, GPL-2.0, Expat~Wu, MIT~Prototype, Apache-2.0, BSD-3-clause~contributors-author, BSD-3-clause~holders, OpenSSL, SSLeay, MIT/X11, BSD-3-clause~Sun, BSD-4-clause~author, BSD-3-clause~Intel, ISC-no-disclaim, Zlib, MPL-2.0, curl", + "licenseDeclared": "Expat, NTP~MIT, ISC, BSD-3-clause~Google, BSD-1-clause, BSD-2-clause~contributors, BSD-2-clause~author, BSD-3-clause~author, BSD-3-clause~contributors, GPL-3.0, GPL-2.0, Expat~Wu, MIT~Prototype, Apache-2.0, BSD-3-clause~contributors-author, BSD-3-clause~holders, OpenSSL, SSLeay, MIT/X11, BSD-3-clause~Sun, BSD-4-clause~author, BSD-3-clause~Intel, ISC-no-disclaim, Zlib, MPL-2.0, curl", + "name": "nodejs", + "sourceInfo": "built package from: nodejs 10.24.0~dfsg-1~deb10u1", + "versionInfo": "10.24.0~dfsg-1~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-2517194abf9399", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/hashdiff@1.0.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-fcc1819c8e21c5dc" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "hashdiff", + "versionInfo": "1.0.1" + }, + { + "SPDXID": "SPDXRef-Package-25c36dfe89ca6c23", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/unzip@6.0-23+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "unzip", + "sourceInfo": "built package from: unzip 6.0-23+deb10u2", + "versionInfo": "6.0-23+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-2636e82320406adf", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libext2fs2@1.44.5-1+deb10u3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.0", + "licenseDeclared": "GPL-2.0, LGPL-2.0", + "name": "libext2fs2", + "sourceInfo": "built package from: e2fsprogs 1.44.5-1+deb10u3", + "versionInfo": "1.44.5-1+deb10u3" + }, + { + "SPDXID": "SPDXRef-Package-2643d3e918f849f9", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpython2.7-stdlib@2.7.16-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libpython2.7-stdlib", + "sourceInfo": "built package from: python2.7 2.7.16-2+deb10u1", + "versionInfo": "2.7.16-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-269ee7224b9677b6", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libilmbase23@2.2.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ilmbase, boost", + "licenseDeclared": "ilmbase, boost", + "name": "libilmbase23", + "sourceInfo": "built package from: ilmbase 2.2.1-2", + "versionInfo": "2.2.1-2" + }, + { + "SPDXID": "SPDXRef-Package-26bfbd3aee7d4436", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/openssh-client@1:7.9p1-10+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "OpenSSH, Mazieres-BSD-style, public-domain, BSD-3-Clause, Beer-ware, Powell-BSD-style, Expat-with-advertising-restriction, BSD-2-Clause", + "licenseDeclared": "OpenSSH, Mazieres-BSD-style, public-domain, BSD-3-Clause, Beer-ware, Powell-BSD-style, Expat-with-advertising-restriction, BSD-2-Clause", + "name": "openssh-client", + "sourceInfo": "built package from: openssh 1:7.9p1-10+deb10u2", + "versionInfo": "1:7.9p1-10+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-271ec194be50b757", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fluent-plugin-kubernetes_metadata_filter@2.6.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-57bc6e693a6ad23f" + ], + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "fluent-plugin-kubernetes_metadata_filter", + "versionInfo": "2.6.0" + }, + { + "SPDXID": "SPDXRef-Package-27d6c56cf4bfb064", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/init-system-helpers@1.56+nmu1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause, GPL-2.0", + "licenseDeclared": "BSD-3-Clause, GPL-2.0", + "name": "init-system-helpers", + "sourceInfo": "built package from: init-system-helpers 1.56+nmu1", + "versionInfo": "1.56+nmu1" + }, + { + "SPDXID": "SPDXRef-Package-28caeafbc9bedc0e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libx11-6@2:1.6.7-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, LicenseRef-C-Ares, LicenseRef-uthash", + "licenseDeclared": "MIT, LicenseRef-C-Ares, LicenseRef-uthash", + "name": "libx11-6", + "sourceInfo": "built package from: libx11 2:1.6.7-1+deb10u1", + "versionInfo": "2:1.6.7-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-295d9e0f6f56fbea", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/rubygems-update@3.0.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-47a2a1175afee1d0" + ], + "licenseConcluded": "Ruby, MIT", + "licenseDeclared": "Ruby, MIT", + "name": "rubygems-update", + "versionInfo": "3.0.3" + }, + { + "SPDXID": "SPDXRef-Package-299c02dfb1b539db", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libice6@2:1.0.9-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libice6", + "sourceInfo": "built package from: libice 2:1.0.9-2", + "versionInfo": "2:1.0.9-2" + }, + { + "SPDXID": "SPDXRef-Package-29eddc615ffe41c7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libevent-pthreads-2.1-6@2.1.8-stable-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libevent-pthreads-2.1-6", + "sourceInfo": "built package from: libevent 2.1.8-stable-4", + "versionInfo": "2.1.8-stable-4" + }, + { + "SPDXID": "SPDXRef-Package-2a2de8c857e587b9", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/minitest@5.10.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-cbead515ba637924" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "minitest", + "versionInfo": "5.10.3" + }, + { + "SPDXID": "SPDXRef-Package-2a87686fbf441463", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fluent-plugin-postgres@0.1.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-74355c988cefcec2" + ], + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "fluent-plugin-postgres", + "versionInfo": "0.1.0" + }, + { + "SPDXID": "SPDXRef-Package-2b02572947fa1bd3", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/apt@1.8.2.2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "apt", + "sourceInfo": "built package from: apt 1.8.2.2", + "versionInfo": "1.8.2.2" + }, + { + "SPDXID": "SPDXRef-Package-2bd453b2ca787979", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxau6@1:1.0.8-1+b2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libxau6", + "sourceInfo": "built package from: libxau 1:1.0.8-1", + "versionInfo": "1:1.0.8-1+b2" + }, + { + "SPDXID": "SPDXRef-Package-2c42c12063bb5281", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpixman-1-dev@0.36.0-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libpixman-1-dev", + "sourceInfo": "built package from: pixman 0.36.0-1", + "versionInfo": "0.36.0-1" + }, + { + "SPDXID": "SPDXRef-Package-2c8af4dfea969dcc", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libglib2.0-dev@2.58.3-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "licenseDeclared": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "name": "libglib2.0-dev", + "sourceInfo": "built package from: glib2.0 2.58.3-2+deb10u2", + "versionInfo": "2.58.3-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-2ca7f3e05ca6060e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpangoft2-1.0-0@1.42.4-8~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, Example, TCL, Unicode, ICU", + "licenseDeclared": "LGPL-2.0, Example, TCL, Unicode, ICU", + "name": "libpangoft2-1.0-0", + "sourceInfo": "built package from: pango1.0 1.42.4-8~deb10u1", + "versionInfo": "1.42.4-8~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-2d2d0256ad2cbdb2", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libfontconfig1@2.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libfontconfig1", + "sourceInfo": "built package from: fontconfig 2.13.1-2", + "versionInfo": "2.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-2dd548b2a8f40a73", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liblcms2-dev@2.9-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, GPL-2.0", + "licenseDeclared": "MIT, GPL-2.0", + "name": "liblcms2-dev", + "sourceInfo": "built package from: lcms2 2.9-3", + "versionInfo": "2.9-3" + }, + { + "SPDXID": "SPDXRef-Package-2e84f7b97323f4d2", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/json@2.5.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-a654618a3d077029" + ], + "licenseConcluded": "Ruby", + "licenseDeclared": "Ruby", + "name": "json", + "versionInfo": "2.5.1" + }, + { + "SPDXID": "SPDXRef-Package-2e91bbddfad6b58d", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libwebpdemux2@0.6.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "libwebpdemux2", + "sourceInfo": "built package from: libwebp 0.6.1-2", + "versionInfo": "0.6.1-2" + }, + { + "SPDXID": "SPDXRef-Package-2f5837af2e7da3", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libfreetype6-dev@2.9.1-3+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, FTL, Catharon-OSL, MIT, BSD-3-Clause, FSFULLR, FSFUL, Permissive, GPL-3.0, Public-Domain, Zlib, OpenGroup-BSD-like", + "licenseDeclared": "GPL-2.0, FTL, Catharon-OSL, MIT, BSD-3-Clause, FSFULLR, FSFUL, Permissive, GPL-3.0, Public-Domain, Zlib, OpenGroup-BSD-like", + "name": "libfreetype6-dev", + "sourceInfo": "built package from: freetype 2.9.1-3+deb10u2", + "versionInfo": "2.9.1-3+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-2f6fd546ebd18212", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/login@1:4.5-1.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "login", + "sourceInfo": "built package from: shadow 1:4.5-1.1", + "versionInfo": "1:4.5-1.1" + }, + { + "SPDXID": "SPDXRef-Package-2fc549d750251755", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgdk-pixbuf2.0-dev@2.38.1+dfsg-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "licenseDeclared": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "name": "libgdk-pixbuf2.0-dev", + "sourceInfo": "built package from: gdk-pixbuf 2.38.1+dfsg-1", + "versionInfo": "2.38.1+dfsg-1" + }, + { + "SPDXID": "SPDXRef-Package-3022be156cb02ac4", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/crack@0.4.5", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-5a9392b128ab8846" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "crack", + "versionInfo": "0.4.5" + }, + { + "SPDXID": "SPDXRef-Package-3109662196609d1", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libheif1@1.3.2-2~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-3.0, BSD-4-Clause, BSD-3-Clause", + "licenseDeclared": "LGPL-3.0, GPL-3.0, BSD-4-Clause, BSD-3-Clause", + "name": "libheif1", + "sourceInfo": "built package from: libheif 1.3.2-2~deb10u1", + "versionInfo": "1.3.2-2~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-3172548c62505d9f", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxdmcp-dev@1:1.1.2-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libxdmcp-dev", + "sourceInfo": "built package from: libxdmcp 1:1.1.2-3", + "versionInfo": "1:1.1.2-3" + }, + { + "SPDXID": "SPDXRef-Package-317595b7018ed00b", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libncursesw6@6.1+20181013-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libncursesw6", + "sourceInfo": "built package from: ncurses 6.1+20181013-2+deb10u2", + "versionInfo": "6.1+20181013-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-31ee771f366d97fe", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/tzinfo@2.0.4", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-a55f5ee03824e645" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "tzinfo", + "versionInfo": "2.0.4" + }, + { + "SPDXID": "SPDXRef-Package-3208fd593da616c7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libopenexr23@2.2.1-4.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "openexr", + "licenseDeclared": "openexr", + "name": "libopenexr23", + "sourceInfo": "built package from: openexr 2.2.1-4.1+deb10u1", + "versionInfo": "2.2.1-4.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-32955d277606b073", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/rake@13.0.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-61d8e4625b4e39c5" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "rake", + "versionInfo": "13.0.3" + }, + { + "SPDXID": "SPDXRef-Package-32a6667282b09531", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/myslog@0.1.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-4cc028742b5d3e1c" + ], + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "myslog", + "versionInfo": "0.1.1" + }, + { + "SPDXID": "SPDXRef-Package-33e24e945847461e", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/tins@1.28.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-abb34f574c0572d6" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "tins", + "versionInfo": "1.28.0" + }, + { + "SPDXID": "SPDXRef-Package-34276835d836db57", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gir1.2-glib-2.0@1.58.3-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.0, BSD-2-Clause, MIT", + "licenseDeclared": "GPL-2.0, LGPL-2.0, BSD-2-Clause, MIT", + "name": "gir1.2-glib-2.0", + "sourceInfo": "built package from: gobject-introspection 1.58.3-2", + "versionInfo": "1.58.3-2" + }, + { + "SPDXID": "SPDXRef-Package-34d2406cfd2f58c4", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libuuid1@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "libuuid1", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-353e6ee8620e9075", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/docile@1.3.5", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-d6e46a3279552a64" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "docile", + "versionInfo": "1.3.5" + }, + { + "SPDXID": "SPDXRef-Package-3569701ef5f04409", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/cpp@4:8.3.0-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "cpp", + "sourceInfo": "built package from: gcc-defaults 1.181", + "versionInfo": "4:8.3.0-1" + }, + { + "SPDXID": "SPDXRef-Package-358e55c61c398fe0", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libexpat1@2.2.6-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libexpat1", + "sourceInfo": "built package from: expat 2.2.6-2+deb10u1", + "versionInfo": "2.2.6-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-372c6637d38419b1", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpango-1.0-0@1.42.4-8~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, Example, TCL, Unicode, ICU", + "licenseDeclared": "LGPL-2.0, Example, TCL, Unicode, ICU", + "name": "libpango-1.0-0", + "sourceInfo": "built package from: pango1.0 1.42.4-8~deb10u1", + "versionInfo": "1.42.4-8~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-377cc25c88863ee3", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/public_suffix@4.0.6", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-2e668632179caf02" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "public_suffix", + "versionInfo": "4.0.6" + }, + { + "SPDXID": "SPDXRef-Package-37f119411bfe17d8", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libidn2-dev@2.0.5-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, LGPL-3.0, GPL-2.0, Unicode", + "licenseDeclared": "GPL-3.0, LGPL-3.0, GPL-2.0, Unicode", + "name": "libidn2-dev", + "sourceInfo": "built package from: libidn2 2.0.5-1+deb10u1", + "versionInfo": "2.0.5-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-384ef4284ef33e90", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcap2-bin@1:2.25-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause, GPL-2.0", + "licenseDeclared": "BSD-3-Clause, GPL-2.0", + "name": "libcap2-bin", + "sourceInfo": "built package from: libcap2 1:2.25-2", + "versionInfo": "1:2.25-2" + }, + { + "SPDXID": "SPDXRef-Package-38576ab9de7da6da", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/binutils-common@2.31.1-16?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, LGPL-3.0, GFDL", + "licenseDeclared": "GPL-3.0, LGPL-3.0, GFDL", + "name": "binutils-common", + "sourceInfo": "built package from: binutils 2.31.1-16", + "versionInfo": "2.31.1-16" + }, + { + "SPDXID": "SPDXRef-Package-386156f56c9f6603", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxrender-dev@1:0.9.10-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LicenseRef-C-Ares", + "licenseDeclared": "LicenseRef-C-Ares", + "name": "libxrender-dev", + "sourceInfo": "built package from: libxrender 1:0.9.10-1", + "versionInfo": "1:0.9.10-1" + }, + { + "SPDXID": "SPDXRef-Package-38e11ea2c97166cc", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/procps@2:3.3.15-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, LGPL-2.0, GPL-2.0", + "licenseDeclared": "LGPL-2.1, LGPL-2.0, GPL-2.0", + "name": "procps", + "sourceInfo": "built package from: procps 2:3.3.15-2", + "versionInfo": "2:3.3.15-2" + }, + { + "SPDXID": "SPDXRef-Package-391c197316c333de", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/librtmp1@2.4+20151223.gitfa8646d.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.1", + "licenseDeclared": "GPL-2.0, LGPL-2.1", + "name": "librtmp1", + "sourceInfo": "built package from: rtmpdump 2.4+20151223.gitfa8646d.1-2", + "versionInfo": "2.4+20151223.gitfa8646d.1-2" + }, + { + "SPDXID": "SPDXRef-Package-3945a82969f25e5a", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/netbase@5.6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "netbase", + "sourceInfo": "built package from: netbase 5.6", + "versionInfo": "5.6" + }, + { + "SPDXID": "SPDXRef-Package-3b1440b155e317f1", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgssrpc4@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libgssrpc4", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-3b5dab1fae25d393", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmariadb-dev-compat@1:10.3.27-0+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, GPL-verbatim, public-domain, BSD-3-Clause, LGPL-2.1, BSD-2-Clause, LGPL-2.0, unlimited-free-doc, LGPL-3.0, zlib/libpng, GPL-2.0-with-bison-exception, GPL-2+-with-bison-exception, SWsoft, Artistic, GPL-3.0, MIT/X11", + "licenseDeclared": "GPL-2.0, GPL-verbatim, public-domain, BSD-3-Clause, LGPL-2.1, BSD-2-Clause, LGPL-2.0, unlimited-free-doc, LGPL-3.0, zlib/libpng, GPL-2.0-with-bison-exception, GPL-2+-with-bison-exception, SWsoft, Artistic, GPL-3.0, MIT/X11", + "name": "libmariadb-dev-compat", + "sourceInfo": "built package from: mariadb-10.3 1:10.3.27-0+deb10u1", + "versionInfo": "1:10.3.27-0+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-3b87db0230f29940", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/tzdata@2021a-0+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "tzdata", + "sourceInfo": "built package from: tzdata 2021a-0+deb10u1", + "versionInfo": "2021a-0+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-3bbca33a3b6251e2", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libicu63@63.1-6+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ICU, Unicode-DFS-2015", + "licenseDeclared": "ICU, Unicode-DFS-2015", + "name": "libicu63", + "sourceInfo": "built package from: icu 63.1-6+deb10u1", + "versionInfo": "63.1-6+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-3be9960d2db0d569", + "attributionTexts": [ + "LayerDigest: sha256:ef7778ed4c65afb1a1cb2319b38ad8ef211b1705974f751c31b21d58cfb503db", + "LayerDiffID: sha256:d0b804499a9363d1ec9cbf7d82b717cc3741f55ef68a8c2b7165fbab2296bb01" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/build-essential@12.6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "build-essential", + "sourceInfo": "built package from: build-essential 12.6", + "versionInfo": "12.6" + }, + { + "SPDXID": "SPDXRef-Package-3d79700e06408bcf", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgcc-8-dev@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libgcc-8-dev", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-3db757dbaf1c2abb", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickwand-dev@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libmagickwand-dev", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-3f51a54d2d55e9da", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libdjvulibre-dev@3.5.27.1-10?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libdjvulibre-dev", + "sourceInfo": "built package from: djvulibre 3.5.27.1-10", + "versionInfo": "3.5.27.1-10" + }, + { + "SPDXID": "SPDXRef-Package-3f8ce1578674efa0", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libtiff-dev@4.1.0+git191117-2~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Hylafax", + "licenseDeclared": "Hylafax", + "name": "libtiff-dev", + "sourceInfo": "built package from: tiff 4.1.0+git191117-2~deb10u1", + "versionInfo": "4.1.0+git191117-2~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-3fbb5185b1c03ff", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpng16-16@1.6.36-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "libpng, expat, GPL-2.0, BSD-like-with-advertising-clause, libpng OR Apache-2.0 OR BSD-3-clause, Apache-2.0, BSD-3-Clause", + "licenseDeclared": "libpng, expat, GPL-2.0, BSD-like-with-advertising-clause, libpng OR Apache-2.0 OR BSD-3-clause, Apache-2.0, BSD-3-Clause", + "name": "libpng16-16", + "sourceInfo": "built package from: libpng1.6 1.6.36-6", + "versionInfo": "1.6.36-6" + }, + { + "SPDXID": "SPDXRef-Package-3fda9e123c5f9c5f", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgnutls30@3.6.7-4+deb10u6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "The main library is licensed under GNU Lesser, LGPL-3.0, GPL-3.0, GFDL-1.3, CC0 license, The MIT License (MIT), LGPLv3+, GPL-2.0, Apache-2.0", + "licenseDeclared": "The main library is licensed under GNU Lesser, LGPL-3.0, GPL-3.0, GFDL-1.3, CC0 license, The MIT License (MIT), LGPLv3+, GPL-2.0, Apache-2.0", + "name": "libgnutls30", + "sourceInfo": "built package from: gnutls28 3.6.7-4+deb10u6", + "versionInfo": "3.6.7-4+deb10u6" + }, + { + "SPDXID": "SPDXRef-Package-40623deba1787bd5", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/scanf@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-5660569c0d42ee26" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "scanf", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-406aca4f6ccf9eb1", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gnupg-utils@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gnupg-utils", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-415c84320c75ad74", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libldap-2.4-2@2.4.47+dfsg-3+deb10u5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-4-Clause-UC, BSD-3-Clause, MIT, ISC, LicenseRef-C-Ares", + "licenseDeclared": "BSD-4-Clause-UC, BSD-3-Clause, MIT, ISC, LicenseRef-C-Ares", + "name": "libldap-2.4-2", + "sourceInfo": "built package from: openldap 2.4.47+dfsg-3+deb10u5", + "versionInfo": "2.4.47+dfsg-3+deb10u5" + }, + { + "SPDXID": "SPDXRef-Package-41de54521d58bf39", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libc-bin@2.28-10?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libc-bin", + "sourceInfo": "built package from: glibc 2.28-10", + "versionInfo": "2.28-10" + }, + { + "SPDXID": "SPDXRef-Package-4203ea25358d0404", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/rexml@3.2.4", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-a5e5c32506af5d0e" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "rexml", + "versionInfo": "3.2.4" + }, + { + "SPDXID": "SPDXRef-Package-431f2bacfb0a4938", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/librsvg2-dev@2.44.10-2.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, BSD-3-Clause, Expat, Unlicense, Apache-2.0, MPL-2.0, BSD-2-Clause, Sun-permissive, Boost-1.0", + "licenseDeclared": "LGPL-2.0, BSD-3-Clause, Expat, Unlicense, Apache-2.0, MPL-2.0, BSD-2-Clause, Sun-permissive, Boost-1.0", + "name": "librsvg2-dev", + "sourceInfo": "built package from: librsvg 2.44.10-2.1", + "versionInfo": "2.44.10-2.1" + }, + { + "SPDXID": "SPDXRef-Package-432e6cf76a5b1e06", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fcntl@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-5efcce251a2eeca8" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "fcntl", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-43d300b0860b07d1", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/m4@1.4.18-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GFDL", + "licenseDeclared": "GPL-3.0, GFDL", + "name": "m4", + "sourceInfo": "built package from: m4 1.4.18-2", + "versionInfo": "1.4.18-2" + }, + { + "SPDXID": "SPDXRef-Package-44a319b1e54c24a3", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libglib2.0-0@2.58.3-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "licenseDeclared": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "name": "libglib2.0-0", + "sourceInfo": "built package from: glib2.0 2.58.3-2+deb10u2", + "versionInfo": "2.58.3-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-458dc29980f0cd6a", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/bigdecimal@1.3.4", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-fc1f948329a3b25b" + ], + "licenseConcluded": "Ruby", + "licenseDeclared": "Ruby", + "name": "bigdecimal", + "versionInfo": "1.3.4" + }, + { + "SPDXID": "SPDXRef-Package-4596196435475f32", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libevent-core-2.1-6@2.1.8-stable-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libevent-core-2.1-6", + "sourceInfo": "built package from: libevent 2.1.8-stable-4", + "versionInfo": "2.1.8-stable-4" + }, + { + "SPDXID": "SPDXRef-Package-45973de89e996b8f", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/webrick@1.4.2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-163e6167199c70f8" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "webrick", + "versionInfo": "1.4.2" + }, + { + "SPDXID": "SPDXRef-Package-45c132bd4b2a8c02", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxml2-dev@2.9.4+dfsg1-7+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT-1, ISC", + "licenseDeclared": "MIT-1, ISC", + "name": "libxml2-dev", + "sourceInfo": "built package from: libxml2 2.9.4+dfsg1-7+deb10u1", + "versionInfo": "2.9.4+dfsg1-7+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-45c956276d358a19", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gpg-wks-server@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gpg-wks-server", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-45e4dbf58d3323b0", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libdatrie1@0.2.12-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libdatrie1", + "sourceInfo": "built package from: libdatrie 0.2.12-2", + "versionInfo": "0.2.12-2" + }, + { + "SPDXID": "SPDXRef-Package-4661a45cfb162289", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/imagemagick@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "licenseDeclared": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "name": "imagemagick", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-46b4d169bf518132", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcurl4@7.64.0-4+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "curl, ISC, BSD-3-Clause, public-domain, BSD-4-Clause, other", + "licenseDeclared": "curl, ISC, BSD-3-Clause, public-domain, BSD-4-Clause, other", + "name": "libcurl4", + "sourceInfo": "built package from: curl 7.64.0-4+deb10u1", + "versionInfo": "7.64.0-4+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-46d7909bafee03ba", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python@2.7.16-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Python-2.0", + "licenseDeclared": "MIT, Python-2.0", + "name": "python", + "sourceInfo": "built package from: python-defaults 2.7.16-1", + "versionInfo": "2.7.16-1" + }, + { + "SPDXID": "SPDXRef-Package-4777f6bbd82ca021", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/nettle-dev@3.4.1-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, LGPL-2.0, other, GPL-2.0, GPL-2.0-with-autoconf-exception, public-domain, GAP, LGPL-3.0, GPL-3.0", + "licenseDeclared": "LGPL-2.1, LGPL-2.0, other, GPL-2.0, GPL-2.0-with-autoconf-exception, public-domain, GAP, LGPL-3.0, GPL-3.0", + "name": "nettle-dev", + "sourceInfo": "built package from: nettle 3.4.1-1", + "versionInfo": "3.4.1-1" + }, + { + "SPDXID": "SPDXRef-Package-478bbd4d2f49b46f", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/unf@0.1.4", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-300115993e47c841" + ], + "licenseConcluded": "2-clause BSDL", + "licenseDeclared": "2-clause BSDL", + "name": "unf", + "versionInfo": "0.1.4" + }, + { + "SPDXID": "SPDXRef-Package-47b3c8952f8fbe50", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/sed@4.7-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "sed", + "sourceInfo": "built package from: sed 4.7-1", + "versionInfo": "4.7-1" + }, + { + "SPDXID": "SPDXRef-Package-48d5b856c5f92b96", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcroco3@0.6.12-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0", + "licenseDeclared": "LGPL-3.0", + "name": "libcroco3", + "sourceInfo": "built package from: libcroco 0.6.12-3", + "versionInfo": "0.6.12-3" + }, + { + "SPDXID": "SPDXRef-Package-4900f2c0300300f1", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liblzma5@5.2.4-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "PD, probably-PD, GPL-2.0, LGPL-2.1, permissive-fsf, Autoconf, permissive-nowarranty, none, config-h, LGPL-2.0, noderivs, PD-debian, GPL-3.0", + "licenseDeclared": "PD, probably-PD, GPL-2.0, LGPL-2.1, permissive-fsf, Autoconf, permissive-nowarranty, none, config-h, LGPL-2.0, noderivs, PD-debian, GPL-3.0", + "name": "liblzma5", + "sourceInfo": "built package from: xz-utils 5.2.4-1", + "versionInfo": "5.2.4-1" + }, + { + "SPDXID": "SPDXRef-Package-49a6aec0aebda6f6", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libtasn1-6-dev@4.13-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, LGPL-2.1, GPL-3.0, GFDL-1.3", + "licenseDeclared": "LGPL-3.0, LGPL-2.1, GPL-3.0, GFDL-1.3", + "name": "libtasn1-6-dev", + "sourceInfo": "built package from: libtasn1-6 4.13-3", + "versionInfo": "4.13-3" + }, + { + "SPDXID": "SPDXRef-Package-49c5afd7d797f425", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpython3.7-stdlib@3.7.3-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libpython3.7-stdlib", + "sourceInfo": "built package from: python3.7 3.7.3-2+deb10u2", + "versionInfo": "3.7.3-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-49cd823649057f01", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/concurrent-ruby@1.1.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-a07c3dd5871cfe09" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "concurrent-ruby", + "versionInfo": "1.1.8" + }, + { + "SPDXID": "SPDXRef-Package-4a42dfcce7824cb1", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpcre16-3@2:8.39-12?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libpcre16-3", + "sourceInfo": "built package from: pcre3 2:8.39-12", + "versionInfo": "2:8.39-12" + }, + { + "SPDXID": "SPDXRef-Package-4a441604f9d66233", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gir1.2-rsvg-2.0@2.44.10-2.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, BSD-3-Clause, Expat, Unlicense, Apache-2.0, MPL-2.0, BSD-2-Clause, Sun-permissive, Boost-1.0", + "licenseDeclared": "LGPL-2.0, BSD-3-Clause, Expat, Unlicense, Apache-2.0, MPL-2.0, BSD-2-Clause, Sun-permissive, Boost-1.0", + "name": "gir1.2-rsvg-2.0", + "sourceInfo": "built package from: librsvg 2.44.10-2.1", + "versionInfo": "2.44.10-2.1" + }, + { + "SPDXID": "SPDXRef-Package-4a666d098f9545e8", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/zlib@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-3e317e1689d57944" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "zlib", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-4a89ca5b19224fd1", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/iputils-ping@3:20180629-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "iputils-ping", + "sourceInfo": "built package from: iputils 3:20180629-2+deb10u1", + "versionInfo": "3:20180629-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-4b5c9fab2976d0ec", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpam-modules@1.3.1-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "libpam-modules", + "sourceInfo": "built package from: pam 1.3.1-5", + "versionInfo": "1.3.1-5" + }, + { + "SPDXID": "SPDXRef-Package-4b7a60a1c1c48e13", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libattr1@1:2.4.48-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.0, LGPL-2.1", + "licenseDeclared": "GPL-2.0, LGPL-2.0, LGPL-2.1", + "name": "libattr1", + "sourceInfo": "built package from: attr 1:2.4.48-4", + "versionInfo": "1:2.4.48-4" + }, + { + "SPDXID": "SPDXRef-Package-4bde3da66a315edf", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/curl@7.64.0-4+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "curl, ISC, BSD-3-Clause, public-domain, BSD-4-Clause, other", + "licenseDeclared": "curl, ISC, BSD-3-Clause, public-domain, BSD-4-Clause, other", + "name": "curl", + "sourceInfo": "built package from: curl 7.64.0-4+deb10u1", + "versionInfo": "7.64.0-4+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-4bf767eb41271f78", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gcc@4:8.3.0-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "gcc", + "sourceInfo": "built package from: gcc-defaults 1.181", + "versionInfo": "4:8.3.0-1" + }, + { + "SPDXID": "SPDXRef-Package-4c1a988ee6380a8", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/kubeclient@4.9.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-1a3b2492488dc1bb" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "kubeclient", + "versionInfo": "4.9.1" + }, + { + "SPDXID": "SPDXRef-Package-4c22807b16bae796", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxrender1@1:0.9.10-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LicenseRef-C-Ares", + "licenseDeclared": "LicenseRef-C-Ares", + "name": "libxrender1", + "sourceInfo": "built package from: libxrender 1:0.9.10-1", + "versionInfo": "1:0.9.10-1" + }, + { + "SPDXID": "SPDXRef-Package-4cf9ca786c78f05", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python3-minimal@3.7.3-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Python-2.0", + "licenseDeclared": "MIT, Python-2.0", + "name": "python3-minimal", + "sourceInfo": "built package from: python3-defaults 3.7.3-1", + "versionInfo": "3.7.3-1" + }, + { + "SPDXID": "SPDXRef-Package-4d216ff3e9c71e55", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/sync@0.5.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-7d050bf79eb943d" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "sync", + "versionInfo": "0.5.0" + }, + { + "SPDXID": "SPDXRef-Package-4d48ef296bb8a76b", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/power_assert@2.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-307750765aca0ebf" + ], + "licenseConcluded": "BSD-2-Clause, Ruby", + "licenseDeclared": "BSD-2-Clause, Ruby", + "name": "power_assert", + "versionInfo": "2.0.0" + }, + { + "SPDXID": "SPDXRef-Package-4e65fe8bbaefbf2b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpixman-1-0@0.36.0-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libpixman-1-0", + "sourceInfo": "built package from: pixman 0.36.0-1", + "versionInfo": "0.36.0-1" + }, + { + "SPDXID": "SPDXRef-Package-4e7b602d3480d09f", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxcb1@1.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxcb1", + "sourceInfo": "built package from: libxcb 1.13.1-2", + "versionInfo": "1.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-4ecfe347a135da68", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/sigdump@0.2.4", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-ba50aee500a585be" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "sigdump", + "versionInfo": "0.2.4" + }, + { + "SPDXID": "SPDXRef-Package-4f5e9b0e804a3f85", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/binutils@2.31.1-16?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, LGPL-3.0, GFDL", + "licenseDeclared": "GPL-3.0, LGPL-3.0, GFDL", + "name": "binutils", + "sourceInfo": "built package from: binutils 2.31.1-16", + "versionInfo": "2.31.1-16" + }, + { + "SPDXID": "SPDXRef-Package-4f6646e2c4e39c66", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gzip@1.9-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "gzip", + "sourceInfo": "built package from: gzip 1.9-3", + "versionInfo": "1.9-3" + }, + { + "SPDXID": "SPDXRef-Package-4fe2f7dfe3c43d94", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liblzma-dev@5.2.4-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "PD, probably-PD, GPL-2.0, LGPL-2.1, permissive-fsf, Autoconf, permissive-nowarranty, none, config-h, LGPL-2.0, noderivs, PD-debian, GPL-3.0", + "licenseDeclared": "PD, probably-PD, GPL-2.0, LGPL-2.1, permissive-fsf, Autoconf, permissive-nowarranty, none, config-h, LGPL-2.0, noderivs, PD-debian, GPL-3.0", + "name": "liblzma-dev", + "sourceInfo": "built package from: xz-utils 5.2.4-1", + "versionInfo": "5.2.4-1" + }, + { + "SPDXID": "SPDXRef-Package-5014364785154bdc", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libncurses5-dev@6.1+20181013-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libncurses5-dev", + "sourceInfo": "built package from: ncurses 6.1+20181013-2+deb10u2", + "versionInfo": "6.1+20181013-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-5076ed8fc78ad1e0", + "attributionTexts": [ + "LayerDigest: sha256:99934cfa0ef4724ea3d6ea510ce5f107f6c48f4920bbd30a19c4696b92a09dd8", + "LayerDiffID: sha256:8a5bce019193727dd66b821449cd5e3fdef5fd47dfa79e824874bd92b55c08bc" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fluent-plugin-vmware-log-intelligence@2.0.6", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-445574002859d577" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "fluent-plugin-vmware-log-intelligence", + "versionInfo": "2.0.6" + }, + { + "SPDXID": "SPDXRef-Package-52bd63f8bb34743d", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/coveralls@0.8.23", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-70a9a5b3f7febc19" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "coveralls", + "versionInfo": "0.8.23" + }, + { + "SPDXID": "SPDXRef-Package-52d615cd61fd57bd", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libjbig0@2.1-3.1+b2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libjbig0", + "sourceInfo": "built package from: jbigkit 2.1-3.1", + "versionInfo": "2.1-3.1+b2" + }, + { + "SPDXID": "SPDXRef-Package-52f0b92f98f15bd7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmaxminddb-dev@1.3.2-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0, CC-BY-SA, GPL-2.0, GPL-3.0, BSD-2-Clause, BSD-3-Clause, BSD-4-Clause", + "licenseDeclared": "Apache-2.0, CC-BY-SA, GPL-2.0, GPL-3.0, BSD-2-Clause, BSD-3-Clause, BSD-4-Clause", + "name": "libmaxminddb-dev", + "sourceInfo": "built package from: libmaxminddb 1.3.2-1+deb10u1", + "versionInfo": "1.3.2-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-530bca05e69142b5", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libprocps7@2:3.3.15-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, LGPL-2.0, GPL-2.0", + "licenseDeclared": "LGPL-2.1, LGPL-2.0, GPL-2.0", + "name": "libprocps7", + "sourceInfo": "built package from: procps 2:3.3.15-2", + "versionInfo": "2:3.3.15-2" + }, + { + "SPDXID": "SPDXRef-Package-534e055ca8f3334b", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/cool.io@1.7.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-a7f3b2ecc0fd3e79" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "cool.io", + "versionInfo": "1.7.1" + }, + { + "SPDXID": "SPDXRef-Package-53e2b609ba1851d8", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python2.7@2.7.16-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, # Licensed to PSF under a Contributor Agreement, Apache-2.0, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person obtaining, This software is provided as-is, without express, * Permission to use this software in any way is granted without, see above, some license as Python., Expat, PSF-2, Apache-2, Python, ISC, LGPL-2.1", + "licenseDeclared": "GPL-2.0, # Licensed to PSF under a Contributor Agreement, Apache-2.0, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person obtaining, This software is provided as-is, without express, * Permission to use this software in any way is granted without, see above, some license as Python., Expat, PSF-2, Apache-2, Python, ISC, LGPL-2.1", + "name": "python2.7", + "sourceInfo": "built package from: python2.7 2.7.16-2+deb10u1", + "versionInfo": "2.7.16-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-541916b041085230", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/rest-client@2.1.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-df9e5a65f822f58" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "rest-client", + "versionInfo": "2.1.0" + }, + { + "SPDXID": "SPDXRef-Package-544fd0e95e335076", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/jsonpath@1.1.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-a8bafe26ee90660e" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "jsonpath", + "versionInfo": "1.1.0" + }, + { + "SPDXID": "SPDXRef-Package-5463f6b226cb968e", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gpg-agent@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gpg-agent", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-54872f0d7deb47b4", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/x11proto-xext-dev@2018.4-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, SGI", + "licenseDeclared": "MIT, SGI", + "name": "x11proto-xext-dev", + "sourceInfo": "built package from: xorgproto 2018.4-4", + "versionInfo": "2018.4-4" + }, + { + "SPDXID": "SPDXRef-Package-5533665b3a58df77", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libssl-dev@1.1.1d-0+deb10u4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "OpenSSL", + "licenseDeclared": "OpenSSL", + "name": "libssl-dev", + "sourceInfo": "built package from: openssl 1.1.1d-0+deb10u4", + "versionInfo": "1.1.1d-0+deb10u4" + }, + { + "SPDXID": "SPDXRef-Package-55d8c4ae5d3c4cae", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libglib2.0-bin@2.58.3-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "licenseDeclared": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "name": "libglib2.0-bin", + "sourceInfo": "built package from: glib2.0 2.58.3-2+deb10u2", + "versionInfo": "2.58.3-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-568a6ef95bf0614b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpng-dev@1.6.36-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "libpng, expat, GPL-2.0, BSD-like-with-advertising-clause, libpng OR Apache-2.0 OR BSD-3-clause, Apache-2.0, BSD-3-Clause", + "licenseDeclared": "libpng, expat, GPL-2.0, BSD-like-with-advertising-clause, libpng OR Apache-2.0 OR BSD-3-clause, Apache-2.0, BSD-3-Clause", + "name": "libpng-dev", + "sourceInfo": "built package from: libpng1.6 1.6.36-6", + "versionInfo": "1.6.36-6" + }, + { + "SPDXID": "SPDXRef-Package-5691322012558da4", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/test-unit@3.2.7", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-222dda99097b5a4b" + ], + "licenseConcluded": "Ruby, PSFL", + "licenseDeclared": "Ruby, PSFL", + "name": "test-unit", + "versionInfo": "3.2.7" + }, + { + "SPDXID": "SPDXRef-Package-57965a002dd87072", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsasl2-2@2.1.27+dfsg-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-4-Clause, GPL-3.0", + "licenseDeclared": "BSD-4-Clause, GPL-3.0", + "name": "libsasl2-2", + "sourceInfo": "built package from: cyrus-sasl2 2.1.27+dfsg-1+deb10u1", + "versionInfo": "2.1.27+dfsg-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-57b0a0a98c8a9644", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libx265-165@2.9-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, Expat, LGPL-2.1, ISC", + "licenseDeclared": "GPL-2.0, Expat, LGPL-2.1, ISC", + "name": "libx265-165", + "sourceInfo": "built package from: x265 2.9-4", + "versionInfo": "2.9-4" + }, + { + "SPDXID": "SPDXRef-Package-57f8489438ac8c9d", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liberror-perl@0.17027-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Artistic, GPL-1.0, MIT/X11", + "licenseDeclared": "Artistic, GPL-1.0, MIT/X11", + "name": "liberror-perl", + "sourceInfo": "built package from: liberror-perl 0.17027-2", + "versionInfo": "0.17027-2" + }, + { + "SPDXID": "SPDXRef-Package-582b1c091f92ae2c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liblzo2-2@2.10-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "liblzo2-2", + "sourceInfo": "built package from: lzo2 2.10-0.1", + "versionInfo": "2.10-0.1" + }, + { + "SPDXID": "SPDXRef-Package-589ce3c1d2c1696b", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libhogweed4@3.4.1-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libhogweed4", + "sourceInfo": "built package from: nettle 3.4.1-1", + "versionInfo": "3.4.1-1" + }, + { + "SPDXID": "SPDXRef-Package-58de9d284eb995b6", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmpdec2@2.4.2-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause, GPL-2.0", + "licenseDeclared": "BSD-3-Clause, GPL-2.0", + "name": "libmpdec2", + "sourceInfo": "built package from: mpdecimal 2.4.2-2", + "versionInfo": "2.4.2-2" + }, + { + "SPDXID": "SPDXRef-Package-59284826e7b2e072", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libx11-data@2:1.6.7-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, LicenseRef-C-Ares, LicenseRef-uthash", + "licenseDeclared": "MIT, LicenseRef-C-Ares, LicenseRef-uthash", + "name": "libx11-data", + "sourceInfo": "built package from: libx11 2:1.6.7-1+deb10u1", + "versionInfo": "2:1.6.7-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-595ae0e1c2592228", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libkrb5-dev@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libkrb5-dev", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-5984a5185345374c", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gpg@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gpg", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-59a2771fc4d2713c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcairo-script-interpreter2@1.16.0-4+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1", + "licenseDeclared": "LGPL-2.1", + "name": "libcairo-script-interpreter2", + "sourceInfo": "built package from: cairo 1.16.0-4+deb10u1", + "versionInfo": "1.16.0-4+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-5b64189fa687815d", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python2.7-minimal@2.7.16-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, # Licensed to PSF under a Contributor Agreement, Apache-2.0, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person obtaining, This software is provided as-is, without express, * Permission to use this software in any way is granted without, see above, some license as Python., Expat, PSF-2, Apache-2, Python, ISC, LGPL-2.1", + "licenseDeclared": "GPL-2.0, # Licensed to PSF under a Contributor Agreement, Apache-2.0, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person obtaining, This software is provided as-is, without express, * Permission to use this software in any way is granted without, see above, some license as Python., Expat, PSF-2, Apache-2, Python, ISC, LGPL-2.1", + "name": "python2.7-minimal", + "sourceInfo": "built package from: python2.7 2.7.16-2+deb10u1", + "versionInfo": "2.7.16-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-5bc418d75e49e572", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libffi6@3.2.1-9?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "libffi6", + "sourceInfo": "built package from: libffi 3.2.1-9", + "versionInfo": "3.2.1-9" + }, + { + "SPDXID": "SPDXRef-Package-5c1cece2afce9ca5", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/git@1:2.20.1-2+deb10u3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.1, EDL-1.0, Expat, BSD-2-Clause, GPL-1.0, Artistic-1, GPL-3.0, Artistic, ISC, mingw-runtime, Boost, dlmalloc, Apache-2.0, LGPL-2.0", + "licenseDeclared": "GPL-2.0, LGPL-2.1, EDL-1.0, Expat, BSD-2-Clause, GPL-1.0, Artistic-1, GPL-3.0, Artistic, ISC, mingw-runtime, Boost, dlmalloc, Apache-2.0, LGPL-2.0", + "name": "git", + "sourceInfo": "built package from: git 1:2.20.1-2+deb10u3", + "versionInfo": "1:2.20.1-2+deb10u3" + }, + { + "SPDXID": "SPDXRef-Package-5c635d900a757402", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libtsan0@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libtsan0", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-5c68bfd82d25827a", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libunbound8@1.9.0-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-NLnetLabs, GPL-3.0, ISC, BSD-3-WIDE, BSD-3-Regents-DEC, BSD-3-ADG, BSD-3-Todd-Miller, BSD-3-NLnetLabs-Mekking, BSD-3-Viagénie, BSD-3-Farsight, BSD-3-VUT, BSD-2-VUT, BSD-3-CZ.NIC, GPL-3+ with Bison exception, public-domain", + "licenseDeclared": "BSD-3-NLnetLabs, GPL-3.0, ISC, BSD-3-WIDE, BSD-3-Regents-DEC, BSD-3-ADG, BSD-3-Todd-Miller, BSD-3-NLnetLabs-Mekking, BSD-3-Viagénie, BSD-3-Farsight, BSD-3-VUT, BSD-2-VUT, BSD-3-CZ.NIC, GPL-3+ with Bison exception, public-domain", + "name": "libunbound8", + "sourceInfo": "built package from: unbound 1.9.0-2+deb10u2", + "versionInfo": "1.9.0-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-5d3913304b80ff4f", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libquadmath0@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libquadmath0", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-5dd1501a764ebc54", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/openssl@2.1.2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-2a16819592df77af" + ], + "licenseConcluded": "Ruby", + "licenseDeclared": "Ruby", + "name": "openssl", + "versionInfo": "2.1.2" + }, + { + "SPDXID": "SPDXRef-Package-5ff73da84ebfecb2", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libidn2-0@2.0.5-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, LGPL-3.0, GPL-2.0, Unicode", + "licenseDeclared": "GPL-3.0, LGPL-3.0, GPL-2.0, Unicode", + "name": "libidn2-0", + "sourceInfo": "built package from: libidn2 2.0.5-1+deb10u1", + "versionInfo": "2.0.5-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-60377124514ccadc", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libx11-dev@2:1.6.7-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, LicenseRef-C-Ares, LicenseRef-uthash", + "licenseDeclared": "MIT, LicenseRef-C-Ares, LicenseRef-uthash", + "name": "libx11-dev", + "sourceInfo": "built package from: libx11 2:1.6.7-1+deb10u1", + "versionInfo": "2:1.6.7-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-6158b572aa34562b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python3@3.7.3-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Python-2.0", + "licenseDeclared": "MIT, Python-2.0", + "name": "python3", + "sourceInfo": "built package from: python3-defaults 3.7.3-1", + "versionInfo": "3.7.3-1" + }, + { + "SPDXID": "SPDXRef-Package-62509c24122118ac", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libevent-dev@2.1.8-stable-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libevent-dev", + "sourceInfo": "built package from: libevent 2.1.8-stable-4", + "versionInfo": "2.1.8-stable-4" + }, + { + "SPDXID": "SPDXRef-Package-627c25bc928058ac", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/bzip2@1.0.6-9.2~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-variant, GPL-2.0", + "licenseDeclared": "BSD-variant, GPL-2.0", + "name": "bzip2", + "sourceInfo": "built package from: bzip2 1.0.6-9.2~deb10u1", + "versionInfo": "1.0.6-9.2~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-627c9d106d1158f0", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/did_you_mean@1.2.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-90d7f34d5de703a2" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "did_you_mean", + "versionInfo": "1.2.0" + }, + { + "SPDXID": "SPDXRef-Package-633ae10dc26b62a1", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/json@2.1.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-79c4e5f2d2818573" + ], + "licenseConcluded": "Ruby", + "licenseDeclared": "Ruby", + "name": "json", + "versionInfo": "2.1.0" + }, + { + "SPDXID": "SPDXRef-Package-638c11a166449db0", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fluent-plugin-multi-format-parser@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-f16aa6f1f336d35a" + ], + "licenseConcluded": "Apache License (2.0)", + "licenseDeclared": "Apache License (2.0)", + "name": "fluent-plugin-multi-format-parser", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-63a0e7c4d186846a", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libopenjp2-7-dev@2.3.0-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-2, MIT, BSD-3, public-domain, LIBPNG, Zlib, LIBTIFF, LIBTIFF-PIXAR, LIBTIFF-GLARSON", + "licenseDeclared": "BSD-2, MIT, BSD-3, public-domain, LIBPNG, Zlib, LIBTIFF, LIBTIFF-PIXAR, LIBTIFF-GLARSON", + "name": "libopenjp2-7-dev", + "sourceInfo": "built package from: openjpeg2 2.3.0-2+deb10u1", + "versionInfo": "2.3.0-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-6402dbff959e8f7b", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/sysvinit-utils@2.93-8?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "sysvinit-utils", + "sourceInfo": "built package from: sysvinit 2.93-8", + "versionInfo": "2.93-8" + }, + { + "SPDXID": "SPDXRef-Package-64d2ce0d3e928c0b", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/debconf@1.5.71?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "debconf", + "sourceInfo": "built package from: debconf 1.5.71", + "versionInfo": "1.5.71" + }, + { + "SPDXID": "SPDXRef-Package-64fecd35dd644dac", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gnupg-l10n@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gnupg-l10n", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-654dd3f52839d49d", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/strptime@0.2.5", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-f84eca1df5bb3072" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "strptime", + "versionInfo": "0.2.5" + }, + { + "SPDXID": "SPDXRef-Package-65a48c6f37dff200", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/tar@1.30+dfsg-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GPL-2.0", + "licenseDeclared": "GPL-3.0, GPL-2.0", + "name": "tar", + "sourceInfo": "built package from: tar 1.30+dfsg-6", + "versionInfo": "1.30+dfsg-6" + }, + { + "SPDXID": "SPDXRef-Package-65c5022c78559cb", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libudev1@241-7~deb10u6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, CC0-1.0, GPL-2.0, Expat, public-domain", + "licenseDeclared": "LGPL-2.1, CC0-1.0, GPL-2.0, Expat, public-domain", + "name": "libudev1", + "sourceInfo": "built package from: systemd 241-7~deb10u6", + "versionInfo": "241-7~deb10u6" + }, + { + "SPDXID": "SPDXRef-Package-65e9ad0fcf459d79", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/mercurial-common@4.8.2-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.1", + "licenseDeclared": "GPL-2.0, LGPL-2.1", + "name": "mercurial-common", + "sourceInfo": "built package from: mercurial 4.8.2-1+deb10u1", + "versionInfo": "4.8.2-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-6669fb6f7c0c53f5", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gpg-wks-client@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gpg-wks-client", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-667512fabb87ffb3", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python2@2.7.16-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Python-2.0", + "licenseDeclared": "MIT, Python-2.0", + "name": "python2", + "sourceInfo": "built package from: python-defaults 2.7.16-1", + "versionInfo": "2.7.16-1" + }, + { + "SPDXID": "SPDXRef-Package-66ebae5dd34f6179", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/mawk@1.3.3-17+b3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "mawk", + "sourceInfo": "built package from: mawk 1.3.3-17", + "versionInfo": "1.3.3-17+b3" + }, + { + "SPDXID": "SPDXRef-Package-673b8c81afb12121", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libice-dev@2:1.0.9-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libice-dev", + "sourceInfo": "built package from: libice 2:1.0.9-2", + "versionInfo": "2:1.0.9-2" + }, + { + "SPDXID": "SPDXRef-Package-673be4195e04fe47", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpython-stdlib@2.7.16-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Python-2.0", + "licenseDeclared": "MIT, Python-2.0", + "name": "libpython-stdlib", + "sourceInfo": "built package from: python-defaults 2.7.16-1", + "versionInfo": "2.7.16-1" + }, + { + "SPDXID": "SPDXRef-Package-68048faa1293698", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gcc-8-base@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GFDL-1.2, GPL-2.0, Artistic, LGPL-3.0", + "licenseDeclared": "GPL-3.0, GFDL-1.2, GPL-2.0, Artistic, LGPL-3.0", + "name": "gcc-8-base", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-68292ceec62681a", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libfftw3-double3@3.3.8-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libfftw3-double3", + "sourceInfo": "built package from: fftw3 3.3.8-2", + "versionInfo": "3.3.8-2" + }, + { + "SPDXID": "SPDXRef-Package-687d6abcaae9684c", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libselinux1@2.8-1+b1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libselinux1", + "sourceInfo": "built package from: libselinux 2.8-1", + "versionInfo": "2.8-1+b1" + }, + { + "SPDXID": "SPDXRef-Package-688dbb58af6442bf", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgpg-error0@1.35-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, BSD-3-Clause, g10-permissive, GPL-3.0", + "licenseDeclared": "LGPL-2.1, BSD-3-Clause, g10-permissive, GPL-3.0", + "name": "libgpg-error0", + "sourceInfo": "built package from: libgpg-error 1.35-1", + "versionInfo": "1.35-1" + }, + { + "SPDXID": "SPDXRef-Package-691461b77e42d682", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/http-form_data@2.3.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-8ac1d4512ae3e952" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "http-form_data", + "versionInfo": "2.3.0" + }, + { + "SPDXID": "SPDXRef-Package-69da9fc663bcefba", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fluent-plugin-concat@2.4.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-4fbfe56ebc910a04" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "fluent-plugin-concat", + "versionInfo": "2.4.0" + }, + { + "SPDXID": "SPDXRef-Package-69e48d70b7e1e94f", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/unf_ext@0.0.7.7", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-c74fcf570b47310a" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "unf_ext", + "versionInfo": "0.0.7.7" + }, + { + "SPDXID": "SPDXRef-Package-6a0038456397f563", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgnutls-dane0@3.6.7-4+deb10u6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "The main library is licensed under GNU Lesser, LGPL-3.0, GPL-3.0, GFDL-1.3, CC0 license, The MIT License (MIT), LGPLv3+, GPL-2.0, Apache-2.0", + "licenseDeclared": "The main library is licensed under GNU Lesser, LGPL-3.0, GPL-3.0, GFDL-1.3, CC0 license, The MIT License (MIT), LGPLv3+, GPL-2.0, Apache-2.0", + "name": "libgnutls-dane0", + "sourceInfo": "built package from: gnutls28 3.6.7-4+deb10u6", + "versionInfo": "3.6.7-4+deb10u6" + }, + { + "SPDXID": "SPDXRef-Package-6a4dd1e705dd3727", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/dpkg-dev@1.19.7?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, BSD-2-Clause, public-domain-s-s-d, public-domain-md5", + "licenseDeclared": "GPL-2.0, BSD-2-Clause, public-domain-s-s-d, public-domain-md5", + "name": "dpkg-dev", + "sourceInfo": "built package from: dpkg 1.19.7", + "versionInfo": "1.19.7" + }, + { + "SPDXID": "SPDXRef-Package-6ae99df519c94a0b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liblsan0@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "liblsan0", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-6befefc20b98bc2d", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libdb5.3@5.3.28+dfsg1-0.5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause, Sleepycat", + "licenseDeclared": "BSD-3-Clause, Sleepycat", + "name": "libdb5.3", + "sourceInfo": "built package from: db5.3 5.3.28+dfsg1-0.5", + "versionInfo": "5.3.28+dfsg1-0.5" + }, + { + "SPDXID": "SPDXRef-Package-6c810e9c546688c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxcb-shm0-dev@1.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxcb-shm0-dev", + "sourceInfo": "built package from: libxcb 1.13.1-2", + "versionInfo": "1.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-6cfb48a13f551b50", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcairo-gobject2@1.16.0-4+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1", + "licenseDeclared": "LGPL-2.1", + "name": "libcairo-gobject2", + "sourceInfo": "built package from: cairo 1.16.0-4+deb10u1", + "versionInfo": "1.16.0-4+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-6d13b2811acadccd", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libassuan0@2.5.2-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GAP~FSF, LGPL-3.0, GPL-2+ with libtool exception, GPL-2.0, GPL-3.0, GAP", + "licenseDeclared": "LGPL-2.1, GAP~FSF, LGPL-3.0, GPL-2+ with libtool exception, GPL-2.0, GPL-3.0, GAP", + "name": "libassuan0", + "sourceInfo": "built package from: libassuan 2.5.2-1", + "versionInfo": "2.5.2-1" + }, + { + "SPDXID": "SPDXRef-Package-6d21c58de759f6d4", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/net-telnet@0.1.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-e10e9d9ae36d17e6" + ], + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "net-telnet", + "versionInfo": "0.1.1" + }, + { + "SPDXID": "SPDXRef-Package-6d38077a12f4929c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libwebp-dev@0.6.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "libwebp-dev", + "sourceInfo": "built package from: libwebp 0.6.1-2", + "versionInfo": "0.6.1-2" + }, + { + "SPDXID": "SPDXRef-Package-6d699acd4ca2572c", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/tzinfo-data@1.2021.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-c37c5b5f82366631" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "tzinfo-data", + "versionInfo": "1.2021.1" + }, + { + "SPDXID": "SPDXRef-Package-6d850cdec149860b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagic1@1:5.35-4+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-2-Clause-alike, public-domain, BSD-2-Clause-netbsd, BSD-2-Clause-regents, MIT-Old-Style-with-legal-disclaimer-2", + "licenseDeclared": "BSD-2-Clause-alike, public-domain, BSD-2-Clause-netbsd, BSD-2-Clause-regents, MIT-Old-Style-with-legal-disclaimer-2", + "name": "libmagic1", + "sourceInfo": "built package from: file 1:5.35-4+deb10u2", + "versionInfo": "1:5.35-4+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-6e50b8b684cfa18", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcairo2@1.16.0-4+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1", + "licenseDeclared": "LGPL-2.1", + "name": "libcairo2", + "sourceInfo": "built package from: cairo 1.16.0-4+deb10u1", + "versionInfo": "1.16.0-4+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-6fe936d3046b719b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gcc-8@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "gcc-8", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-6fed6422a026cbfe", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/passwd@1:4.5-1.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "passwd", + "sourceInfo": "built package from: shadow 1:4.5-1.1", + "versionInfo": "1:4.5-1.1" + }, + { + "SPDXID": "SPDXRef-Package-7109ffacfaa3d408", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpcre3-dev@2:8.39-12?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libpcre3-dev", + "sourceInfo": "built package from: pcre3 2:8.39-12", + "versionInfo": "2:8.39-12" + }, + { + "SPDXID": "SPDXRef-Package-711773da6ff4a7df", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libnghttp2-14@1.36.0-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Expat, MIT, all-permissive, GPL-3+ with autoconf exception, BSD-2-Clause, SIL-OFL-1.1, GPL-3.0", + "licenseDeclared": "Expat, MIT, all-permissive, GPL-3+ with autoconf exception, BSD-2-Clause, SIL-OFL-1.1, GPL-3.0", + "name": "libnghttp2-14", + "sourceInfo": "built package from: nghttp2 1.36.0-2+deb10u1", + "versionInfo": "1.36.0-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-7166008ef0d0d794", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/ffi@1.15.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-e0a269b5adb01415" + ], + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "ffi", + "versionInfo": "1.15.0" + }, + { + "SPDXID": "SPDXRef-Package-7199d7c2949f084", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libwebp6@0.6.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "libwebp6", + "sourceInfo": "built package from: libwebp 0.6.1-2", + "versionInfo": "0.6.1-2" + }, + { + "SPDXID": "SPDXRef-Package-71bff02914a5f016", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickwand-6.q16-6@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "licenseDeclared": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "name": "libmagickwand-6.q16-6", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-72169715e76cda1f", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmount1@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "libmount1", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-73289eee74d1193", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libglib2.0-dev-bin@2.58.3-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "licenseDeclared": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "name": "libglib2.0-dev-bin", + "sourceInfo": "built package from: glib2.0 2.58.3-2+deb10u2", + "versionInfo": "2.58.3-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-73f782866971903d", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libzstd1@1.3.8+dfsg-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause, GPL-2.0, Zlib, Expat", + "licenseDeclared": "BSD-3-Clause, GPL-2.0, Zlib, Expat", + "name": "libzstd1", + "sourceInfo": "built package from: libzstd 1.3.8+dfsg-3", + "versionInfo": "1.3.8+dfsg-3" + }, + { + "SPDXID": "SPDXRef-Package-7689fa8f8a4576ad", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickcore-dev@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libmagickcore-dev", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-76e5b6b4252879af", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/x11-common@1:7.7+19?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "x11-common", + "sourceInfo": "built package from: xorg 1:7.7+19", + "versionInfo": "1:7.7+19" + }, + { + "SPDXID": "SPDXRef-Package-779fca035571204d", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gnupg@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gnupg", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-780fadfb1b09bc82", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/shared-mime-info@1.10-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "shared-mime-info", + "sourceInfo": "built package from: shared-mime-info 1.10-1", + "versionInfo": "1.10-1" + }, + { + "SPDXID": "SPDXRef-Package-783ef76702d3a91a", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpython2.7-minimal@2.7.16-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, # Licensed to PSF under a Contributor Agreement, Apache-2.0, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person obtaining, This software is provided as-is, without express, * Permission to use this software in any way is granted without, see above, some license as Python., Expat, PSF-2, Apache-2, Python, ISC, LGPL-2.1", + "licenseDeclared": "GPL-2.0, # Licensed to PSF under a Contributor Agreement, Apache-2.0, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person obtaining, This software is provided as-is, without express, * Permission to use this software in any way is granted without, see above, some license as Python., Expat, PSF-2, Apache-2, Python, ISC, LGPL-2.1", + "name": "libpython2.7-minimal", + "sourceInfo": "built package from: python2.7 2.7.16-2+deb10u1", + "versionInfo": "2.7.16-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-788d1374b1636be", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/yajl-ruby@1.4.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-3e6177586289e490" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "yajl-ruby", + "versionInfo": "1.4.1" + }, + { + "SPDXID": "SPDXRef-Package-78af4f0dccaa863a", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/webmock@3.4.2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-17e14d81e7f99760" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "webmock", + "versionInfo": "3.4.2" + }, + { + "SPDXID": "SPDXRef-Package-7a1255281ea8acde", + "attributionTexts": [ + "LayerDigest: sha256:ef7778ed4c65afb1a1cb2319b38ad8ef211b1705974f751c31b21d58cfb503db", + "LayerDiffID: sha256:d0b804499a9363d1ec9cbf7d82b717cc3741f55ef68a8c2b7165fbab2296bb01" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libc-ares2@1.14.0-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "libc-ares2", + "sourceInfo": "built package from: c-ares 1.14.0-1", + "versionInfo": "1.14.0-1" + }, + { + "SPDXID": "SPDXRef-Package-7ac16f90845b2afe", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickcore-6.q16-6-extra@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "licenseDeclared": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "name": "libmagickcore-6.q16-6-extra", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-7afd5ba82e2a133b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/imagemagick-6.q16@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "licenseDeclared": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "name": "imagemagick-6.q16", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-7b46d06f33a442d4", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/bundler@2.2.14", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-7782e9e66b5721ea" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "bundler", + "versionInfo": "2.2.14" + }, + { + "SPDXID": "SPDXRef-Package-7b5a8afaf2e761b0", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liblqr-1-0@0.4.2-2.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-3.0, GPLv3", + "licenseDeclared": "LGPL-3.0, GPL-3.0, GPLv3", + "name": "liblqr-1-0", + "sourceInfo": "built package from: liblqr 0.4.2-2.1", + "versionInfo": "0.4.2-2.1" + }, + { + "SPDXID": "SPDXRef-Package-7bc2f0fcdc61a57f", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/grep@3.3-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "grep", + "sourceInfo": "built package from: grep 3.3-1", + "versionInfo": "3.3-1" + }, + { + "SPDXID": "SPDXRef-Package-7bffe398276f86e2", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/fontconfig@2.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "fontconfig", + "sourceInfo": "built package from: fontconfig 2.13.1-2", + "versionInfo": "2.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-7c1031d7f2486bbe", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickcore-6.q16-6@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "licenseDeclared": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "name": "libmagickcore-6.q16-6", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-7c5adb0b6cce54a7", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gpgsm@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "gpgsm", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-7d72d2d4c0326608", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libreadline7@7.0-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GFDL", + "licenseDeclared": "GPL-3.0, GFDL", + "name": "libreadline7", + "sourceInfo": "built package from: readline 7.0-5", + "versionInfo": "7.0-5" + }, + { + "SPDXID": "SPDXRef-Package-7e04b37489c1b79b", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/pg@1.2.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-79506f569f1eaeee" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "pg", + "versionInfo": "1.2.3" + }, + { + "SPDXID": "SPDXRef-Package-7e78769ff0e667c3", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/adduser@3.118?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "adduser", + "sourceInfo": "built package from: adduser 3.118", + "versionInfo": "3.118" + }, + { + "SPDXID": "SPDXRef-Package-7e86d037fca632cd", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libutf8proc2@2.3.0-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Expat, Unicode", + "licenseDeclared": "Expat, Unicode", + "name": "libutf8proc2", + "sourceInfo": "built package from: utf8proc 2.3.0-1", + "versionInfo": "2.3.0-1" + }, + { + "SPDXID": "SPDXRef-Package-7ee95ee507d0214d", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python3.7-minimal@3.7.3-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, Redistribution, use in source, binary forms, with, without, By obtaining, using, and/or copying this software and/or its, Permission to use, copy, modify, distribute this software and, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person, Permission is hereby granted, free of charge, to any person obtaining, distribute this software, its, This software is provided as-is, without express, distribute this software for any, * Permission to use this software in any way is granted without", + "licenseDeclared": "GPL-2.0, Redistribution, use in source, binary forms, with, without, By obtaining, using, and/or copying this software and/or its, Permission to use, copy, modify, distribute this software and, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person, Permission is hereby granted, free of charge, to any person obtaining, distribute this software, its, This software is provided as-is, without express, distribute this software for any, * Permission to use this software in any way is granted without", + "name": "python3.7-minimal", + "sourceInfo": "built package from: python3.7 3.7.3-2+deb10u2", + "versionInfo": "3.7.3-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-7fd0ba5c2395e0c6", + "attributionTexts": [ + "LayerDigest: sha256:ef7778ed4c65afb1a1cb2319b38ad8ef211b1705974f751c31b21d58cfb503db", + "LayerDiffID: sha256:d0b804499a9363d1ec9cbf7d82b717cc3741f55ef68a8c2b7165fbab2296bb01" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/nodejs-doc@10.24.0~dfsg-1~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Expat, NTP~MIT, ISC, BSD-3-clause~Google, BSD-1-clause, BSD-2-clause~contributors, BSD-2-clause~author, BSD-3-clause~author, BSD-3-clause~contributors, GPL-3.0, GPL-2.0, Expat~Wu, MIT~Prototype, Apache-2.0, BSD-3-clause~contributors-author, BSD-3-clause~holders, OpenSSL, SSLeay, MIT/X11, BSD-3-clause~Sun, BSD-4-clause~author, BSD-3-clause~Intel, ISC-no-disclaim, Zlib, MPL-2.0, curl", + "licenseDeclared": "Expat, NTP~MIT, ISC, BSD-3-clause~Google, BSD-1-clause, BSD-2-clause~contributors, BSD-2-clause~author, BSD-3-clause~author, BSD-3-clause~contributors, GPL-3.0, GPL-2.0, Expat~Wu, MIT~Prototype, Apache-2.0, BSD-3-clause~contributors-author, BSD-3-clause~holders, OpenSSL, SSLeay, MIT/X11, BSD-3-clause~Sun, BSD-4-clause~author, BSD-3-clause~Intel, ISC-no-disclaim, Zlib, MPL-2.0, curl", + "name": "nodejs-doc", + "sourceInfo": "built package from: nodejs 10.24.0~dfsg-1~deb10u1", + "versionInfo": "10.24.0~dfsg-1~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-800514f30841d332", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libncursesw5-dev@6.1+20181013-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libncursesw5-dev", + "sourceInfo": "built package from: ncurses 6.1+20181013-2+deb10u2", + "versionInfo": "6.1+20181013-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-80b18b95c9cc9549", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/librsvg2-2@2.44.10-2.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, BSD-3-Clause, Expat, Unlicense, Apache-2.0, MPL-2.0, BSD-2-Clause, Sun-permissive, Boost-1.0", + "licenseDeclared": "LGPL-2.0, BSD-3-Clause, Expat, Unlicense, Apache-2.0, MPL-2.0, BSD-2-Clause, Sun-permissive, Boost-1.0", + "name": "librsvg2-2", + "sourceInfo": "built package from: librsvg 2.44.10-2.1", + "versionInfo": "2.44.10-2.1" + }, + { + "SPDXID": "SPDXRef-Package-8134081a9a6b6bc5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmpx2@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libmpx2", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-81b6ea3cbc85e111", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libjpeg-dev@1:1.5.2-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-BY-LC-NE, BSD-3, Expat", + "licenseDeclared": "BSD-BY-LC-NE, BSD-3, Expat", + "name": "libjpeg-dev", + "sourceInfo": "built package from: libjpeg-turbo 1:1.5.2-2+deb10u1", + "versionInfo": "1:1.5.2-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-8302d5afe26e7835", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/xmlrpc@0.3.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-c8b50c4cd74f7167" + ], + "licenseConcluded": "Ruby", + "licenseDeclared": "Ruby", + "name": "xmlrpc", + "versionInfo": "0.3.0" + }, + { + "SPDXID": "SPDXRef-Package-8371a237cc235653", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fluent-plugin-detect-exceptions@0.0.13", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-515c25dff75d4464" + ], + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "fluent-plugin-detect-exceptions", + "versionInfo": "0.0.13" + }, + { + "SPDXID": "SPDXRef-Package-83c9f297ece7c123", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickwand-6-headers@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libmagickwand-6-headers", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-83e4fdb7a809fc28", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxml2@2.9.4+dfsg1-7+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT-1, ISC", + "licenseDeclared": "MIT-1, ISC", + "name": "libxml2", + "sourceInfo": "built package from: libxml2 2.9.4+dfsg1-7+deb10u1", + "versionInfo": "2.9.4+dfsg1-7+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-83fb28ec7339ae6e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgdbm-dev@1.18.1-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GPL-2.0, GFDL-NIV-1.3+", + "licenseDeclared": "GPL-3.0, GPL-2.0, GFDL-NIV-1.3+", + "name": "libgdbm-dev", + "sourceInfo": "built package from: gdbm 1.18.1-4", + "versionInfo": "1.18.1-4" + }, + { + "SPDXID": "SPDXRef-Package-847a56d89217bc1a", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libisl19@0.20-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, BSD-2-Clause, LGPL-2.1, LGPL-2.0", + "licenseDeclared": "MIT, BSD-2-Clause, LGPL-2.1, LGPL-2.0", + "name": "libisl19", + "sourceInfo": "built package from: isl 0.20-2", + "versionInfo": "0.20-2" + }, + { + "SPDXID": "SPDXRef-Package-847e65910700dc06", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libtasn1-6@4.13-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, LGPL-2.1, GPL-3.0, GFDL-1.3", + "licenseDeclared": "LGPL-3.0, LGPL-2.1, GPL-3.0, GFDL-1.3", + "name": "libtasn1-6", + "sourceInfo": "built package from: libtasn1-6 4.13-3", + "versionInfo": "4.13-3" + }, + { + "SPDXID": "SPDXRef-Package-85e173a6683042d4", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libbinutils@2.31.1-16?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libbinutils", + "sourceInfo": "built package from: binutils 2.31.1-16", + "versionInfo": "2.31.1-16" + }, + { + "SPDXID": "SPDXRef-Package-86340f89de09fdbf", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python3-distutils@3.7.3-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Python-2.0", + "licenseDeclared": "Python-2.0", + "name": "python3-distutils", + "sourceInfo": "built package from: python3-stdlib-extensions 3.7.3-1", + "versionInfo": "3.7.3-1" + }, + { + "SPDXID": "SPDXRef-Package-86777ccc116c497b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickwand-6.q16-dev@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "licenseDeclared": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "name": "libmagickwand-6.q16-dev", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-867f5455852a6358", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libaprutil1@1.6.1-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "libaprutil1", + "sourceInfo": "built package from: apr-util 1.6.1-4", + "versionInfo": "1.6.1-4" + }, + { + "SPDXID": "SPDXRef-Package-871a6d9263da4386", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/ncurses-bin@6.1+20181013-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, BSD-3-Clause", + "licenseDeclared": "MIT, BSD-3-Clause", + "name": "ncurses-bin", + "sourceInfo": "built package from: ncurses 6.1+20181013-2+deb10u2", + "versionInfo": "6.1+20181013-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-876135a4b6d69872", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxslt1-dev@1.1.32-2.2~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxslt1-dev", + "sourceInfo": "built package from: libxslt 1.1.32-2.2~deb10u1", + "versionInfo": "1.1.32-2.2~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-885c6578f3659652", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/uuid-dev@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "uuid-dev", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-88746d9375f00e42", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/rdoc@6.0.1.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-21c05387f9618dca" + ], + "licenseConcluded": "Ruby", + "licenseDeclared": "Ruby", + "name": "rdoc", + "versionInfo": "6.0.1.1" + }, + { + "SPDXID": "SPDXRef-Package-8895ecba46b314aa", + "attributionTexts": [ + "LayerDigest: sha256:ef7778ed4c65afb1a1cb2319b38ad8ef211b1705974f751c31b21d58cfb503db", + "LayerDiffID: sha256:d0b804499a9363d1ec9cbf7d82b717cc3741f55ef68a8c2b7165fbab2296bb01" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libbrotli1@1.0.7-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libbrotli1", + "sourceInfo": "built package from: brotli 1.0.7-2+deb10u1", + "versionInfo": "1.0.7-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-88f8e3722edac0f0", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/git-man@1:2.20.1-2+deb10u3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.1, EDL-1.0, Expat, BSD-2-Clause, GPL-1.0, Artistic-1, GPL-3.0, Artistic, ISC, mingw-runtime, Boost, dlmalloc, Apache-2.0, LGPL-2.0", + "licenseDeclared": "GPL-2.0, LGPL-2.1, EDL-1.0, Expat, BSD-2-Clause, GPL-1.0, Artistic-1, GPL-3.0, Artistic, ISC, mingw-runtime, Boost, dlmalloc, Apache-2.0, LGPL-2.0", + "name": "git-man", + "sourceInfo": "built package from: git 1:2.20.1-2+deb10u3", + "versionInfo": "1:2.20.1-2+deb10u3" + }, + { + "SPDXID": "SPDXRef-Package-890e6dec52b75068", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/diffutils@1:3.7-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GFDL", + "licenseDeclared": "GPL-3.0, GFDL", + "name": "diffutils", + "sourceInfo": "built package from: diffutils 1:3.7-3", + "versionInfo": "1:3.7-3" + }, + { + "SPDXID": "SPDXRef-Package-89fc40165ef70eb7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/patch@2.7.6-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "patch", + "sourceInfo": "built package from: patch 2.7.6-3+deb10u1", + "versionInfo": "2.7.6-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-8afe1ddd4b684c15", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxext6@2:1.3.3-1+b2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LicenseRef-C-Ares, MIT", + "licenseDeclared": "LicenseRef-C-Ares, MIT", + "name": "libxext6", + "sourceInfo": "built package from: libxext 2:1.3.3-1", + "versionInfo": "2:1.3.3-1+b2" + }, + { + "SPDXID": "SPDXRef-Package-8b7b7117a127d62f", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liblz4-1@1.8.3-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-2-Clause, GPL-2.0", + "licenseDeclared": "BSD-2-Clause, GPL-2.0", + "name": "liblz4-1", + "sourceInfo": "built package from: lz4 1.8.3-1", + "versionInfo": "1.8.3-1" + }, + { + "SPDXID": "SPDXRef-Package-8bd675e4321e4daa", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmount-dev@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "libmount-dev", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-8c0e2fedddb99fa9", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/perl-base@5.28.1-6+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "perl-base", + "sourceInfo": "built package from: perl 5.28.1-6+deb10u1", + "versionInfo": "5.28.1-6+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-8c2a4d03f0fba45b", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/wget@1.20.1-1.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GFDL-1.2", + "licenseDeclared": "GPL-3.0, GFDL-1.2", + "name": "wget", + "sourceInfo": "built package from: wget 1.20.1-1.1", + "versionInfo": "1.20.1-1.1" + }, + { + "SPDXID": "SPDXRef-Package-8c3a003d517e7ab4", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsepol1@2.8-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-3.0", + "licenseDeclared": "LGPL-3.0, GPL-3.0", + "name": "libsepol1", + "sourceInfo": "built package from: libsepol 2.8-1", + "versionInfo": "2.8-1" + }, + { + "SPDXID": "SPDXRef-Package-8ca81cac67268daf", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/ncurses-base@6.1+20181013-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, BSD-3-Clause", + "licenseDeclared": "MIT, BSD-3-Clause", + "name": "ncurses-base", + "sourceInfo": "built package from: ncurses 6.1+20181013-2+deb10u2", + "versionInfo": "6.1+20181013-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-8ce9c711ee67d098", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsigsegv2@2.12-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, GPL-2.0-with-autoconf-exception, permissive-fsf, permissive-other", + "licenseDeclared": "GPL-2.0, GPL-2.0-with-autoconf-exception, permissive-fsf, permissive-other", + "name": "libsigsegv2", + "sourceInfo": "built package from: libsigsegv 2.12-2", + "versionInfo": "2.12-2" + }, + { + "SPDXID": "SPDXRef-Package-8cef463190b14865", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libbz2-1.0@1.0.6-9.2~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-variant, GPL-2.0", + "licenseDeclared": "BSD-variant, GPL-2.0", + "name": "libbz2-1.0", + "sourceInfo": "built package from: bzip2 1.0.6-9.2~deb10u1", + "versionInfo": "1.0.6-9.2~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-8cf76ab78a2e2833", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libldap-common@2.4.47+dfsg-3+deb10u5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-4-Clause-UC, BSD-3-Clause, MIT, ISC, LicenseRef-C-Ares", + "licenseDeclared": "BSD-4-Clause-UC, BSD-3-Clause, MIT, ISC, LicenseRef-C-Ares", + "name": "libldap-common", + "sourceInfo": "built package from: openldap 2.4.47+dfsg-3+deb10u5", + "versionInfo": "2.4.47+dfsg-3+deb10u5" + }, + { + "SPDXID": "SPDXRef-Package-8d0b539acad89ece", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libp11-kit0@0.23.15-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause, permissive-like-automake-output, ISC, ISC+IBM, same-as-rest-of-p11kit", + "licenseDeclared": "BSD-3-Clause, permissive-like-automake-output, ISC, ISC+IBM, same-as-rest-of-p11kit", + "name": "libp11-kit0", + "sourceInfo": "built package from: p11-kit 0.23.15-2+deb10u1", + "versionInfo": "0.23.15-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-8d1b83ccbbe7a657", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/date@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-9b36710b2dfd3203" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "date", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-8dcb22a88d94043e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libltdl7@2.4.6-9?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GFDL", + "licenseDeclared": "GPL-3.0, GFDL", + "name": "libltdl7", + "sourceInfo": "built package from: libtool 2.4.6-9", + "versionInfo": "2.4.6-9" + }, + { + "SPDXID": "SPDXRef-Package-8de7744eb4197c06", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/strscan@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-db76a60fb42672e3" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "strscan", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-8f3dd1f970cb1b07", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgraphite2-3@1.3.13-7?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, MPL-1.1, GPL-2.0, public-domain, Artistic, GPL-1.0, custom-sil-open-font-license", + "licenseDeclared": "LGPL-2.1, MPL-1.1, GPL-2.0, public-domain, Artistic, GPL-1.0, custom-sil-open-font-license", + "name": "libgraphite2-3", + "sourceInfo": "built package from: graphite2 1.3.13-7", + "versionInfo": "1.3.13-7" + }, + { + "SPDXID": "SPDXRef-Package-9035f7a0b5e13e86", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libdjvulibre21@3.5.27.1-10?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libdjvulibre21", + "sourceInfo": "built package from: djvulibre 3.5.27.1-10", + "versionInfo": "3.5.27.1-10" + }, + { + "SPDXID": "SPDXRef-Package-903c6c865524f5e4", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libtiffxx5@4.1.0+git191117-2~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Hylafax", + "licenseDeclared": "Hylafax", + "name": "libtiffxx5", + "sourceInfo": "built package from: tiff 4.1.0+git191117-2~deb10u1", + "versionInfo": "4.1.0+git191117-2~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-9045e43fba3e46c9", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/http-accept@1.7.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-db5f9504237dc6e" + ], + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "http-accept", + "versionInfo": "1.7.0" + }, + { + "SPDXID": "SPDXRef-Package-912ae0f8767007b9", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpython3.7-minimal@3.7.3-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, Redistribution, use in source, binary forms, with, without, By obtaining, using, and/or copying this software and/or its, Permission to use, copy, modify, distribute this software and, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person, Permission is hereby granted, free of charge, to any person obtaining, distribute this software, its, This software is provided as-is, without express, distribute this software for any, * Permission to use this software in any way is granted without", + "licenseDeclared": "GPL-2.0, Redistribution, use in source, binary forms, with, without, By obtaining, using, and/or copying this software and/or its, Permission to use, copy, modify, distribute this software and, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person, Permission is hereby granted, free of charge, to any person obtaining, distribute this software, its, This software is provided as-is, without express, distribute this software for any, * Permission to use this software in any way is granted without", + "name": "libpython3.7-minimal", + "sourceInfo": "built package from: python3.7 3.7.3-2+deb10u2", + "versionInfo": "3.7.3-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-912e8bc590e039f2", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libexif-dev@0.6.21-5.1+deb10u5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, BSD-2-Clause, GPL-2.0", + "licenseDeclared": "LGPL-2.1, BSD-2-Clause, GPL-2.0", + "name": "libexif-dev", + "sourceInfo": "built package from: libexif 0.6.21-5.1+deb10u5", + "versionInfo": "0.6.21-5.1+deb10u5" + }, + { + "SPDXID": "SPDXRef-Package-91a2296eb5544b5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpthread-stubs0-dev@0.4-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libpthread-stubs0-dev", + "sourceInfo": "built package from: libpthread-stubs 0.4-1", + "versionInfo": "0.4-1" + }, + { + "SPDXID": "SPDXRef-Package-91dfc2a45d789935", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libapt-pkg5.0@1.8.2.2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libapt-pkg5.0", + "sourceInfo": "built package from: apt 1.8.2.2", + "versionInfo": "1.8.2.2" + }, + { + "SPDXID": "SPDXRef-Package-91f9d7edc93b59bc", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/multi_json@1.15.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-dda3950a8b6346e" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "multi_json", + "versionInfo": "1.15.0" + }, + { + "SPDXID": "SPDXRef-Package-9208825c13acd5fb", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/xtrans-dev@1.3.5-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, LicenseRef-C-Ares", + "licenseDeclared": "MIT, LicenseRef-C-Ares", + "name": "xtrans-dev", + "sourceInfo": "built package from: xtrans 1.3.5-1", + "versionInfo": "1.3.5-1" + }, + { + "SPDXID": "SPDXRef-Package-920a389b76c5089d", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsemanage-common@2.8-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-3.0", + "licenseDeclared": "LGPL-3.0, GPL-3.0", + "name": "libsemanage-common", + "sourceInfo": "built package from: libsemanage 2.8-2", + "versionInfo": "2.8-2" + }, + { + "SPDXID": "SPDXRef-Package-92614622b3877d18", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/util-linux@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "util-linux", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-92d76e4c649afdf7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libjpeg62-turbo@1:1.5.2-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-BY-LC-NE, BSD-3, Expat", + "licenseDeclared": "BSD-BY-LC-NE, BSD-3, Expat", + "name": "libjpeg62-turbo", + "sourceInfo": "built package from: libjpeg-turbo 1:1.5.2-2+deb10u1", + "versionInfo": "1:1.5.2-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-92e3299b7eda13b5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libp11-kit-dev@0.23.15-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause, permissive-like-automake-output, ISC, ISC+IBM, same-as-rest-of-p11kit", + "licenseDeclared": "BSD-3-Clause, permissive-like-automake-output, ISC, ISC+IBM, same-as-rest-of-p11kit", + "name": "libp11-kit-dev", + "sourceInfo": "built package from: p11-kit 0.23.15-2+deb10u1", + "versionInfo": "0.23.15-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-92f1545e6d17521d", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/http@4.4.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-59685867d7685a04" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "http", + "versionInfo": "4.4.1" + }, + { + "SPDXID": "SPDXRef-Package-93d57f56f28ce25b", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libdebconfclient0@0.249?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "libdebconfclient0", + "sourceInfo": "built package from: cdebconf 0.249", + "versionInfo": "0.249" + }, + { + "SPDXID": "SPDXRef-Package-945dbaf93cb8f0b9", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/automake@1:1.16.1-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, GPL-3.0, GFDL-NIV-1.3+, GFDL-1.3, permissive", + "licenseDeclared": "GPL-2.0, GPL-3.0, GFDL-NIV-1.3+, GFDL-1.3, permissive", + "name": "automake", + "sourceInfo": "built package from: automake-1.16 1:1.16.1-4", + "versionInfo": "1:1.16.1-4" + }, + { + "SPDXID": "SPDXRef-Package-94b777a179dd0645", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libtiff5@4.1.0+git191117-2~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Hylafax", + "licenseDeclared": "Hylafax", + "name": "libtiff5", + "sourceInfo": "built package from: tiff 4.1.0+git191117-2~deb10u1", + "versionInfo": "4.1.0+git191117-2~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-950a7ef4104bca2", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/dbm@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-5039b4dd5be61326" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "dbm", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-955ece6da65e436f", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/test-unit@3.1.9", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-4f1c92731740d645" + ], + "licenseConcluded": "Ruby, PSFL", + "licenseDeclared": "Ruby, PSFL", + "name": "test-unit", + "versionInfo": "3.1.9" + }, + { + "SPDXID": "SPDXRef-Package-967f0b7f931cd78", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libasan5@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libasan5", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-9690b726bbf4d63a", + "attributionTexts": [ + "LayerDigest: sha256:ef7778ed4c65afb1a1cb2319b38ad8ef211b1705974f751c31b21d58cfb503db", + "LayerDiffID: sha256:d0b804499a9363d1ec9cbf7d82b717cc3741f55ef68a8c2b7165fbab2296bb01" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libnode64@10.24.0~dfsg-1~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Expat, NTP~MIT, ISC, BSD-3-clause~Google, BSD-1-clause, BSD-2-clause~contributors, BSD-2-clause~author, BSD-3-clause~author, BSD-3-clause~contributors, GPL-3.0, GPL-2.0, Expat~Wu, MIT~Prototype, Apache-2.0, BSD-3-clause~contributors-author, BSD-3-clause~holders, OpenSSL, SSLeay, MIT/X11, BSD-3-clause~Sun, BSD-4-clause~author, BSD-3-clause~Intel, ISC-no-disclaim, Zlib, MPL-2.0, curl", + "licenseDeclared": "Expat, NTP~MIT, ISC, BSD-3-clause~Google, BSD-1-clause, BSD-2-clause~contributors, BSD-2-clause~author, BSD-3-clause~author, BSD-3-clause~contributors, GPL-3.0, GPL-2.0, Expat~Wu, MIT~Prototype, Apache-2.0, BSD-3-clause~contributors-author, BSD-3-clause~holders, OpenSSL, SSLeay, MIT/X11, BSD-3-clause~Sun, BSD-4-clause~author, BSD-3-clause~Intel, ISC-no-disclaim, Zlib, MPL-2.0, curl", + "name": "libnode64", + "sourceInfo": "built package from: nodejs 10.24.0~dfsg-1~deb10u1", + "versionInfo": "10.24.0~dfsg-1~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-96e41ded3fd17de", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcairo2-dev@1.16.0-4+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1", + "licenseDeclared": "LGPL-2.1", + "name": "libcairo2-dev", + "sourceInfo": "built package from: cairo 1.16.0-4+deb10u1", + "versionInfo": "1.16.0-4+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-97215eb83b3cbaa7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickcore-6.q16-dev@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "licenseDeclared": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "name": "libmagickcore-6.q16-dev", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-98b8a60a69ddf188", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/readline-common@7.0-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GFDL", + "licenseDeclared": "GPL-3.0, GFDL", + "name": "readline-common", + "sourceInfo": "built package from: readline 7.0-5", + "versionInfo": "7.0-5" + }, + { + "SPDXID": "SPDXRef-Package-9969002e1d481fa6", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxtables12@1.8.2-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, Artistic-2, custom", + "licenseDeclared": "GPL-2.0, Artistic-2, custom", + "name": "libxtables12", + "sourceInfo": "built package from: iptables 1.8.2-4", + "versionInfo": "1.8.2-4" + }, + { + "SPDXID": "SPDXRef-Package-99e4e2467544af04", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/http_parser.rb@0.6.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-14f66e6492118e2b" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "http_parser.rb", + "versionInfo": "0.6.0" + }, + { + "SPDXID": "SPDXRef-Package-99e822aaa7150b98", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgirepository-1.0-1@1.58.3-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.0, BSD-2-Clause, MIT", + "licenseDeclared": "GPL-2.0, LGPL-2.0, BSD-2-Clause, MIT", + "name": "libgirepository-1.0-1", + "sourceInfo": "built package from: gobject-introspection 1.58.3-2", + "versionInfo": "1.58.3-2" + }, + { + "SPDXID": "SPDXRef-Package-9a48679a5e094d0b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/librsvg2-common@2.44.10-2.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, BSD-3-Clause, Expat, Unlicense, Apache-2.0, MPL-2.0, BSD-2-Clause, Sun-permissive, Boost-1.0", + "licenseDeclared": "LGPL-2.0, BSD-3-Clause, Expat, Unlicense, Apache-2.0, MPL-2.0, BSD-2-Clause, Sun-permissive, Boost-1.0", + "name": "librsvg2-common", + "sourceInfo": "built package from: librsvg 2.44.10-2.1", + "versionInfo": "2.44.10-2.1" + }, + { + "SPDXID": "SPDXRef-Package-9a5b05cc4ed185b1", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libthai-data@0.1.28-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libthai-data", + "sourceInfo": "built package from: libthai 0.1.28-2", + "versionInfo": "0.1.28-2" + }, + { + "SPDXID": "SPDXRef-Package-9b41bfb9f8fa54f3", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/mime-types-data@3.2021.0225", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-23b1097f60fe4ff5" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "mime-types-data", + "versionInfo": "3.2021.0225" + }, + { + "SPDXID": "SPDXRef-Package-9b66f8d6b74dd6eb", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/debianutils@4.8.6.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "debianutils", + "sourceInfo": "built package from: debianutils 4.8.6.1", + "versionInfo": "4.8.6.1" + }, + { + "SPDXID": "SPDXRef-Package-9bdc1657b1c8590c", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libk5crypto3@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libk5crypto3", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-9c423383920eb8a2", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libstdc++-8-dev@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libstdc++-8-dev", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-9c78ca4a6a449098", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libglib2.0-data@2.58.3-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "licenseDeclared": "LGPL-3.0, Expat, GPL-2.0, Apache-2.0", + "name": "libglib2.0-data", + "sourceInfo": "built package from: glib2.0 2.58.3-2+deb10u2", + "versionInfo": "2.58.3-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-9cfc244611ed73c5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/default-libmysqlclient-dev@1.0.5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "default-libmysqlclient-dev", + "sourceInfo": "built package from: mysql-defaults 1.0.5", + "versionInfo": "1.0.5" + }, + { + "SPDXID": "SPDXRef-Package-9e5ea0adad763b85", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgssapi-krb5-2@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libgssapi-krb5-2", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-9f78d05ddd4d3326", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsvn1@1.10.4-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0, BSD-3-Clause, Utfwidth, Svnwrap, GPL-2.0, GPL-3.0, AFL-3, Expat, Unicode, BSD-2-Clause", + "licenseDeclared": "Apache-2.0, BSD-3-Clause, Utfwidth, Svnwrap, GPL-2.0, GPL-3.0, AFL-3, Expat, Unicode, BSD-2-Clause", + "name": "libsvn1", + "sourceInfo": "built package from: subversion 1.10.4-1+deb10u1", + "versionInfo": "1.10.4-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-a051717309f7e78c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxau-dev@1:1.0.8-1+b2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libxau-dev", + "sourceInfo": "built package from: libxau 1:1.0.8-1", + "versionInfo": "1:1.0.8-1+b2" + }, + { + "SPDXID": "SPDXRef-Package-a09cfc974be4520f", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmpfr6@4.0.2-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0", + "licenseDeclared": "LGPL-3.0", + "name": "libmpfr6", + "sourceInfo": "built package from: mpfr4 4.0.2-1", + "versionInfo": "4.0.2-1" + }, + { + "SPDXID": "SPDXRef-Package-a23376ff469f5e4a", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/e2fsprogs@1.44.5-1+deb10u3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.0", + "licenseDeclared": "GPL-2.0, LGPL-2.0", + "name": "e2fsprogs", + "sourceInfo": "built package from: e2fsprogs 1.44.5-1+deb10u3", + "versionInfo": "1.44.5-1+deb10u3" + }, + { + "SPDXID": "SPDXRef-Package-a2fbfde3e64326e5", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fiddle@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-f421ad278fed879" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "fiddle", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-a354d01e70b0c064", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgcc1@1:8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libgcc1", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "1:8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-a3bd87e038082c9e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libfontconfig1-dev@2.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libfontconfig1-dev", + "sourceInfo": "built package from: fontconfig 2.13.1-2", + "versionInfo": "2.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-a3e26448c88207b7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmpc3@1.1.0-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1", + "licenseDeclared": "LGPL-2.1", + "name": "libmpc3", + "sourceInfo": "built package from: mpclib3 1.1.0-1", + "versionInfo": "1.1.0-1" + }, + { + "SPDXID": "SPDXRef-Package-a4c330759de73d1d", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/cmath@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-bea4fe934e66850" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "cmath", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-a5ced497997789b", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libblkid1@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "libblkid1", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-a5ed2713bf9443c", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/term-ansicolor@1.7.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-283c0fcf1ce181dd" + ], + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "term-ansicolor", + "versionInfo": "1.7.1" + }, + { + "SPDXID": "SPDXRef-Package-a6d69f871ff62504", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/linux-libc-dev@4.19.171-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.1, X11, CRYPTOGAMS, Unicode-data, Xen-interface", + "licenseDeclared": "GPL-2.0, LGPL-2.1, X11, CRYPTOGAMS, Unicode-data, Xen-interface", + "name": "linux-libc-dev", + "sourceInfo": "built package from: linux 4.19.171-2", + "versionInfo": "4.19.171-2" + }, + { + "SPDXID": "SPDXRef-Package-a8c73aa220b1255d", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libyaml-dev@0.2.1-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Expat, permissive", + "licenseDeclared": "Expat, permissive", + "name": "libyaml-dev", + "sourceInfo": "built package from: libyaml 0.2.1-1", + "versionInfo": "0.2.1-1" + }, + { + "SPDXID": "SPDXRef-Package-a9636aea35344da4", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcap2@1:2.25-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause, GPL-2.0", + "licenseDeclared": "BSD-3-Clause, GPL-2.0", + "name": "libcap2", + "sourceInfo": "built package from: libcap2 1:2.25-2", + "versionInfo": "1:2.25-2" + }, + { + "SPDXID": "SPDXRef-Package-a9d0ff7e5cf0fb5", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpam-runtime@1.3.1-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "libpam-runtime", + "sourceInfo": "built package from: pam 1.3.1-5", + "versionInfo": "1.3.1-5" + }, + { + "SPDXID": "SPDXRef-Package-aa78538a959604fd", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickcore-6-arch-config@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "licenseDeclared": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "name": "libmagickcore-6-arch-config", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-abef1fd51676531e", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcurl3-gnutls@7.64.0-4+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "curl, ISC, BSD-3-Clause, public-domain, BSD-4-Clause, other", + "licenseDeclared": "curl, ISC, BSD-3-Clause, public-domain, BSD-4-Clause, other", + "name": "libcurl3-gnutls", + "sourceInfo": "built package from: curl 7.64.0-4+deb10u1", + "versionInfo": "7.64.0-4+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-ac6bdaa9638615c5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/comerr-dev@2.1-1.44.5-1+deb10u3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.0", + "licenseDeclared": "GPL-2.0, LGPL-2.0", + "name": "comerr-dev", + "sourceInfo": "built package from: e2fsprogs 1.44.5-1+deb10u3", + "versionInfo": "2.1-1.44.5-1+deb10u3" + }, + { + "SPDXID": "SPDXRef-Package-ac72ac877c267087", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/foo@0.0.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-f834608e337889d9" + ], + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "foo", + "versionInfo": "0.0.1" + }, + { + "SPDXID": "SPDXRef-Package-acce92ca006784b5", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/ca-certificates@20200601~deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "...", + "licenseDeclared": "...", + "name": "ca-certificates", + "sourceInfo": "built package from: ca-certificates 20200601~deb10u2", + "versionInfo": "20200601~deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-ad2e9725aa42b8b6", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcurl4-openssl-dev@7.64.0-4+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "curl, ISC, BSD-3-Clause, public-domain, BSD-4-Clause, other", + "licenseDeclared": "curl, ISC, BSD-3-Clause, public-domain, BSD-4-Clause, other", + "name": "libcurl4-openssl-dev", + "sourceInfo": "built package from: curl 7.64.0-4+deb10u1", + "versionInfo": "7.64.0-4+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-ad83dd757466ff5e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libwebpmux3@0.6.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "libwebpmux3", + "sourceInfo": "built package from: libwebp 0.6.1-2", + "versionInfo": "0.6.1-2" + }, + { + "SPDXID": "SPDXRef-Package-afb15084adb3d3a2", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/xorg-sgml-doctools@1:1.11-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "xorg-sgml-doctools", + "sourceInfo": "built package from: xorg-sgml-doctools 1:1.11-1", + "versionInfo": "1:1.11-1" + }, + { + "SPDXID": "SPDXRef-Package-afcd5752c2589b0c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpq5@11.10-0+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "PostgreSQL, Custom-regex, Tcl, Custom-pg_dump, Snowball, Custom-Unicode, double-metaphone, GPL-1.0, Artistic, nagaysau-ishii, blf, BSD-3-Clause, BSD-2-Clause, imath, rijndael", + "licenseDeclared": "PostgreSQL, Custom-regex, Tcl, Custom-pg_dump, Snowball, Custom-Unicode, double-metaphone, GPL-1.0, Artistic, nagaysau-ishii, blf, BSD-3-Clause, BSD-2-Clause, imath, rijndael", + "name": "libpq5", + "sourceInfo": "built package from: postgresql-11 11.10-0+deb10u1", + "versionInfo": "11.10-0+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-b0139c7641a7abec", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/mime-support@3.62?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ad-hoc, Bellcore", + "licenseDeclared": "ad-hoc, Bellcore", + "name": "mime-support", + "sourceInfo": "built package from: mime-support 3.62", + "versionInfo": "3.62" + }, + { + "SPDXID": "SPDXRef-Package-b04560240cc4bd09", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsqlite3-dev@3.27.2-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "public-domain, GPL-2.0", + "licenseDeclared": "public-domain, GPL-2.0", + "name": "libsqlite3-dev", + "sourceInfo": "built package from: sqlite3 3.27.2-3+deb10u1", + "versionInfo": "3.27.2-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-b06b08ea283bd8ee", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/io-console@0.4.6", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-fa686adffd1942a4" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "io-console", + "versionInfo": "0.4.6" + }, + { + "SPDXID": "SPDXRef-Package-b15a650745f0fa83", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/autotools-dev@20180224.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "autotools-dev", + "sourceInfo": "built package from: autotools-dev 20180224.1", + "versionInfo": "20180224.1" + }, + { + "SPDXID": "SPDXRef-Package-b199b8f68e8baeff", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/perl-modules-5.28@5.28.1-6+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-1.0, Artistic, Expat, REGCOMP, GPL-2.0-with-bison-exception, Unicode, S2P, BZIP, Zlib, GPL-2.0, RRA-KEEP-THIS-NOTICE, BSD-3-clause-with-weird-numbering, CC0-1.0, TEXT-TABS, BSD-4-clause-POWERDOG, BSD-3-clause-GENERIC, BSD-3-Clause, SDBM-PUBLIC-DOMAIN, DONT-CHANGE-THE-GPL, Artistic-dist, LGPL-2.1, Artistic-2, HSIEH-DERIVATIVE, HSIEH-BSD", + "licenseDeclared": "GPL-1.0, Artistic, Expat, REGCOMP, GPL-2.0-with-bison-exception, Unicode, S2P, BZIP, Zlib, GPL-2.0, RRA-KEEP-THIS-NOTICE, BSD-3-clause-with-weird-numbering, CC0-1.0, TEXT-TABS, BSD-4-clause-POWERDOG, BSD-3-clause-GENERIC, BSD-3-Clause, SDBM-PUBLIC-DOMAIN, DONT-CHANGE-THE-GPL, Artistic-dist, LGPL-2.1, Artistic-2, HSIEH-DERIVATIVE, HSIEH-BSD", + "name": "perl-modules-5.28", + "sourceInfo": "built package from: perl 5.28.1-6+deb10u1", + "versionInfo": "5.28.1-6+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-b1a57522e3ab688d", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgnutlsxx28@3.6.7-4+deb10u6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libgnutlsxx28", + "sourceInfo": "built package from: gnutls28 3.6.7-4+deb10u6", + "versionInfo": "3.6.7-4+deb10u6" + }, + { + "SPDXID": "SPDXRef-Package-b2ab9e915f40cb41", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libwmf0.2-7@0.2.8.4-14?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0", + "licenseDeclared": "LGPL-2.0", + "name": "libwmf0.2-7", + "sourceInfo": "built package from: libwmf 0.2.8.4-14", + "versionInfo": "0.2.8.4-14" + }, + { + "SPDXID": "SPDXRef-Package-b2ce54377238a88d", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libicu-dev@63.1-6+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ICU, Unicode-DFS-2015", + "licenseDeclared": "ICU, Unicode-DFS-2015", + "name": "libicu-dev", + "sourceInfo": "built package from: icu 63.1-6+deb10u1", + "versionInfo": "63.1-6+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-b3a32f20416ef93d", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgdbm6@1.18.1-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GPL-2.0, GFDL-NIV-1.3+", + "licenseDeclared": "GPL-3.0, GPL-2.0, GFDL-NIV-1.3+", + "name": "libgdbm6", + "sourceInfo": "built package from: gdbm 1.18.1-4", + "versionInfo": "1.18.1-4" + }, + { + "SPDXID": "SPDXRef-Package-b441afa6d5a843b5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libitm1@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libitm1", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-b494d06e2c30badd", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/serverengine@2.2.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-d77d5c9a873c5bdd" + ], + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "serverengine", + "versionInfo": "2.2.3" + }, + { + "SPDXID": "SPDXRef-Package-b4fdc212b229cc18", + "attributionTexts": [ + "LayerDigest: sha256:ef7778ed4c65afb1a1cb2319b38ad8ef211b1705974f751c31b21d58cfb503db", + "LayerDiffID: sha256:d0b804499a9363d1ec9cbf7d82b717cc3741f55ef68a8c2b7165fbab2296bb01" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libuv1@1.24.1-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Expat, ISC, BSD-1-clause, BSD-2-Clause, GPL-3.0, BSD-3-Clause", + "licenseDeclared": "Expat, ISC, BSD-1-clause, BSD-2-Clause, GPL-3.0, BSD-3-Clause", + "name": "libuv1", + "sourceInfo": "built package from: libuv1 1.24.1-1", + "versionInfo": "1.24.1-1" + }, + { + "SPDXID": "SPDXRef-Package-b50f5cfb82c11e50", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libseccomp2@2.3.3-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1", + "licenseDeclared": "LGPL-2.1", + "name": "libseccomp2", + "sourceInfo": "built package from: libseccomp 2.3.3-4", + "versionInfo": "2.3.3-4" + }, + { + "SPDXID": "SPDXRef-Package-b5485ab521b6927f", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/pinentry-curses@1.1.0-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, X11, LGPL-3.0", + "licenseDeclared": "GPL-2.0, X11, LGPL-3.0", + "name": "pinentry-curses", + "sourceInfo": "built package from: pinentry 1.1.0-2", + "versionInfo": "1.1.0-2" + }, + { + "SPDXID": "SPDXRef-Package-b61d94acf74f6a72", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxcb-render0-dev@1.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxcb-render0-dev", + "sourceInfo": "built package from: libxcb 1.13.1-2", + "versionInfo": "1.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-b65feb9a9f6952b8", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/http-cookie@1.0.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-71aed48a0d5cd57c" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "http-cookie", + "versionInfo": "1.0.3" + }, + { + "SPDXID": "SPDXRef-Package-b6a84917c5df02b0", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/bsdutils@1:2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "bsdutils", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "1:2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-b71a7c91f0d6c315", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liblcms2-2@2.9-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, GPL-2.0", + "licenseDeclared": "MIT, GPL-2.0", + "name": "liblcms2-2", + "sourceInfo": "built package from: lcms2 2.9-3", + "versionInfo": "2.9-3" + }, + { + "SPDXID": "SPDXRef-Package-b741269dafd58839", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/x11proto-core-dev@2018.4-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, SGI", + "licenseDeclared": "MIT, SGI", + "name": "x11proto-core-dev", + "sourceInfo": "built package from: xorgproto 2018.4-4", + "versionInfo": "2018.4-4" + }, + { + "SPDXID": "SPDXRef-Package-b7626a89fcabe50d", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libnuma1@2.0.12-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-3.0, LGPL-3.0", + "name": "libnuma1", + "sourceInfo": "built package from: numactl 2.0.12-1", + "versionInfo": "2.0.12-1" + }, + { + "SPDXID": "SPDXRef-Package-b7a1c9c40e735f98", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/addressable@2.7.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-cd2dbe4c8627035c" + ], + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "addressable", + "versionInfo": "2.7.0" + }, + { + "SPDXID": "SPDXRef-Package-b7ddd4543de002be", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gir1.2-gdkpixbuf-2.0@2.38.1+dfsg-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "licenseDeclared": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "name": "gir1.2-gdkpixbuf-2.0", + "sourceInfo": "built package from: gdk-pixbuf 2.38.1+dfsg-1", + "versionInfo": "2.38.1+dfsg-1" + }, + { + "SPDXID": "SPDXRef-Package-b7f0f066b4fcd2e0", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libelf1@0.176-1.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, GPL-3.0, LGPL-3.0", + "name": "libelf1", + "sourceInfo": "built package from: elfutils 0.176-1.1", + "versionInfo": "0.176-1.1" + }, + { + "SPDXID": "SPDXRef-Package-b834a37045ba0def", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libunistring2@0.9.10-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-2.0, FreeSoftware, GPL-2+ with distribution exception, GPL-3.0, GFDL-1.2+, MIT, GFDL-1.2", + "licenseDeclared": "LGPL-3.0, GPL-2.0, FreeSoftware, GPL-2+ with distribution exception, GPL-3.0, GFDL-1.2+, MIT, GFDL-1.2", + "name": "libunistring2", + "sourceInfo": "built package from: libunistring 0.9.10-1", + "versionInfo": "0.9.10-1" + }, + { + "SPDXID": "SPDXRef-Package-b84a8f368a0e6b2f", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/coreutils@8.30-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "coreutils", + "sourceInfo": "built package from: coreutils 8.30-3", + "versionInfo": "8.30-3" + }, + { + "SPDXID": "SPDXRef-Package-b905a90114b6f01d", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxt-dev@1:1.1.5-1+b3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxt-dev", + "sourceInfo": "built package from: libxt 1:1.1.5-1", + "versionInfo": "1:1.1.5-1+b3" + }, + { + "SPDXID": "SPDXRef-Package-b9088362309e6e97", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/icu-devtools@63.1-6+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ICU, Unicode-DFS-2015", + "licenseDeclared": "ICU, Unicode-DFS-2015", + "name": "icu-devtools", + "sourceInfo": "built package from: icu 63.1-6+deb10u1", + "versionInfo": "63.1-6+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-b9860d5ef0605203", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxcb-render0@1.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxcb-render0", + "sourceInfo": "built package from: libxcb 1.13.1-2", + "versionInfo": "1.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-b9a600283f261ef3", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpcre2-8-0@10.32-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libpcre2-8-0", + "sourceInfo": "built package from: pcre2 10.32-5", + "versionInfo": "10.32-5" + }, + { + "SPDXID": "SPDXRef-Package-ba1f42e7270fe8ab", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/thor@1.1.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-85b5947892d5c29e" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "thor", + "versionInfo": "1.1.0" + }, + { + "SPDXID": "SPDXRef-Package-bb19cb657d3c734a", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/make@4.2.1-1.2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "make", + "sourceInfo": "built package from: make-dfsg 4.2.1-1.2", + "versionInfo": "4.2.1-1.2" + }, + { + "SPDXID": "SPDXRef-Package-bb8456910f77a8b7", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/simplecov@0.16.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-917f29a5996816f9" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "simplecov", + "versionInfo": "0.16.1" + }, + { + "SPDXID": "SPDXRef-Package-bba2fe62be430500", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/etc@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-af446aff14d6d8ff" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "etc", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-bba3f83f4e482d35", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsepol1-dev@2.8-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-3.0", + "licenseDeclared": "LGPL-3.0, GPL-3.0", + "name": "libsepol1-dev", + "sourceInfo": "built package from: libsepol 2.8-1", + "versionInfo": "2.8-1" + }, + { + "SPDXID": "SPDXRef-Package-bcaacee2e6641d7a", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libbz2-dev@1.0.6-9.2~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libbz2-dev", + "sourceInfo": "built package from: bzip2 1.0.6-9.2~deb10u1", + "versionInfo": "1.0.6-9.2~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-bcf538c2d6e98680", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libnettle6@3.4.1-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, LGPL-2.0, other, GPL-2.0, GPL-2.0-with-autoconf-exception, public-domain, GAP, LGPL-3.0, GPL-3.0", + "licenseDeclared": "LGPL-2.1, LGPL-2.0, other, GPL-2.0, GPL-2.0-with-autoconf-exception, public-domain, GAP, LGPL-3.0, GPL-3.0", + "name": "libnettle6", + "sourceInfo": "built package from: nettle 3.4.1-1", + "versionInfo": "3.4.1-1" + }, + { + "SPDXID": "SPDXRef-Package-bd4cd99cd3e6b6f5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxdmcp6@1:1.1.2-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libxdmcp6", + "sourceInfo": "built package from: libxdmcp 1:1.1.2-3", + "versionInfo": "1:1.1.2-3" + }, + { + "SPDXID": "SPDXRef-Package-bd846d8e9309939", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpython3-stdlib@3.7.3-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Python-2.0", + "licenseDeclared": "MIT, Python-2.0", + "name": "libpython3-stdlib", + "sourceInfo": "built package from: python3-defaults 3.7.3-1", + "versionInfo": "3.7.3-1" + }, + { + "SPDXID": "SPDXRef-Package-bdb59f452bdda108", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/ucf@3.0038+nmu1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "ucf", + "sourceInfo": "built package from: ucf 3.0038+nmu1", + "versionInfo": "3.0038+nmu1" + }, + { + "SPDXID": "SPDXRef-Package-be3701b8d3fe0562", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/http-parser@1.2.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-2bcbcb8df2c093e9" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "http-parser", + "versionInfo": "1.2.3" + }, + { + "SPDXID": "SPDXRef-Package-be62a3090310955", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgcrypt20@1.8.4-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-2.0", + "licenseDeclared": "LGPL-3.0, GPL-2.0", + "name": "libgcrypt20", + "sourceInfo": "built package from: libgcrypt20 1.8.4-5", + "versionInfo": "1.8.4-5" + }, + { + "SPDXID": "SPDXRef-Package-beded330499d4975", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsm-dev@2:1.2.3-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libsm-dev", + "sourceInfo": "built package from: libsm 2:1.2.3-1", + "versionInfo": "2:1.2.3-1" + }, + { + "SPDXID": "SPDXRef-Package-c0cf710bb3c247f7", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpam-modules-bin@1.3.1-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "libpam-modules-bin", + "sourceInfo": "built package from: pam 1.3.1-5", + "versionInfo": "1.3.1-5" + }, + { + "SPDXID": "SPDXRef-Package-c24802e7afe41fe4", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/g++-8@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "g++-8", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-c2833b7cf21f8a6d", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpcre3@2:8.39-12?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libpcre3", + "sourceInfo": "built package from: pcre3 2:8.39-12", + "versionInfo": "2:8.39-12" + }, + { + "SPDXID": "SPDXRef-Package-c2c0d5620b0a1c5", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libaudit1@1:2.8.4-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.1, GPL-1.0", + "licenseDeclared": "GPL-2.0, LGPL-2.1, GPL-1.0", + "name": "libaudit1", + "sourceInfo": "built package from: audit 1:2.8.4-3", + "versionInfo": "1:2.8.4-3" + }, + { + "SPDXID": "SPDXRef-Package-c33e5e6f8936564a", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxslt1.1@1.1.32-2.2~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxslt1.1", + "sourceInfo": "built package from: libxslt 1.1.32-2.2~deb10u1", + "versionInfo": "1.1.32-2.2~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-c34d95b9e9e39264", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/sensible-utils@0.0.12?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, All-permissive, configure, installsh", + "licenseDeclared": "GPL-2.0, All-permissive, configure, installsh", + "name": "sensible-utils", + "sourceInfo": "built package from: sensible-utils 0.0.12", + "versionInfo": "0.0.12" + }, + { + "SPDXID": "SPDXRef-Package-c40f0eb76e6fec5f", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/perl@5.28.1-6+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-1.0, Artistic, Expat, REGCOMP, GPL-2.0-with-bison-exception, Unicode, S2P, BZIP, Zlib, GPL-2.0, RRA-KEEP-THIS-NOTICE, BSD-3-clause-with-weird-numbering, CC0-1.0, TEXT-TABS, BSD-4-clause-POWERDOG, BSD-3-clause-GENERIC, BSD-3-Clause, SDBM-PUBLIC-DOMAIN, DONT-CHANGE-THE-GPL, Artistic-dist, LGPL-2.1, Artistic-2, HSIEH-DERIVATIVE, HSIEH-BSD", + "licenseDeclared": "GPL-1.0, Artistic, Expat, REGCOMP, GPL-2.0-with-bison-exception, Unicode, S2P, BZIP, Zlib, GPL-2.0, RRA-KEEP-THIS-NOTICE, BSD-3-clause-with-weird-numbering, CC0-1.0, TEXT-TABS, BSD-4-clause-POWERDOG, BSD-3-clause-GENERIC, BSD-3-Clause, SDBM-PUBLIC-DOMAIN, DONT-CHANGE-THE-GPL, Artistic-dist, LGPL-2.1, Artistic-2, HSIEH-DERIVATIVE, HSIEH-BSD", + "name": "perl", + "sourceInfo": "built package from: perl 5.28.1-6+deb10u1", + "versionInfo": "5.28.1-6+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-c4bcd19d4afdad56", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/ipaddr@1.2.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-b6f4795c10542ff3" + ], + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "ipaddr", + "versionInfo": "1.2.0" + }, + { + "SPDXID": "SPDXRef-Package-c50ebe3c54f0cf0f", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgdk-pixbuf2.0-common@2.38.1+dfsg-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "licenseDeclared": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "name": "libgdk-pixbuf2.0-common", + "sourceInfo": "built package from: gdk-pixbuf 2.38.1+dfsg-1", + "versionInfo": "2.38.1+dfsg-1" + }, + { + "SPDXID": "SPDXRef-Package-c527492651764198", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libyaml-0-2@0.2.1-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Expat, permissive", + "licenseDeclared": "Expat, permissive", + "name": "libyaml-0-2", + "sourceInfo": "built package from: libyaml 0.2.1-1", + "versionInfo": "0.2.1-1" + }, + { + "SPDXID": "SPDXRef-Package-c5bdf6a54856f82c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libtool@2.4.6-9?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GFDL", + "licenseDeclared": "GPL-3.0, GFDL", + "name": "libtool", + "sourceInfo": "built package from: libtool 2.4.6-9", + "versionInfo": "2.4.6-9" + }, + { + "SPDXID": "SPDXRef-Package-c5ee7ca37a15ac4c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libopenexr-dev@2.2.1-4.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "openexr", + "licenseDeclared": "openexr", + "name": "libopenexr-dev", + "sourceInfo": "built package from: openexr 2.2.1-4.1+deb10u1", + "versionInfo": "2.2.1-4.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-c629ede1cd041098", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/simplecov-html@0.10.2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-68d2fc8fa0adeaaa" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "simplecov-html", + "versionInfo": "0.10.2" + }, + { + "SPDXID": "SPDXRef-Package-c6f76c636b94c126", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmariadb3@1:10.3.27-0+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, GPL-verbatim, public-domain, BSD-3-Clause, LGPL-2.1, BSD-2-Clause, LGPL-2.0, unlimited-free-doc, LGPL-3.0, zlib/libpng, GPL-2.0-with-bison-exception, GPL-2+-with-bison-exception, SWsoft, Artistic, GPL-3.0, MIT/X11", + "licenseDeclared": "GPL-2.0, GPL-verbatim, public-domain, BSD-3-Clause, LGPL-2.1, BSD-2-Clause, LGPL-2.0, unlimited-free-doc, LGPL-3.0, zlib/libpng, GPL-2.0-with-bison-exception, GPL-2+-with-bison-exception, SWsoft, Artistic, GPL-3.0, MIT/X11", + "name": "libmariadb3", + "sourceInfo": "built package from: mariadb-10.3 1:10.3.27-0+deb10u1", + "versionInfo": "1:10.3.27-0+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-c707eba2972b49f1", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fluentd@1.12.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-5088bc45a0077c6e" + ], + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "fluentd", + "versionInfo": "1.12.1" + }, + { + "SPDXID": "SPDXRef-Package-c74b67bf40b1041f", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libperl5.28@5.28.1-6+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-1.0, Artistic, Expat, REGCOMP, GPL-2.0-with-bison-exception, Unicode, S2P, BZIP, Zlib, GPL-2.0, RRA-KEEP-THIS-NOTICE, BSD-3-clause-with-weird-numbering, CC0-1.0, TEXT-TABS, BSD-4-clause-POWERDOG, BSD-3-clause-GENERIC, BSD-3-Clause, SDBM-PUBLIC-DOMAIN, DONT-CHANGE-THE-GPL, Artistic-dist, LGPL-2.1, Artistic-2, HSIEH-DERIVATIVE, HSIEH-BSD", + "licenseDeclared": "GPL-1.0, Artistic, Expat, REGCOMP, GPL-2.0-with-bison-exception, Unicode, S2P, BZIP, Zlib, GPL-2.0, RRA-KEEP-THIS-NOTICE, BSD-3-clause-with-weird-numbering, CC0-1.0, TEXT-TABS, BSD-4-clause-POWERDOG, BSD-3-clause-GENERIC, BSD-3-Clause, SDBM-PUBLIC-DOMAIN, DONT-CHANGE-THE-GPL, Artistic-dist, LGPL-2.1, Artistic-2, HSIEH-DERIVATIVE, HSIEH-BSD", + "name": "libperl5.28", + "sourceInfo": "built package from: perl 5.28.1-6+deb10u1", + "versionInfo": "5.28.1-6+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-c75410ed0ae2f05c", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/mercurial@4.8.2-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.1", + "licenseDeclared": "GPL-2.0, LGPL-2.1", + "name": "mercurial", + "sourceInfo": "built package from: mercurial 4.8.2-1+deb10u1", + "versionInfo": "4.8.2-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-c7a34bd2fa6d1852", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libkrb5-3@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libkrb5-3", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-c7e8e99ba2a9901", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libjpeg62-turbo-dev@1:1.5.2-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-BY-LC-NE, BSD-3, Expat", + "licenseDeclared": "BSD-BY-LC-NE, BSD-3, Expat", + "name": "libjpeg62-turbo-dev", + "sourceInfo": "built package from: libjpeg-turbo 1:1.5.2-2+deb10u1", + "versionInfo": "1:1.5.2-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-c7e9ee4975d80564", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libevent-extra-2.1-6@2.1.8-stable-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libevent-extra-2.1-6", + "sourceInfo": "built package from: libevent 2.1.8-stable-4", + "versionInfo": "2.1.8-stable-4" + }, + { + "SPDXID": "SPDXRef-Package-c8308a58a7c34f73", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgnutls-openssl27@3.6.7-4+deb10u6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "The main library is licensed under GNU Lesser, LGPL-3.0, GPL-3.0, GFDL-1.3, CC0 license, The MIT License (MIT), LGPLv3+, GPL-2.0, Apache-2.0", + "licenseDeclared": "The main library is licensed under GNU Lesser, LGPL-3.0, GPL-3.0, GFDL-1.3, CC0 license, The MIT License (MIT), LGPLv3+, GPL-2.0, Apache-2.0", + "name": "libgnutls-openssl27", + "sourceInfo": "built package from: gnutls28 3.6.7-4+deb10u6", + "versionInfo": "3.6.7-4+deb10u6" + }, + { + "SPDXID": "SPDXRef-Package-c877236f1816b067", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libaudit-common@1:2.8.4-3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.1, GPL-1.0", + "licenseDeclared": "GPL-2.0, LGPL-2.1, GPL-1.0", + "name": "libaudit-common", + "sourceInfo": "built package from: audit 1:2.8.4-3", + "versionInfo": "1:2.8.4-3" + }, + { + "SPDXID": "SPDXRef-Package-c8aa6f474dbc1c7c", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsmartcols1@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "libsmartcols1", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-c8f0722d51a9bdcb", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/fonts-dejavu-core@2.37-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "bitstream-vera, GPL-2.0", + "licenseDeclared": "bitstream-vera, GPL-2.0", + "name": "fonts-dejavu-core", + "sourceInfo": "built package from: fonts-dejavu 2.37-1", + "versionInfo": "2.37-1" + }, + { + "SPDXID": "SPDXRef-Package-c906ef1e5055c9a2", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libdpkg-perl@1.19.7?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, BSD-2-Clause, public-domain-s-s-d, public-domain-md5", + "licenseDeclared": "GPL-2.0, BSD-2-Clause, public-domain-s-s-d, public-domain-md5", + "name": "libdpkg-perl", + "sourceInfo": "built package from: dpkg 1.19.7", + "versionInfo": "1.19.7" + }, + { + "SPDXID": "SPDXRef-Package-c9b858593baf6aad", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/mysql-common@5.8+1.0.5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "mysql-common", + "sourceInfo": "built package from: mysql-defaults 1.0.5", + "versionInfo": "5.8+1.0.5" + }, + { + "SPDXID": "SPDXRef-Package-ca8a68f88586c9ed", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/hostname@3.21?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "hostname", + "sourceInfo": "built package from: hostname 3.21", + "versionInfo": "3.21" + }, + { + "SPDXID": "SPDXRef-Package-ca8ffb6e8edcbf0e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libatomic1@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libatomic1", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-cad1b7cc581de740", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/xz-utils@5.2.4-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "PD, probably-PD, GPL-2.0, LGPL-2.1, permissive-fsf, Autoconf, permissive-nowarranty, none, config-h, LGPL-2.0, noderivs, PD-debian, GPL-3.0", + "licenseDeclared": "PD, probably-PD, GPL-2.0, LGPL-2.1, permissive-fsf, Autoconf, permissive-nowarranty, none, config-h, LGPL-2.0, noderivs, PD-debian, GPL-3.0", + "name": "xz-utils", + "sourceInfo": "built package from: xz-utils 5.2.4-1", + "versionInfo": "5.2.4-1" + }, + { + "SPDXID": "SPDXRef-Package-cc5fad0bb22a7aef", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/debian-archive-keyring@2019.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "debian-archive-keyring", + "sourceInfo": "built package from: debian-archive-keyring 2019.1", + "versionInfo": "2019.1" + }, + { + "SPDXID": "SPDXRef-Package-cc6da607837820c0", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpq-dev@11.10-0+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "PostgreSQL, Custom-regex, Tcl, Custom-pg_dump, Snowball, Custom-Unicode, double-metaphone, GPL-1.0, Artistic, nagaysau-ishii, blf, BSD-3-Clause, BSD-2-Clause, imath, rijndael", + "licenseDeclared": "PostgreSQL, Custom-regex, Tcl, Custom-pg_dump, Snowball, Custom-Unicode, double-metaphone, GPL-1.0, Artistic, nagaysau-ishii, blf, BSD-3-Clause, BSD-2-Clause, imath, rijndael", + "name": "libpq-dev", + "sourceInfo": "built package from: postgresql-11 11.10-0+deb10u1", + "versionInfo": "11.10-0+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-ccc25f1a50673fe4", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/base-passwd@3.5.46?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, PD", + "licenseDeclared": "GPL-2.0, PD", + "name": "base-passwd", + "sourceInfo": "built package from: base-passwd 3.5.46", + "versionInfo": "3.5.46" + }, + { + "SPDXID": "SPDXRef-Package-cd375b784f7e7baf", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libreadline-dev@7.0-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libreadline-dev", + "sourceInfo": "built package from: readline 7.0-5", + "versionInfo": "7.0-5" + }, + { + "SPDXID": "SPDXRef-Package-cd3f1284d4c7c499", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsqlite3-0@3.27.2-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "public-domain, GPL-2.0", + "licenseDeclared": "public-domain, GPL-2.0", + "name": "libsqlite3-0", + "sourceInfo": "built package from: sqlite3 3.27.2-3+deb10u1", + "versionInfo": "3.27.2-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-cd8b3e45aecc37a7", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fileutils@1.0.2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-776c249af65f80a" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "fileutils", + "versionInfo": "1.0.2" + }, + { + "SPDXID": "SPDXRef-Package-cf28d319b28b642", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libevent-openssl-2.1-6@2.1.8-stable-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libevent-openssl-2.1-6", + "sourceInfo": "built package from: libevent 2.1.8-stable-4", + "versionInfo": "2.1.8-stable-4" + }, + { + "SPDXID": "SPDXRef-Package-cf86c165b16efe04", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/fluent-plugin-mysqlslowquery@0.0.9", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-1b0c1a7abfdf3750" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "fluent-plugin-mysqlslowquery", + "versionInfo": "0.0.9" + }, + { + "SPDXID": "SPDXRef-Package-cfd7da951d866f62", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libexif12@0.6.21-5.1+deb10u5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, BSD-2-Clause, GPL-2.0", + "licenseDeclared": "LGPL-2.1, BSD-2-Clause, GPL-2.0", + "name": "libexif12", + "sourceInfo": "built package from: libexif 0.6.21-5.1+deb10u5", + "versionInfo": "0.6.21-5.1+deb10u5" + }, + { + "SPDXID": "SPDXRef-Package-cffa2ef169326f23", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libfribidi0@1.0.5-3.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1", + "licenseDeclared": "LGPL-2.1", + "name": "libfribidi0", + "sourceInfo": "built package from: fribidi 1.0.5-3.1+deb10u1", + "versionInfo": "1.0.5-3.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-d05a5c43f40cbb03", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmariadb-dev@1:10.3.27-0+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, GPL-verbatim, public-domain, BSD-3-Clause, LGPL-2.1, BSD-2-Clause, LGPL-2.0, unlimited-free-doc, LGPL-3.0, zlib/libpng, GPL-2.0-with-bison-exception, GPL-2+-with-bison-exception, SWsoft, Artistic, GPL-3.0, MIT/X11", + "licenseDeclared": "GPL-2.0, GPL-verbatim, public-domain, BSD-3-Clause, LGPL-2.1, BSD-2-Clause, LGPL-2.0, unlimited-free-doc, LGPL-3.0, zlib/libpng, GPL-2.0-with-bison-exception, GPL-2+-with-bison-exception, SWsoft, Artistic, GPL-3.0, MIT/X11", + "name": "libmariadb-dev", + "sourceInfo": "built package from: mariadb-10.3 1:10.3.27-0+deb10u1", + "versionInfo": "1:10.3.27-0+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-d0ab4f8021103415", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libserf-1-1@1.3.9-7+b10?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0, Zlib", + "licenseDeclared": "Apache-2.0, Zlib", + "name": "libserf-1-1", + "sourceInfo": "built package from: serf 1.3.9-7", + "versionInfo": "1.3.9-7+b10" + }, + { + "SPDXID": "SPDXRef-Package-d0eca77a65b78800", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/file@1:5.35-4+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-2-Clause-alike, public-domain, BSD-2-Clause-netbsd, BSD-2-Clause-regents, MIT-Old-Style-with-legal-disclaimer-2", + "licenseDeclared": "BSD-2-Clause-alike, public-domain, BSD-2-Clause-netbsd, BSD-2-Clause-regents, MIT-Old-Style-with-legal-disclaimer-2", + "name": "file", + "sourceInfo": "built package from: file 1:5.35-4+deb10u2", + "versionInfo": "1:5.35-4+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-d116eacaeab23b34", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/dash@0.5.10.2-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "dash", + "sourceInfo": "built package from: dash 0.5.10.2-5", + "versionInfo": "0.5.10.2-5" + }, + { + "SPDXID": "SPDXRef-Package-d11b4e2c2a9126b1", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libksba8@1.3.5-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "libksba8", + "sourceInfo": "built package from: libksba 1.3.5-2", + "versionInfo": "1.3.5-2" + }, + { + "SPDXID": "SPDXRef-Package-d11d7965f2fbc3ff", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/dpkg@1.19.7?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, BSD-2-Clause, public-domain-s-s-d, public-domain-md5", + "licenseDeclared": "GPL-2.0, BSD-2-Clause, public-domain-s-s-d, public-domain-md5", + "name": "dpkg", + "sourceInfo": "built package from: dpkg 1.19.7", + "versionInfo": "1.19.7" + }, + { + "SPDXID": "SPDXRef-Package-d18cfe939ac6007c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python3-lib2to3@3.7.3-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Python-2.0", + "licenseDeclared": "Python-2.0", + "name": "python3-lib2to3", + "sourceInfo": "built package from: python3-stdlib-extensions 3.7.3-1", + "versionInfo": "3.7.3-1" + }, + { + "SPDXID": "SPDXRef-Package-d2c0ea0411035bb4", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libfreetype6@2.9.1-3+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, FTL, Catharon-OSL, MIT, BSD-3-Clause, FSFULLR, FSFUL, Permissive, GPL-3.0, Public-Domain, Zlib, OpenGroup-BSD-like", + "licenseDeclared": "GPL-2.0, FTL, Catharon-OSL, MIT, BSD-3-Clause, FSFULLR, FSFUL, Permissive, GPL-3.0, Public-Domain, Zlib, OpenGroup-BSD-like", + "name": "libfreetype6", + "sourceInfo": "built package from: freetype 2.9.1-3+deb10u2", + "versionInfo": "2.9.1-3+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-d4367d0e7c963cc", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libncurses-dev@6.1+20181013-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libncurses-dev", + "sourceInfo": "built package from: ncurses 6.1+20181013-2+deb10u2", + "versionInfo": "6.1+20181013-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-d46b309f3fbeda8e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxt6@1:1.1.5-1+b3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxt6", + "sourceInfo": "built package from: libxt 1:1.1.5-1", + "versionInfo": "1:1.1.5-1+b3" + }, + { + "SPDXID": "SPDXRef-Package-d4c45c4900bfddf5", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/sdbm@1.0.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-ccf15d538d702705" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "sdbm", + "versionInfo": "1.0.0" + }, + { + "SPDXID": "SPDXRef-Package-d4e57f8a33a71413", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsasl2-modules-db@2.1.27+dfsg-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-4-Clause, GPL-3.0", + "licenseDeclared": "BSD-4-Clause, GPL-3.0", + "name": "libsasl2-modules-db", + "sourceInfo": "built package from: cyrus-sasl2 2.1.27+dfsg-1+deb10u1", + "versionInfo": "2.1.27+dfsg-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-d581e1b7eff2722", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgdk-pixbuf2.0-0@2.38.1+dfsg-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "licenseDeclared": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "name": "libgdk-pixbuf2.0-0", + "sourceInfo": "built package from: gdk-pixbuf 2.38.1+dfsg-1", + "versionInfo": "2.38.1+dfsg-1" + }, + { + "SPDXID": "SPDXRef-Package-d5d2b115df9603c5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libblkid-dev@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "libblkid-dev", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-d5e2c04b62cd7627", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libedit2@3.1-20181209-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libedit2", + "sourceInfo": "built package from: libedit 3.1-20181209-1", + "versionInfo": "3.1-20181209-1" + }, + { + "SPDXID": "SPDXRef-Package-d73ede469a2f8a88", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libexpat1-dev@2.2.6-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libexpat1-dev", + "sourceInfo": "built package from: expat 2.2.6-2+deb10u1", + "versionInfo": "2.2.6-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-d8d03fa7ecea36b7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgmpxx4ldbl@2:6.1.2+dfsg-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-2.0, GPL-3.0", + "licenseDeclared": "LGPL-3.0, GPL-2.0, GPL-3.0", + "name": "libgmpxx4ldbl", + "sourceInfo": "built package from: gmp 2:6.1.2+dfsg-4", + "versionInfo": "2:6.1.2+dfsg-4" + }, + { + "SPDXID": "SPDXRef-Package-d988e1bebac5198", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/openssl@1.1.1d-0+deb10u4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "OpenSSL", + "licenseDeclared": "OpenSSL", + "name": "openssl", + "sourceInfo": "built package from: openssl 1.1.1d-0+deb10u4", + "versionInfo": "1.1.1d-0+deb10u4" + }, + { + "SPDXID": "SPDXRef-Package-d98e3de7fea20e11", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libkeyutils1@1.6-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.0", + "licenseDeclared": "GPL-2.0, LGPL-2.0", + "name": "libkeyutils1", + "sourceInfo": "built package from: keyutils 1.6-6", + "versionInfo": "1.6-6" + }, + { + "SPDXID": "SPDXRef-Package-daac27c308c5a641", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/msgpack@1.4.2", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-dec440c01be37d5a" + ], + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "msgpack", + "versionInfo": "1.4.2" + }, + { + "SPDXID": "SPDXRef-Package-dabcf0a6724a1754", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/krb5-multidev@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "krb5-multidev", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-db06150794f17419", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/zlib1g-dev@1:1.2.11.dfsg-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Zlib", + "licenseDeclared": "Zlib", + "name": "zlib1g-dev", + "sourceInfo": "built package from: zlib 1:1.2.11.dfsg-1", + "versionInfo": "1:1.2.11.dfsg-1" + }, + { + "SPDXID": "SPDXRef-Package-dbd0892e119aef63", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/iproute2@4.20.0-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "iproute2", + "sourceInfo": "built package from: iproute2 4.20.0-2+deb10u1", + "versionInfo": "4.20.0-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-dc51fe79cf51b4ac", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libevent-2.1-6@2.1.8-stable-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause", + "licenseDeclared": "BSD-3-Clause", + "name": "libevent-2.1-6", + "sourceInfo": "built package from: libevent 2.1.8-stable-4", + "versionInfo": "2.1.8-stable-4" + }, + { + "SPDXID": "SPDXRef-Package-dd3a37a0b644a6e5", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libc-dev-bin@2.28-10?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libc-dev-bin", + "sourceInfo": "built package from: glibc 2.28-10", + "versionInfo": "2.28-10" + }, + { + "SPDXID": "SPDXRef-Package-dd8e5ed3ce4706d", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libcc1-0@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libcc1-0", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-df1b32b55923282c", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/zlib1g@1:1.2.11.dfsg-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Zlib", + "licenseDeclared": "Zlib", + "name": "zlib1g", + "sourceInfo": "built package from: zlib 1:1.2.11.dfsg-1", + "versionInfo": "1:1.2.11.dfsg-1" + }, + { + "SPDXID": "SPDXRef-Package-e0076c75a60428f7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libxcb-shm0@1.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libxcb-shm0", + "sourceInfo": "built package from: libxcb 1.13.1-2", + "versionInfo": "1.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-e0bb192b5cfce4ae", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libncurses6@6.1+20181013-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libncurses6", + "sourceInfo": "built package from: ncurses 6.1+20181013-2+deb10u2", + "versionInfo": "6.1+20181013-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-e28735c39d179d58", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmaxminddb0@1.3.2-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0, CC-BY-SA, GPL-2.0, GPL-3.0, BSD-2-Clause, BSD-3-Clause, BSD-4-Clause", + "licenseDeclared": "Apache-2.0, CC-BY-SA, GPL-2.0, GPL-3.0, BSD-2-Clause, BSD-3-Clause, BSD-4-Clause", + "name": "libmaxminddb0", + "sourceInfo": "built package from: libmaxminddb 1.3.2-1+deb10u1", + "versionInfo": "1.3.2-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-e2c8d19b750f2cd6", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsystemd0@241-7~deb10u6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, CC0-1.0, GPL-2.0, Expat, public-domain", + "licenseDeclared": "LGPL-2.1, CC0-1.0, GPL-2.0, Expat, public-domain", + "name": "libsystemd0", + "sourceInfo": "built package from: systemd 241-7~deb10u6", + "versionInfo": "241-7~deb10u6" + }, + { + "SPDXID": "SPDXRef-Package-e386ffc295843912", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmnl0@1.0.4-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libmnl0", + "sourceInfo": "built package from: libmnl 1.0.4-2", + "versionInfo": "1.0.4-2" + }, + { + "SPDXID": "SPDXRef-Package-e4542206c50b3548", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpam0g@1.3.1-5?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "libpam0g", + "sourceInfo": "built package from: pam 1.3.1-5", + "versionInfo": "1.3.1-5" + }, + { + "SPDXID": "SPDXRef-Package-e4b7be2e33c921fd", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgmp-dev@2:6.1.2+dfsg-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-2.0, GPL-3.0", + "licenseDeclared": "LGPL-3.0, GPL-2.0, GPL-3.0", + "name": "libgmp-dev", + "sourceInfo": "built package from: gmp 2:6.1.2+dfsg-4", + "versionInfo": "2:6.1.2+dfsg-4" + }, + { + "SPDXID": "SPDXRef-Package-e661534c8e83825f", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libc6@2.28-10?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libc6", + "sourceInfo": "built package from: glibc 2.28-10", + "versionInfo": "2.28-10" + }, + { + "SPDXID": "SPDXRef-Package-e785fd67c4cb88e8", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/dirmngr@2.2.12-1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "licenseDeclared": "GPL-3.0, permissive, LGPL-2.1, Expat, BSD-3-Clause, LGPL-3.0, RFC-Reference, TinySCHEME, CC0-1.0", + "name": "dirmngr", + "sourceInfo": "built package from: gnupg2 2.2.12-1+deb10u1", + "versionInfo": "2.2.12-1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-e79b8e4b2da82181", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpython2-stdlib@2.7.16-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Python-2.0", + "licenseDeclared": "MIT, Python-2.0", + "name": "libpython2-stdlib", + "sourceInfo": "built package from: python-defaults 2.7.16-1", + "versionInfo": "2.7.16-1" + }, + { + "SPDXID": "SPDXRef-Package-e813b6025d3907d5", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/mount@2.33.1-0.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "licenseDeclared": "GPL-2.0, public-domain, BSD-4-Clause, MIT, BSD-2-Clause, BSD-3-Clause, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0", + "name": "mount", + "sourceInfo": "built package from: util-linux 2.33.1-0.1", + "versionInfo": "2.33.1-0.1" + }, + { + "SPDXID": "SPDXRef-Package-e9487ea24e04c44b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/imagemagick-6-common@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "licenseDeclared": "ImageMagick, aclocal, Makefile-in, Imagemagick, ImageMagickPartlibsquish, ImageMagickPartGraphicsMagick, ImageMagickPartlibjpeg, ImageMagickLicensePartFIG, GPL-2.0, BSD-with-FSF-change-public-domain, ImageMagickLicensePartGsview, ImageMagickLicensePartOpenSSH, Magick++, TatcherUlrichPublicDomain, GPL3+-with-Autoconf-Macros-exception, GPL2+-with-Autoconf-Macros-exception, GNU-All-Permissive-License, LGPL-3.0, ImageMagickLicensePartEZXML, Perllikelicence, Artistic, GPL-1.0, GPL3+-with-Autoconf-Macros-exception-GNU, GPL-3.0", + "name": "imagemagick-6-common", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-e94c2ac4e9c541bc", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libss2@1.44.5-1+deb10u3?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libss2", + "sourceInfo": "built package from: e2fsprogs 1.44.5-1+deb10u3", + "versionInfo": "1.44.5-1+deb10u3" + }, + { + "SPDXID": "SPDXRef-Package-e994d16c2e39e572", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libapr1@1.6.5-1+b1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "libapr1", + "sourceInfo": "built package from: apr 1.6.5-1", + "versionInfo": "1.6.5-1+b1" + }, + { + "SPDXID": "SPDXRef-Package-e994e84e73315d56", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libkadm5srv-mit11@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libkadm5srv-mit11", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-ea372d41f1b69ef1", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python3.7@3.7.3-2+deb10u2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, Redistribution, use in source, binary forms, with, without, By obtaining, using, and/or copying this software and/or its, Permission to use, copy, modify, distribute this software and, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person, Permission is hereby granted, free of charge, to any person obtaining, distribute this software, its, This software is provided as-is, without express, distribute this software for any, * Permission to use this software in any way is granted without", + "licenseDeclared": "GPL-2.0, Redistribution, use in source, binary forms, with, without, By obtaining, using, and/or copying this software and/or its, Permission to use, copy, modify, distribute this software and, This software is provided 'as-is', without any express, implied, Permission is hereby granted, free of charge, to any person, Permission is hereby granted, free of charge, to any person obtaining, distribute this software, its, This software is provided as-is, without express, distribute this software for any, * Permission to use this software in any way is granted without", + "name": "python3.7", + "sourceInfo": "built package from: python3.7 3.7.3-2+deb10u2", + "versionInfo": "3.7.3-2+deb10u2" + }, + { + "SPDXID": "SPDXRef-Package-eaab4ac6ac63059e", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libkrb5support0@1.17-3+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0", + "licenseDeclared": "GPL-2.0", + "name": "libkrb5support0", + "sourceInfo": "built package from: krb5 1.17-3+deb10u1", + "versionInfo": "1.17-3+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-eacef0bc5e99480", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/mariadb-common@1:10.3.27-0+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, GPL-verbatim, public-domain, BSD-3-Clause, LGPL-2.1, BSD-2-Clause, LGPL-2.0, unlimited-free-doc, LGPL-3.0, zlib/libpng, GPL-2.0-with-bison-exception, GPL-2+-with-bison-exception, SWsoft, Artistic, GPL-3.0, MIT/X11", + "licenseDeclared": "GPL-2.0, GPL-verbatim, public-domain, BSD-3-Clause, LGPL-2.1, BSD-2-Clause, LGPL-2.0, unlimited-free-doc, LGPL-3.0, zlib/libpng, GPL-2.0-with-bison-exception, GPL-2+-with-bison-exception, SWsoft, Artistic, GPL-3.0, MIT/X11", + "name": "mariadb-common", + "sourceInfo": "built package from: mariadb-10.3 1:10.3.27-0+deb10u1", + "versionInfo": "1:10.3.27-0+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-eb13abbb67b9d7ab", + "attributionTexts": [ + "LayerDigest: sha256:feab2c490a3cea21cc051ff29c33cc9857418edfa1be9966124b18abe1d5ae16", + "LayerDiffID: sha256:4ef81dc52d996453d718fe990558f82275ee8c0270adbf36966743370692863d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/lsb-base@10.2019051400?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, BSD-3-Clause", + "licenseDeclared": "GPL-2.0, BSD-3-Clause", + "name": "lsb-base", + "sourceInfo": "built package from: lsb 10.2019051400", + "versionInfo": "10.2019051400" + }, + { + "SPDXID": "SPDXRef-Package-ebbf693f5c789ba6", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/mime-types@3.3.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-691430647dbe2404" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "mime-types", + "versionInfo": "3.3.1" + }, + { + "SPDXID": "SPDXRef-Package-ec06d0b79d6be8df", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgdk-pixbuf2.0-bin@2.38.1+dfsg-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "licenseDeclared": "LGPL-2.0, MPL-1.1-or-LGPL-2+, GPL-2.0", + "name": "libgdk-pixbuf2.0-bin", + "sourceInfo": "built package from: gdk-pixbuf 2.38.1+dfsg-1", + "versionInfo": "2.38.1+dfsg-1" + }, + { + "SPDXID": "SPDXRef-Package-ed64b9b23a31d7c", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/gir1.2-freedesktop@1.58.3-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.0, BSD-2-Clause, MIT", + "licenseDeclared": "GPL-2.0, LGPL-2.0, BSD-2-Clause, MIT", + "name": "gir1.2-freedesktop", + "sourceInfo": "built package from: gobject-introspection 1.58.3-2", + "versionInfo": "1.58.3-2" + }, + { + "SPDXID": "SPDXRef-Package-edc65751f0ce1be6", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpsl5@0.20.2-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Chromium", + "licenseDeclared": "MIT, Chromium", + "name": "libpsl5", + "sourceInfo": "built package from: libpsl 0.20.2-2", + "versionInfo": "0.20.2-2" + }, + { + "SPDXID": "SPDXRef-Package-ef83593bab67b692", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libselinux1-dev@2.8-1+b1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.1, GPL-2.0", + "licenseDeclared": "LGPL-2.1, GPL-2.0", + "name": "libselinux1-dev", + "sourceInfo": "built package from: libselinux 2.8-1", + "versionInfo": "2.8-1+b1" + }, + { + "SPDXID": "SPDXRef-Package-ef9c7949ab90bc0a", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libharfbuzz0b@2.3.1-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "libharfbuzz0b", + "sourceInfo": "built package from: harfbuzz 2.3.1-1", + "versionInfo": "2.3.1-1" + }, + { + "SPDXID": "SPDXRef-Package-efc18c337a67c4b2", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgmp10@2:6.1.2+dfsg-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-2.0, GPL-3.0", + "licenseDeclared": "LGPL-3.0, GPL-2.0, GPL-3.0", + "name": "libgmp10", + "sourceInfo": "built package from: gmp 2:6.1.2+dfsg-4", + "versionInfo": "2:6.1.2+dfsg-4" + }, + { + "SPDXID": "SPDXRef-Package-f112cfb1caf5e598", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/ffi-compiler@1.0.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-c019b46eb3781764" + ], + "licenseConcluded": "Apache-2.0", + "licenseDeclared": "Apache-2.0", + "name": "ffi-compiler", + "versionInfo": "1.0.1" + }, + { + "SPDXID": "SPDXRef-Package-f3256a4b435c757a", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libpangocairo-1.0-0@1.42.4-8~deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0, Example, TCL, Unicode, ICU", + "licenseDeclared": "LGPL-2.0, Example, TCL, Unicode, ICU", + "name": "libpangocairo-1.0-0", + "sourceInfo": "built package from: pango1.0 1.42.4-8~deb10u1", + "versionInfo": "1.42.4-8~deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-f464715509dad179", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libmagickcore-6-headers@8:6.9.10.23+dfsg-2.1+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libmagickcore-6-headers", + "sourceInfo": "built package from: imagemagick 8:6.9.10.23+dfsg-2.1+deb10u1", + "versionInfo": "8:6.9.10.23+dfsg-2.1+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-f476e3538ef448bc", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libwmf-dev@0.2.8.4-14?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-2.0", + "licenseDeclared": "LGPL-2.0", + "name": "libwmf-dev", + "sourceInfo": "built package from: libwmf 0.2.8.4-14", + "versionInfo": "0.2.8.4-14" + }, + { + "SPDXID": "SPDXRef-Package-f47a2cdcc6e52cc1", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/bundler@1.17.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-87d4b29ad2a1dc0a" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "bundler", + "versionInfo": "1.17.3" + }, + { + "SPDXID": "SPDXRef-Package-f4c7601edaebb485", + "attributionTexts": [ + "LayerDigest: sha256:7467d1831b6947c294d92ee957902c3cd448b17c5ac2103ca5e79d15afb317c3", + "LayerDiffID: sha256:909e93c7174510acfb8f423fd685094540810e3288b99932ca2ab94d9fd99e1d" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libssl1.1@1.1.1d-0+deb10u4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "OpenSSL", + "licenseDeclared": "OpenSSL", + "name": "libssl1.1", + "sourceInfo": "built package from: openssl 1.1.1d-0+deb10u4", + "versionInfo": "1.1.1d-0+deb10u4" + }, + { + "SPDXID": "SPDXRef-Package-f5375bd637ab0fcb", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python2-minimal@2.7.16-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Python-2.0", + "licenseDeclared": "MIT, Python-2.0", + "name": "python2-minimal", + "sourceInfo": "built package from: python-defaults 2.7.16-1", + "versionInfo": "2.7.16-1" + }, + { + "SPDXID": "SPDXRef-Package-f7795e59b6247b99", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/findutils@4.6.0+git+20190209-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0, GFDL-1.3", + "licenseDeclared": "GPL-3.0, GFDL-1.3", + "name": "findutils", + "sourceInfo": "built package from: findutils 4.6.0+git+20190209-2", + "versionInfo": "4.6.0+git+20190209-2" + }, + { + "SPDXID": "SPDXRef-Package-f81fc474d75a42f8", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/python-minimal@2.7.16-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "MIT, Python-2.0", + "licenseDeclared": "MIT, Python-2.0", + "name": "python-minimal", + "sourceInfo": "built package from: python-defaults 2.7.16-1", + "versionInfo": "2.7.16-1" + }, + { + "SPDXID": "SPDXRef-Package-f878c07ee575483b", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/fontconfig-config@2.13.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "fontconfig-config", + "sourceInfo": "built package from: fontconfig 2.13.1-2", + "versionInfo": "2.13.1-2" + }, + { + "SPDXID": "SPDXRef-Package-f92a461c7c1070a2", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libstdc++6@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libstdc++6", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-f943381c907b5a6d", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/power_assert@1.1.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-4c55fead3fb1eacd" + ], + "licenseConcluded": "2-clause BSDL, Ruby's", + "licenseDeclared": "2-clause BSDL, Ruby's", + "name": "power_assert", + "versionInfo": "1.1.1" + }, + { + "SPDXID": "SPDXRef-Package-fa98b47f226b027b", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libacl1@2.2.53-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-2.0, LGPL-2.0, LGPL-2.1", + "licenseDeclared": "GPL-2.0, LGPL-2.0, LGPL-2.1", + "name": "libacl1", + "sourceInfo": "built package from: acl 2.2.53-4", + "versionInfo": "2.2.53-4" + }, + { + "SPDXID": "SPDXRef-Package-fac191527f6580f7", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libde265-0@1.0.3-1+b1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-3.0, BSD-4-Clause, public-domain-1, public-domain-2, other-1", + "licenseDeclared": "LGPL-3.0, GPL-3.0, BSD-4-Clause, public-domain-1, public-domain-2, other-1", + "name": "libde265-0", + "sourceInfo": "built package from: libde265 1.0.3-1", + "versionInfo": "1.0.3-1+b1" + }, + { + "SPDXID": "SPDXRef-Package-fcabe5c7c2884adb", + "attributionTexts": [ + "LayerDigest: sha256:d1c02ade23b40c59bbbc90621149b723e4860d630c607cb72d277dac7ee80bfa", + "LayerDiffID: sha256:dd85c9dd7415776b0cbfc3730b664375a58404ce4f1fffa737065ea7c66cf9a9" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/recursive-open-struct@1.1.3", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-9125528db386d007" + ], + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "name": "recursive-open-struct", + "versionInfo": "1.1.3" + }, + { + "SPDXID": "SPDXRef-Package-fdb09b26a91b0da0", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/bash@5.0-4?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "GPL-3.0", + "licenseDeclared": "GPL-3.0", + "name": "bash", + "sourceInfo": "built package from: bash 5.0-4", + "versionInfo": "5.0-4" + }, + { + "SPDXID": "SPDXRef-Package-fe9a72ae16b19d52", + "attributionTexts": [ + "LayerDigest: sha256:b0a1725fc4ba47e94ebb0e5f12084e1115c8f0e223a2d8b4211cc1346182e98d", + "LayerDiffID: sha256:5f8094bba64ac4fa40853577411e3f1585eccd200693969a4ca96ffcb5dbefce" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:gem/stringio@0.0.1", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "hasFiles": [ + "SPDXRef-File-5a1b4d806d2b1fcc" + ], + "licenseConcluded": "BSD-2-Clause", + "licenseDeclared": "BSD-2-Clause", + "name": "stringio", + "versionInfo": "0.0.1" + }, + { + "SPDXID": "SPDXRef-Package-feaa90a768c2c919", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsm6@2:1.2.3-1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libsm6", + "sourceInfo": "built package from: libsm 2:1.2.3-1", + "versionInfo": "2:1.2.3-1" + }, + { + "SPDXID": "SPDXRef-Package-fef90c6da0797b73", + "attributionTexts": [ + "LayerDigest: sha256:f15a0f46f8c38f4ca7daecf160ba9cdb3ddeafda769e2741e179851cfaa14eec", + "LayerDiffID: sha256:da654bc8bc80edf45dcec6dc7b2c71e1c283b1ffe49e81cd6289498ab9b58e5f" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libbsd0@0.9.1-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-3-Clause, BSD-4-clause-Niels-Provos, BSD-4-clause-Christopher-G-Demetriou, BSD-3-clause-Regents, BSD-2-clause-NetBSD, BSD-3-clause-author, BSD-3-clause-John-Birrell, BSD-5-clause-Peter-Wemm, BSD-2-Clause, BSD-2-clause-verbatim, BSD-2-clause-author, ISC, ISC-Original, Expat, public-domain-Colin-Plumb, public-domain, Beerware", + "licenseDeclared": "BSD-3-Clause, BSD-4-clause-Niels-Provos, BSD-4-clause-Christopher-G-Demetriou, BSD-3-clause-Regents, BSD-2-clause-NetBSD, BSD-3-clause-author, BSD-3-clause-John-Birrell, BSD-5-clause-Peter-Wemm, BSD-2-Clause, BSD-2-clause-verbatim, BSD-2-clause-author, ISC, ISC-Original, Expat, public-domain-Colin-Plumb, public-domain, Beerware", + "name": "libbsd0", + "sourceInfo": "built package from: libbsd 0.9.1-2", + "versionInfo": "0.9.1-2" + }, + { + "SPDXID": "SPDXRef-Package-ff4e09e4e61fdd19", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libgomp1@8.3.0-6?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "NONE", + "licenseDeclared": "NONE", + "name": "libgomp1", + "sourceInfo": "built package from: gcc-8 8.3.0-6", + "versionInfo": "8.3.0-6" + }, + { + "SPDXID": "SPDXRef-Package-ff8931fc43e02148", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/liblqr-1-0-dev@0.4.2-2.1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-3.0, GPLv3", + "licenseDeclared": "LGPL-3.0, GPL-3.0, GPLv3", + "name": "liblqr-1-0-dev", + "sourceInfo": "built package from: liblqr 0.4.2-2.1", + "versionInfo": "0.4.2-2.1" + }, + { + "SPDXID": "SPDXRef-Package-ffaa271b2f7d502e", + "attributionTexts": [ + "LayerDigest: sha256:937782447ff61abe49fd83ca9e3bdea338c1ae1d53278b2f31eca18ab4366a1e", + "LayerDiffID: sha256:10bf86ff9f6a0d24fa41491e74b8dcdeb8b23cc654a2a5e36573eac5e40ea25c" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libopenjp2-7@2.3.0-2+deb10u1?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "BSD-2, MIT, BSD-3, public-domain, LIBPNG, Zlib, LIBTIFF, LIBTIFF-PIXAR, LIBTIFF-GLARSON", + "licenseDeclared": "BSD-2, MIT, BSD-3, public-domain, LIBPNG, Zlib, LIBTIFF, LIBTIFF-PIXAR, LIBTIFF-GLARSON", + "name": "libopenjp2-7", + "sourceInfo": "built package from: openjpeg2 2.3.0-2+deb10u1", + "versionInfo": "2.3.0-2+deb10u1" + }, + { + "SPDXID": "SPDXRef-Package-ffe24c3fb037cd5b", + "attributionTexts": [ + "LayerDigest: sha256:0ecb575e629cd60aa802266a3bc6847dcf4073aa2a6d7d43f717dd61e7b90e0b", + "LayerDiffID: sha256:7f03bfe4d6dc12155877f0d2e8b3429090bad1af7b005f75b7b3a874f386fd5a" + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceLocator": "pkg:deb/debian/libsemanage1@2.8-2?distro=debian-10.8", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "licenseConcluded": "LGPL-3.0, GPL-3.0", + "licenseDeclared": "LGPL-3.0, GPL-3.0", + "name": "libsemanage1", + "sourceInfo": "built package from: libsemanage 2.8-2", + "versionInfo": "2.8-2" + } + ], + "relationships": [ + { + "relatedSpdxElement": "SPDXRef-ContainerImage-83c3ff25d55771a4", + "relationshipType": "DESCRIBE", + "spdxElementId": "SPDXRef-DOCUMENT" + }, + { + "relatedSpdxElement": "SPDXRef-OperatingSystem-100fd27dbdf9d366", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-ContainerImage-83c3ff25d55771a4" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7e78769ff0e667c3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2b02572947fa1bd3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-24754988d5349c18", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-945dbaf93cb8f0b9", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b15a650745f0fa83", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1ebcb86363fecedc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ccc25f1a50673fe4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-fdb09b26a91b0da0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4f5e9b0e804a3f85", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-38576ab9de7da6da", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-148eb497a15a2ffc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b6a84917c5df02b0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3be9960d2db0d569", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-627c25bc928058ac", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-acce92ca006784b5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ac6bdaa9638615c5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b84a8f368a0e6b2f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3569701ef5f04409", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-228999fe3e6baae9", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4bde3da66a315edf", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d116eacaeab23b34", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-64d2ce0d3e928c0b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cc5fad0bb22a7aef", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9b66f8d6b74dd6eb", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9cfc244611ed73c5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-890e6dec52b75068", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e785fd67c4cb88e8", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d11d7965f2fbc3ff", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6a4dd1e705dd3727", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a23376ff469f5e4a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1f69f215f63bdafe", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d0eca77a65b78800", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f7795e59b6247b99", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7bffe398276f86e2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f878c07ee575483b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c8f0722d51a9bdcb", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-162cb2f66dfde37f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c24802e7afe41fe4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4bf767eb41271f78", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6fe936d3046b719b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-68048faa1293698", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ed64b9b23a31d7c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b7ddd4543de002be", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-34276835d836db57", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4a441604f9d66233", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5c1cece2afce9ca5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-88f8e3722edac0f0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-779fca035571204d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-64fecd35dd644dac", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-406aca4f6ccf9eb1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5984a5185345374c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5463f6b226cb968e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6669fb6f7c0c53f5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-45c956276d358a19", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-24e923697bb40f2d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7c5adb0b6cce54a7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-225c105bfa9eeef3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7bc2f0fcdc61a57f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4f6646e2c4e39c66", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-18235d7783e0d31", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ca8a68f88586c9ed", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b9088362309e6e97", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4661a45cfb162289", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e9487ea24e04c44b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7afd5ba82e2a133b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-27d6c56cf4bfb064", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-dbd0892e119aef63", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4a89ca5b19224fd1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-dabcf0a6724a1754", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-fa98b47f226b027b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e994d16c2e39e572", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-867f5455852a6358", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-91dfc2a45d789935", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-967f0b7f931cd78", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6d13b2811acadccd", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ca8ffb6e8edcbf0e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4b7a60a1c1c48e13", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c877236f1816b067", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c2c0d5620b0a1c5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-85e173a6683042d4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d5d2b115df9603c5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a5ced497997789b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8895ecba46b314aa", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-fef90c6da0797b73", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8cef463190b14865", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-bcaacee2e6641d7a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7a1255281ea8acde", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-41de54521d58bf39", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-dd3a37a0b644a6e5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e661534c8e83825f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-10e63bb0c8c927e2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6cfb48a13f551b50", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-59a2771fc4d2713c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6e50b8b684cfa18", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-96e41ded3fd17de", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1041640e30a1c2dd", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a9636aea35344da4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-384ef4284ef33e90", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-dd8e5ed3ce4706d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1a2925a178f0527e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-48d5b856c5f92b96", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-abef1fd51676531e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-46b4d169bf518132", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ad2e9725aa42b8b6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-45e4dbf58d3323b0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-22266fb151bc142b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6befefc20b98bc2d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-172c95e997f6e5d5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-fac191527f6580f7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-93d57f56f28ce25b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3f51a54d2d55e9da", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1be2178063709639", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9035f7a0b5e13e86", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c906ef1e5055c9a2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d5e2c04b62cd7627", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b7f0f066b4fcd2e0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-57f8489438ac8c9d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-dc51fe79cf51b4ac", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4596196435475f32", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-62509c24122118ac", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c7e9ee4975d80564", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cf28d319b28b642", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-29eddc615ffe41c7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-912e8bc590e039f2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cfd7da951d866f62", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-358e55c61c398fe0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d73ede469a2f8a88", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2636e82320406adf", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-17962f3241de260", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1db0861ab23e0107", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5bc418d75e49e572", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-68292ceec62681a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2d2d0256ad2cbdb2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a3bd87e038082c9e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d2c0ea0411035bb4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2f5837af2e7da3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cffa2ef169326f23", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3d79700e06408bcf", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a354d01e70b0c064", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-be62a3090310955", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1693791e87e1315b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-83fb28ec7339ae6e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b3a32f20416ef93d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d581e1b7eff2722", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ec06d0b79d6be8df", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c50ebe3c54f0cf0f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2fc549d750251755", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-99e822aaa7150b98", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-44a319b1e54c24a3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-55d8c4ae5d3c4cae", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9c78ca4a6a449098", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2c8af4dfea969dcc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-73289eee74d1193", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e4b7be2e33c921fd", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-efc18c337a67c4b2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d8d03fa7ecea36b7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6a0038456397f563", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c8308a58a7c34f73", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-13ff46745cf4b557", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3fda9e123c5f9c5f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b1a57522e3ab688d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ff4e09e4e61fdd19", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-688dbb58af6442bf", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8f3dd1f970cb1b07", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9e5ea0adad763b85", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3b1440b155e317f1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ef9c7949ab90bc0a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3109662196609d1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-589ce3c1d2c1696b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-673b8c81afb12121", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-299c02dfb1b539db", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b2ce54377238a88d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3bbca33a3b6251e2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5ff73da84ebfecb2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-37f119411bfe17d8", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2434a9197c5f8367", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-269ee7224b9677b6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-847a56d89217bc1a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b441afa6d5a843b5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-17312a987fd5556e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-52d615cd61fd57bd", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-81b6ea3cbc85e111", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-92d76e4c649afdf7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c7e8e99ba2a9901", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9bdc1657b1c8590c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-19e778120eea3982", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e994e84e73315d56", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-227c82cff970ce52", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d98e3de7fea20e11", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c7a34bd2fa6d1852", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-595ae0e1c2592228", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-eaab4ac6ac63059e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d11b4e2c2a9126b1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b71a7c91f0d6c315", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2dd548b2a8f40a73", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-415c84320c75ad74", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8cf76ab78a2e2833", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7b5a8afaf2e761b0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ff8931fc43e02148", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6ae99df519c94a0b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-17934a51fb6d7f29", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8dcb22a88d94043e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8b7b7117a127d62f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4fe2f7dfe3c43d94", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4900f2c0300300f1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-582b1c091f92ae2c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1aeecf842515f440", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6d850cdec149860b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-aa78538a959604fd", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f464715509dad179", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7c1031d7f2486bbe", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7ac16f90845b2afe", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-97215eb83b3cbaa7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7689fa8f8a4576ad", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-83c9f297ece7c123", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-71bff02914a5f016", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-86777ccc116c497b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3db757dbaf1c2abb", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d05a5c43f40cbb03", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3b5dab1fae25d393", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c6f76c636b94c126", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-52f0b92f98f15bd7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e28735c39d179d58", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e386ffc295843912", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8bd675e4321e4daa", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-72169715e76cda1f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a3e26448c88207b7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-58de9d284eb995b6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a09cfc974be4520f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8134081a9a6b6bc5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d4367d0e7c963cc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5014364785154bdc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e0bb192b5cfce4ae", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-800514f30841d332", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-317595b7018ed00b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-bcf538c2d6e98680", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-711773da6ff4a7df", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9690b726bbf4d63a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1ca3bdaa6155edce", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b7626a89fcabe50d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c5ee7ca37a15ac4c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3208fd593da616c7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ffaa271b2f7d502e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-63a0e7c4d186846a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-92e3299b7eda13b5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8d0b539acad89ece", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4b5c9fab2976d0ec", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c0cf710bb3c247f7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a9d0ff7e5cf0fb5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e4542206c50b3548", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-372c6637d38419b1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f3256a4b435c757a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2ca7f3e05ca6060e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4a42dfcce7824cb1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b9a600283f261ef3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c2833b7cf21f8a6d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7109ffacfaa3d408", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1834d15b09e44fa", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2193304ec9a9d18", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c74b67bf40b1041f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4e65fe8bbaefbf2b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2c42c12063bb5281", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-568a6ef95bf0614b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3fbb5185b1c03ff", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cc6da607837820c0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-afcd5752c2589b0c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-530bca05e69142b5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-edc65751f0ce1be6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-91a2296eb5544b5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-673be4195e04fe47", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e79b8e4b2da82181", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-783ef76702d3a91a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2643d3e918f849f9", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-bd846d8e9309939", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-912ae0f8767007b9", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-49c5afd7d797f425", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5d3913304b80ff4f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cd375b784f7e7baf", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7d72d2d4c0326608", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-80b18b95c9cc9549", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9a48679a5e094d0b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-431f2bacfb0a4938", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-391c197316c333de", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-57965a002dd87072", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d4e57f8a33a71413", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b50f5cfb82c11e50", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-687d6abcaae9684c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ef83593bab67b692", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-920a389b76c5089d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ffe24c3fb037cd5b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8c3a003d517e7ab4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-bba3f83f4e482d35", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d0ab4f8021103415", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8ce9c711ee67d098", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-beded330499d4975", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-feaa90a768c2c919", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c8aa6f474dbc1c7c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cd3f1284d4c7c499", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b04560240cc4bd09", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e94c2ac4e9c541bc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-17e1ab7227afecf0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5533665b3a58df77", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f4c7601edaebb485", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9c423383920eb8a2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f92a461c7c1070a2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9f78d05ddd4d3326", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e2c8d19b750f2cd6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-847e65910700dc06", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-49a6aec0aebda6f6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9a5b05cc4ed185b1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1d4e48b231b2b77b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3f8ce1578674efa0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-94b777a179dd0645", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-903c6c865524f5e4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-12758e3d4619f1c5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c5bdf6a54856f82c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5c635d900a757402", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-19f3815bfdada995", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-65c5022c78559cb", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5c68bfd82d25827a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b834a37045ba0def", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7e86d037fca632cd", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-34d2406cfd2f58c4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b4fdc212b229cc18", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6d38077a12f4929c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7199d7c2949f084", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2e91bbddfad6b58d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ad83dd757466ff5e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f476e3538ef448bc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b2ab9e915f40cb41", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-28caeafbc9bedc0e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-59284826e7b2e072", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-60377124514ccadc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-57b0a0a98c8a9644", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a051717309f7e78c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2bd453b2ca787979", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b9860d5ef0605203", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b61d94acf74f6a72", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e0076c75a60428f7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6c810e9c546688c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4e7b602d3480d09f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-208da78d723c749b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3172548c62505d9f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-bd4cd99cd3e6b6f5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-22f4ed53809a2f10", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8afe1ddd4b684c15", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-83e4fdb7a809fc28", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-45c132bd4b2a8c02", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-386156f56c9f6603", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4c22807b16bae796", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-876135a4b6d69872", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c33e5e6f8936564a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b905a90114b6f01d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d46b309f3fbeda8e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9969002e1d481fa6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c527492651764198", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a8c73aa220b1255d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-73f782866971903d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a6d69f871ff62504", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2f6fd546ebd18212", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-eb13abbb67b9d7ab", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-43d300b0860b07d1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-bb19cb657d3c734a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-eacef0bc5e99480", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-66ebae5dd34f6179", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c75410ed0ae2f05c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-65e9ad0fcf459d79", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b0139c7641a7abec", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-e813b6025d3907d5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c9b858593baf6aad", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8ca81cac67268daf", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-871a6d9263da4386", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3945a82969f25e5a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4777f6bbd82ca021", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-24f81198c2b5819f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7fd0ba5c2395e0c6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-26bfbd3aee7d4436", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d988e1bebac5198", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6fed6422a026cbfe", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-89fc40165ef70eb7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c40f0eb76e6fec5f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8c0e2fedddb99fa9", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b199b8f68e8baeff", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b5485ab521b6927f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1f971eaee71aede5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-38e11ea2c97166cc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-46d7909bafee03ba", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f81fc474d75a42f8", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-667512fabb87ffb3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f5375bd637ab0fcb", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-53e2b609ba1851d8", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5b64189fa687815d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6158b572aa34562b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-86340f89de09fdbf", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d18cfe939ac6007c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4cf9ca786c78f05", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ea372d41f1b69ef1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7ee95ee507d0214d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-98b8a60a69ddf188", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-47b3c8952f8fbe50", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c34d95b9e9e39264", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-780fadfb1b09bc82", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1ccf84255921351", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6402dbff959e8f7b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-65a48c6f37dff200", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3b87db0230f29940", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-bdb59f452bdda108", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-25c36dfe89ca6c23", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-92614622b3877d18", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-885c6578f3659652", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8c2a4d03f0fba45b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-76e5b6b4252879af", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b741269dafd58839", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-18fca66e267667e7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-54872f0d7deb47b4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-afb15084adb3d3a2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9208825c13acd5fb", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cad1b7cc581de740", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-df1b32b55923282c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Package-db06150794f17419", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-OperatingSystem-100fd27dbdf9d366" + }, + { + "relatedSpdxElement": "SPDXRef-Application-441a648f2aeeee72", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-ContainerImage-83c3ff25d55771a4" + }, + { + "relatedSpdxElement": "SPDXRef-Package-14c00ba4fb0e9bfc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ac72ac877c267087", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5691322012558da4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8302d5afe26e7835", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-627c9d106d1158f0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6d21c58de759f6d4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f943381c907b5a6d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-295d9e0f6f56fbea", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8d1b83ccbbe7a657", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-432e6cf76a5b1e06", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-40623deba1787bd5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-fe9a72ae16b19d52", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-45973de89e996b8f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-bba2fe62be430500", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a2fbfde3e64326e5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b06b08ea283bd8ee", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c4bcd19d4afdad56", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-633ae10dc26b62a1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-24af159b03559a3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-88746d9375f00e42", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-d4c45c4900bfddf5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-458dc29980f0cd6a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a4c330759de73d1d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-229b952a289327b5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-950a7ef4104bca2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cd8b3e45aecc37a7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-14eaab2ee5584e96", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8de7744eb4197c06", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4a666d098f9545e8", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f47a2cdcc6e52cc1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5dd1501a764ebc54", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2a2de8c857e587b9", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1e1f1adc637448d5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-52bd63f8bb34743d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-271ec194be50b757", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-19bcf5c8e50620f6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-3022be156cb02ac4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-cf86c165b16efe04", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c707eba2972b49f1", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b65feb9a9f6952b8", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-377cc25c88863ee3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-99e4e2467544af04", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-32955d277606b073", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-69e48d70b7e1e94f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-69da9fc663bcefba", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-1fd9ecaa617a5dd5", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7e04b37489c1b79b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-c629ede1cd041098", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-788d1374b1636be", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-49cd823649057f01", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-534e055ca8f3334b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-638c11a166449db0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-91f9d7edc93b59bc", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-353e6ee8620e9075", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4c1a988ee6380a8", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-a5ed2713bf9443c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-be3701b8d3fe0562", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-fcabe5c7c2884adb", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b494d06e2c30badd", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-24d87789c23a726c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-92f1545e6d17521d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-bb8456910f77a8b7", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9b41bfb9f8fa54f3", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-daac27c308c5a641", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-541916b041085230", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4d216ff3e9c71e55", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ba1f42e7270fe8ab", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-478bbd4d2f49b46f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2517194abf9399", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4203ea25358d0404", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-654dd3f52839d49d", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-955ece6da65e436f", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-691461b77e42d682", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-544fd0e95e335076", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4d48ef296bb8a76b", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-31ee771f366d97fe", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-5076ed8fc78ad1e0", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7166008ef0d0d794", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2e84f7b97323f4d2", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-4ecfe347a135da68", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-78af4f0dccaa863a", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-7b46d06f33a442d4", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-ebbf693f5c789ba6", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-32a6667282b09531", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-f112cfb1caf5e598", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-6d699acd4ca2572c", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-b7a1c9c40e735f98", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-8371a237cc235653", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-9045e43fba3e46c9", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-2a87686fbf441463", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + }, + { + "relatedSpdxElement": "SPDXRef-Package-33e24e945847461e", + "relationshipType": "CONTAINS", + "spdxElementId": "SPDXRef-Application-441a648f2aeeee72" + } + ], + "spdxVersion": "SPDX-2.2" +} \ No newline at end of file diff --git a/tests/spdx/examples/__init__.py b/tests/spdx/examples/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/examples/test_examples.py b/tests/spdx/examples/test_examples.py new file mode 100644 index 000000000..95de85576 --- /dev/null +++ b/tests/spdx/examples/test_examples.py @@ -0,0 +1,56 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os.path +import runpy + +import pytest + + +@pytest.fixture +def cleanup_output_files(): + yield + + files_to_delete = ["spdx2_to_3.jsonld", "my_spdx_document.spdx.json", "converted_format.xml", "graph.png"] + for file in files_to_delete: + if os.path.exists(file): + os.remove(file) + + +def run_example(example_file: str): + file_path = os.path.join(os.path.dirname(__file__), "../../../examples/", example_file) + runpy.run_path(file_path) + + +def test_spdx2_parse_file(): + run_example("spdx2_parse_file.py") + + +@pytest.mark.usefixtures("cleanup_output_files") +def test_spdx2_convert_to_spdx3(): + run_example("spdx2_convert_to_spdx3.py") + assert os.path.exists("spdx2_to_3.jsonld") + + +@pytest.mark.usefixtures("cleanup_output_files") +def test_spdx2_document_from_scratch(): + run_example("spdx2_document_from_scratch.py") + assert os.path.exists("my_spdx_document.spdx.json") + + +@pytest.mark.usefixtures("cleanup_output_files") +def test_spdx2_convert_format(): + run_example("spdx2_convert_format.py") + assert os.path.exists("converted_format.xml") + + +@pytest.mark.usefixtures("cleanup_output_files") +def test_spdx2_generate_graph(): + try: + import networkx # noqa F401 + import pygraphviz # noqa F401 + except ImportError: + pytest.skip("Missing optional dependencies") + + run_example("spdx2_generate_graph.py") + assert os.path.exists("graph.png") diff --git a/tests/spdx/examples/test_spdx2_document_from_scratch.py b/tests/spdx/examples/test_spdx2_document_from_scratch.py new file mode 100644 index 000000000..7c3228d91 --- /dev/null +++ b/tests/spdx/examples/test_spdx2_document_from_scratch.py @@ -0,0 +1,148 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import logging +from datetime import datetime +from typing import List + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, + CreationInfo, + Document, + ExternalPackageRef, + ExternalPackageRefCategory, + File, + FileType, + Package, + PackagePurpose, + PackageVerificationCode, + Relationship, + RelationshipType, +) +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage + +# This example shows how to use the spdx-tools to create an SPDX document from scratch, +# validate it and write it to a file. + + +def test_spdx2_document_from_scratch(): + # First up, we need general information about the creation of the document, summarised by the CreationInfo class. + creation_info = CreationInfo( + spdx_version="SPDX-2.3", + spdx_id="SPDXRef-DOCUMENT", + name="document name", + data_license="CC0-1.0", + document_namespace="https://some.namespace", + creators=[Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com")], + created=datetime(2022, 1, 1), + ) + + # creation_info is the only required property of the Document class (have a look there!), + # the rest are optional lists. + # So, we are set up to create a new document instance. + document = Document(creation_info) + + # The document currently does not describe anything. Let's create a package that we can add to it. + # The Package class has quite a few properties (have a look there!), + # but only name, spdx_id and download_location are mandatory in SPDX v2.3. + package = Package( + name="package name", + spdx_id="SPDXRef-Package", + download_location="https://download.com", + version="2.2.1", + file_name="./foo.bar", + supplier=Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com"), + originator=Actor(ActorType.ORGANIZATION, "some organization", "contact@example.com"), + files_analyzed=True, + verification_code=PackageVerificationCode( + value="d6a770ba38583ed4bb4525bd96e50461655d2758", excluded_files=["./some.file"] + ), + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + license_concluded=spdx_licensing.parse("GPL-2.0-only OR MIT"), + license_info_from_files=[spdx_licensing.parse("GPL-2.0-only"), spdx_licensing.parse("MIT")], + license_declared=spdx_licensing.parse("GPL-2.0-only AND MIT"), + license_comment="license comment", + copyright_text="Copyright 2022 Jane Doe", + description="package description", + attribution_texts=["package attribution"], + primary_package_purpose=PackagePurpose.LIBRARY, + release_date=datetime(2015, 1, 1), + external_references=[ + ExternalPackageRef( + category=ExternalPackageRefCategory.OTHER, + reference_type="http://reference.type", + locator="reference/locator", + comment="external reference comment", + ) + ], + ) + + # Now that we have a package defined, we can add it to the document's package property. + document.packages = [package] + + # A DESCRIBES relationship asserts that the document indeed describes the package. + describes_relationship = Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package") + document.relationships = [describes_relationship] + + # Let's add two files. Have a look at the file class for all possible properties a file can have. + file1 = File( + name="./package/file1.py", + spdx_id="SPDXRef-File1", + file_types=[FileType.SOURCE], + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + license_concluded=spdx_licensing.parse("MIT"), + license_info_in_file=[spdx_licensing.parse("MIT")], + copyright_text="Copyright 2022 Jane Doe", + ) + file2 = File( + name="./package/file2.py", + spdx_id="SPDXRef-File2", + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"), + ], + license_concluded=spdx_licensing.parse("GPL-2.0-only"), + ) + + # Assuming the package contains those two files, we create two CONTAINS relationships. + contains_relationship1 = Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File1") + contains_relationship2 = Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File2") + + # This library uses run-time type checks when assigning properties. + # Because in-place alterations like .append() circumvent these checks, we don't use them here. + document.relationships += [contains_relationship1, contains_relationship2] + document.files += [file1, file2] + + # We now have created a document with basic creation information, describing a package that contains two files. + # You can also add Annotations, Snippets and ExtractedLicensingInfo + # to the document in an analogous manner to the above. + # Have a look at their respective classes if you are unsure about their properties. + assert len(document.packages) == 1 + assert len(document.files) == 2 + assert len(document.relationships) == 3 + assert len(document.snippets) == 0 + assert len(document.annotations) == 0 + assert len(document.extracted_licensing_info) == 0 + + # This library provides comprehensive validation against the SPDX specification. + # Note that details of the validation depend on the SPDX version of the document. + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + + # You can have a look at each entry's message and context (like spdx_id, parent_id, full_element) + # which will help you pinpoint the location of the invalidity. + for message in validation_messages: + logging.warning(message.validation_message) + logging.warning(message.context) + + # If the document is valid, validation_messages will be empty. + assert validation_messages == [] diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py new file mode 100644 index 000000000..eebfb0f76 --- /dev/null +++ b/tests/spdx/fixtures.py @@ -0,0 +1,312 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Checksum, + ChecksumAlgorithm, + CreationInfo, + Document, + ExternalDocumentRef, + ExternalPackageRef, + ExternalPackageRefCategory, + ExtractedLicensingInfo, + File, + FileType, + Package, + PackagePurpose, + PackageVerificationCode, + Relationship, + RelationshipType, + Snippet, + SpdxNoAssertion, + SpdxNone, + Version, +) + +# Utility methods to create data model instances. All properties have valid defaults, so they don't need to be +# specified unless relevant for the test. + + +def actor_fixture(actor_type=ActorType.PERSON, name="actorName", email="some@mail.com") -> Actor: + return Actor(actor_type, name, email) + + +def checksum_fixture(algorithm=ChecksumAlgorithm.SHA1, value="71c4025dd9897b364f3ebbb42c484ff43d00791c") -> Checksum: + return Checksum(algorithm, value) + + +def package_verification_code_fixture( + value="85ed0817af83a24ad8da68c2b5094de69833983c", excluded_files=None +) -> PackageVerificationCode: + excluded_files = ["./exclude.py"] if excluded_files is None else excluded_files + return PackageVerificationCode(value, excluded_files) + + +def creation_info_fixture( + spdx_version="SPDX-2.3", + spdx_id=DOCUMENT_SPDX_ID, + name="documentName", + document_namespace="https://some.namespace", + creators=None, + created=datetime(2022, 12, 1), + creator_comment="creatorComment", + data_license="CC0-1.0", + external_document_refs=None, + license_list_version=Version(3, 19), + document_comment="documentComment", +) -> CreationInfo: + creators = [actor_fixture(name="creatorName")] if creators is None else creators + external_document_refs = ( + [external_document_ref_fixture()] if external_document_refs is None else external_document_refs + ) + return CreationInfo( + spdx_version, + spdx_id, + name, + document_namespace, + creators, + created, + creator_comment, + data_license, + external_document_refs, + license_list_version, + document_comment, + ) + + +def file_fixture( + name="./fileName.py", + spdx_id="SPDXRef-File", + checksums=None, + file_types=None, + license_concluded=spdx_licensing.parse("MIT and GPL-2.0"), + license_info_in_file=None, + license_comment="licenseComment", + copyright_text="copyrightText", + comment="fileComment", + notice="fileNotice", + contributors=None, + attribution_texts=None, +) -> File: + checksums = [checksum_fixture()] if checksums is None else checksums + file_types = [FileType.TEXT] if file_types is None else file_types + license_info_in_file = ( + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()] + if license_info_in_file is None + else license_info_in_file + ) + contributors = ["fileContributor"] if contributors is None else contributors + attribution_texts = ["fileAttributionText"] if attribution_texts is None else attribution_texts + return File( + name=name, + spdx_id=spdx_id, + checksums=checksums, + file_types=file_types, + license_concluded=license_concluded, + license_info_in_file=license_info_in_file, + license_comment=license_comment, + copyright_text=copyright_text, + comment=comment, + notice=notice, + contributors=contributors, + attribution_texts=attribution_texts, + ) + + +def package_fixture( + spdx_id="SPDXRef-Package", + name="packageName", + download_location="https://download.com", + version="12.2", + file_name="./packageFileName", + supplier=actor_fixture(name="supplierName"), + originator=actor_fixture(name="originatorName"), + files_analyzed=True, + verification_code=package_verification_code_fixture(), + checksums=None, + homepage="https://homepage.com", + source_info="sourceInfo", + license_concluded=spdx_licensing.parse("MIT and GPL-2.0"), + license_info_from_files=None, + license_declared=spdx_licensing.parse("MIT and GPL-2.0"), + license_comment="packageLicenseComment", + copyright_text="packageCopyrightText", + summary="packageSummary", + description="packageDescription", + comment="packageComment", + external_references=None, + attribution_texts=None, + primary_package_purpose=PackagePurpose.SOURCE, + release_date=datetime(2022, 11, 1), + built_date=datetime(2022, 11, 2), + valid_until_date=datetime(2022, 11, 3), +) -> Package: + checksums = [checksum_fixture()] if checksums is None else checksums + license_info_from_files = ( + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()] + if license_info_from_files is None + else license_info_from_files + ) + external_references = [external_package_ref_fixture()] if external_references is None else external_references + attribution_texts = ["packageAttributionText"] if attribution_texts is None else attribution_texts + return Package( + spdx_id=spdx_id, + name=name, + download_location=download_location, + version=version, + file_name=file_name, + supplier=supplier, + originator=originator, + files_analyzed=files_analyzed, + verification_code=verification_code, + checksums=checksums, + homepage=homepage, + source_info=source_info, + license_concluded=license_concluded, + license_info_from_files=license_info_from_files, + license_declared=license_declared, + license_comment=license_comment, + copyright_text=copyright_text, + summary=summary, + description=description, + comment=comment, + external_references=external_references, + attribution_texts=attribution_texts, + primary_package_purpose=primary_package_purpose, + release_date=release_date, + built_date=built_date, + valid_until_date=valid_until_date, + ) + + +def external_document_ref_fixture( + document_ref_id="DocumentRef-external", document_uri="https://namespace.com", checksum=checksum_fixture() +) -> ExternalDocumentRef: + return ExternalDocumentRef(document_ref_id=document_ref_id, document_uri=document_uri, checksum=checksum) + + +def external_package_ref_fixture( + category=ExternalPackageRefCategory.PACKAGE_MANAGER, + reference_type="maven-central", + locator="org.apache.tomcat:tomcat:9.0.0.M4", + comment="externalPackageRefComment", +) -> ExternalPackageRef: + return ExternalPackageRef(category=category, reference_type=reference_type, locator=locator, comment=comment) + + +def snippet_fixture( + spdx_id="SPDXRef-Snippet", + file_spdx_id="SPDXRef-File", + byte_range=(1, 2), + line_range=(3, 4), + license_concluded=spdx_licensing.parse("MIT and GPL-2.0"), + license_info_in_snippet=None, + license_comment="snippetLicenseComment", + copyright_text="licenseCopyrightText", + comment="snippetComment", + name="snippetName", + attribution_texts=None, +) -> Snippet: + license_info_in_snippet = ( + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNone()] + if license_info_in_snippet is None + else license_info_in_snippet + ) + attribution_texts = ["snippetAttributionText"] if attribution_texts is None else attribution_texts + return Snippet( + spdx_id=spdx_id, + file_spdx_id=file_spdx_id, + byte_range=byte_range, + line_range=line_range, + license_concluded=license_concluded, + license_info_in_snippet=license_info_in_snippet, + license_comment=license_comment, + copyright_text=copyright_text, + comment=comment, + name=name, + attribution_texts=attribution_texts, + ) + + +def annotation_fixture( + spdx_id="SPDXRef-File", + annotation_type=AnnotationType.REVIEW, + annotator=actor_fixture(name="annotatorName"), + annotation_date=datetime(2022, 12, 24), + annotation_comment="annotationComment", +) -> Annotation: + return Annotation( + spdx_id=spdx_id, + annotation_type=annotation_type, + annotator=annotator, + annotation_date=annotation_date, + annotation_comment=annotation_comment, + ) + + +def extracted_licensing_info_fixture( + license_id="LicenseRef-1", + extracted_text="extractedText", + license_name="licenseName", + cross_references=None, + comment="licenseComment", +) -> ExtractedLicensingInfo: + cross_references = ["https://see.also"] if cross_references is None else cross_references + return ExtractedLicensingInfo( + license_id=license_id, + extracted_text=extracted_text, + license_name=license_name, + cross_references=cross_references, + comment=comment, + ) + + +def relationship_fixture( + spdx_element_id=DOCUMENT_SPDX_ID, + relationship_type=RelationshipType.DESCRIBES, + related_spdx_element_id="SPDXRef-File", + comment="relationshipComment", +) -> Relationship: + return Relationship( + spdx_element_id=spdx_element_id, + relationship_type=relationship_type, + related_spdx_element_id=related_spdx_element_id, + comment=comment, + ) + + +def document_fixture( + creation_info=None, + packages=None, + files=None, + snippets=None, + annotations=None, + relationships=None, + extracted_licensing_info=None, +) -> Document: + creation_info = creation_info_fixture() if creation_info is None else creation_info + packages = [package_fixture()] if packages is None else packages + files = [file_fixture()] if files is None else files + snippets = [snippet_fixture()] if snippets is None else snippets + annotations = [annotation_fixture()] if annotations is None else annotations + relationships = [relationship_fixture()] if relationships is None else relationships + extracted_licensing_info = ( + [extracted_licensing_info_fixture()] if extracted_licensing_info is None else extracted_licensing_info + ) + return Document( + creation_info=creation_info, + packages=packages, + files=files, + snippets=snippets, + annotations=annotations, + relationships=relationships, + extracted_licensing_info=extracted_licensing_info, + ) diff --git a/tests/spdx/jsonschema/__init__.py b/tests/spdx/jsonschema/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/jsonschema/test_annotation_converter.py b/tests/spdx/jsonschema/test_annotation_converter.py new file mode 100644 index 000000000..fdc2e6ce2 --- /dev/null +++ b/tests/spdx/jsonschema/test_annotation_converter.py @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +import pytest + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.annotation_properties import AnnotationProperty +from spdx_tools.spdx.model import Actor, ActorType, Annotation, AnnotationType + + +@pytest.fixture +def converter() -> AnnotationConverter: + return AnnotationConverter() + + +@pytest.mark.parametrize( + "annotation_property,expected", + [ + (AnnotationProperty.ANNOTATION_DATE, "annotationDate"), + (AnnotationProperty.ANNOTATION_TYPE, "annotationType"), + (AnnotationProperty.ANNOTATOR, "annotator"), + (AnnotationProperty.COMMENT, "comment"), + ], +) +def test_json_property_names(converter: AnnotationConverter, annotation_property: AnnotationProperty, expected: str): + assert converter.json_property_name(annotation_property) == expected + + +def test_json_type(converter: AnnotationConverter): + assert converter.get_json_type() == AnnotationProperty + + +def test_data_model_type(converter: AnnotationConverter): + assert converter.get_data_model_type() == Annotation + + +def test_successful_conversion(converter: AnnotationConverter): + date = datetime(2022, 12, 1) + annotator = Actor(ActorType.PERSON, "actorName") + annotation = Annotation("spdxId", AnnotationType.REVIEW, annotator, date, "comment") + + converted_dict = converter.convert(annotation) + + assert converted_dict == { + converter.json_property_name(AnnotationProperty.ANNOTATION_DATE): datetime_to_iso_string(date), + converter.json_property_name(AnnotationProperty.ANNOTATION_TYPE): "REVIEW", + converter.json_property_name(AnnotationProperty.ANNOTATOR): annotator.to_serialized_string(), + converter.json_property_name(AnnotationProperty.COMMENT): "comment", + } diff --git a/tests/spdx/jsonschema/test_checksum_converter.py b/tests/spdx/jsonschema/test_checksum_converter.py new file mode 100644 index 000000000..892c35f85 --- /dev/null +++ b/tests/spdx/jsonschema/test_checksum_converter.py @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter +from spdx_tools.spdx.jsonschema.checksum_properties import ChecksumProperty +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm + + +@pytest.fixture +def converter() -> ChecksumConverter: + return ChecksumConverter() + + +@pytest.mark.parametrize( + "checksum_property,expected", + [(ChecksumProperty.ALGORITHM, "algorithm"), (ChecksumProperty.CHECKSUM_VALUE, "checksumValue")], +) +def test_json_property_names(converter: ChecksumConverter, checksum_property: ChecksumProperty, expected: str): + assert converter.json_property_name(checksum_property) == expected + + +def test_successful_conversion(converter: ChecksumConverter): + checksum = Checksum(ChecksumAlgorithm.SHA1, "123") + + converted_dict = converter.convert(checksum) + + assert converted_dict == { + converter.json_property_name(ChecksumProperty.ALGORITHM): "SHA1", + converter.json_property_name(ChecksumProperty.CHECKSUM_VALUE): "123", + } + + +def test_json_type(converter: ChecksumConverter): + assert converter.get_json_type() == ChecksumProperty + + +def test_data_model_type(converter: ChecksumConverter): + assert converter.get_data_model_type() == Checksum diff --git a/tests/spdx/jsonschema/test_converter.py b/tests/spdx/jsonschema/test_converter.py new file mode 100644 index 000000000..46558d904 --- /dev/null +++ b/tests/spdx/jsonschema/test_converter.py @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import auto +from typing import Any, Type + +import pytest + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, Document + + +class TestPropertyType(JsonProperty): + FIRST_NAME = auto() + SECOND_NAME = auto() + + +@dataclass_with_properties +class TestDataModelType: + first_property: str + second_property: int + third_property: int + + def __init__(self, first_property: str, second_property: int, third_property: int): + check_types_and_set_values(self, locals()) + + +class TestConverter(TypedConverter): + def json_property_name(self, test_property: TestPropertyType) -> str: + if test_property == TestPropertyType.FIRST_NAME: + return "jsonFirstName" + else: + return "jsonSecondName" + + def _get_property_value( + self, instance: TestDataModelType, test_property: TestPropertyType, _document: Document = None + ) -> Any: + if test_property == TestPropertyType.FIRST_NAME: + return instance.first_property + elif test_property == TestPropertyType.SECOND_NAME: + return instance.second_property + instance.third_property + + def get_json_type(self) -> Type[JsonProperty]: + return TestPropertyType + + def get_data_model_type(self) -> Type: + return TestDataModelType + + +def test_conversion(): + converter = TestConverter() + test_instance = TestDataModelType("firstPropertyValue", 1, 2) + + converted_dict = converter.convert(test_instance) + + assert converted_dict == {"jsonFirstName": "firstPropertyValue", "jsonSecondName": 3} + + +def test_wrong_type(): + converter = TestConverter() + checksum = Checksum(ChecksumAlgorithm.SHA1, "123") + + with pytest.raises(TypeError) as error: + converter.convert(checksum) + + error_message: str = error.value.args[0] + assert TestConverter.__name__ in error_message + assert TestDataModelType.__name__ in error_message + assert Checksum.__name__ in error_message diff --git a/tests/spdx/jsonschema/test_creation_info_converter.py b/tests/spdx/jsonschema/test_creation_info_converter.py new file mode 100644 index 000000000..e8445f23b --- /dev/null +++ b/tests/spdx/jsonschema/test_creation_info_converter.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +import pytest + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.creation_info_converter import CreationInfoConverter +from spdx_tools.spdx.jsonschema.creation_info_properties import CreationInfoProperty +from spdx_tools.spdx.model import Actor, ActorType, CreationInfo, Version +from tests.spdx.fixtures import creation_info_fixture + + +@pytest.fixture +def converter() -> CreationInfoConverter: + return CreationInfoConverter() + + +@pytest.mark.parametrize( + "creation_info_property,expected", + [ + (CreationInfoProperty.CREATED, "created"), + (CreationInfoProperty.CREATORS, "creators"), + (CreationInfoProperty.LICENSE_LIST_VERSION, "licenseListVersion"), + (CreationInfoProperty.COMMENT, "comment"), + ], +) +def test_json_property_names( + converter: CreationInfoConverter, creation_info_property: CreationInfoProperty, expected: str +): + assert converter.json_property_name(creation_info_property) == expected + + +def test_successful_conversion(converter: CreationInfoConverter): + creators = [Actor(ActorType.PERSON, "personName"), Actor(ActorType.TOOL, "toolName")] + created = datetime(2022, 12, 1) + + converted_dict = converter.convert( + creation_info_fixture( + creators=creators, created=created, creator_comment="comment", license_list_version=Version(1, 2) + ) + ) + + assert converted_dict == { + converter.json_property_name(CreationInfoProperty.CREATED): datetime_to_iso_string(created), + converter.json_property_name(CreationInfoProperty.CREATORS): ["Person: personName", "Tool: toolName"], + converter.json_property_name(CreationInfoProperty.LICENSE_LIST_VERSION): "1.2", + converter.json_property_name(CreationInfoProperty.COMMENT): "comment", + } + + +def test_null_values(converter: CreationInfoConverter): + creation_info = creation_info_fixture(license_list_version=None, creator_comment=None, creators=[]) + + converted_dict = converter.convert(creation_info) + + assert converter.json_property_name(CreationInfoProperty.LICENSE_LIST_VERSION) not in converted_dict + assert converter.json_property_name(CreationInfoProperty.COMMENT) not in converted_dict + assert converter.json_property_name(CreationInfoProperty.CREATORS) not in converted_dict + + +def test_json_type(converter: CreationInfoConverter): + assert converter.get_json_type() == CreationInfoProperty + + +def test_data_model_type(converter: CreationInfoConverter): + assert converter.get_data_model_type() == CreationInfo diff --git a/tests/spdx/jsonschema/test_document_converter.py b/tests/spdx/jsonschema/test_document_converter.py new file mode 100644 index 000000000..e9966b87e --- /dev/null +++ b/tests/spdx/jsonschema/test_document_converter.py @@ -0,0 +1,212 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import Union +from unittest import mock +from unittest.mock import MagicMock, NonCallableMagicMock + +import pytest + +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.jsonschema.document_properties import DocumentProperty +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Document, + ExtractedLicensingInfo, + Relationship, + RelationshipType, +) +from tests.spdx.fixtures import ( + annotation_fixture, + creation_info_fixture, + external_document_ref_fixture, + file_fixture, + package_fixture, + snippet_fixture, +) +from tests.spdx.mock_utils import assert_mock_method_called_with_arguments + + +@pytest.fixture +@mock.patch("spdx_tools.spdx.jsonschema.creation_info_converter.CreationInfoConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.external_document_ref_converter.ExternalDocumentRefConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.package_converter.PackageConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +@mock.patch( + "spdx_tools.spdx.jsonschema.extracted_licensing_info_converter.ExtractedLicensingInfoConverter", autospec=True +) +@mock.patch("spdx_tools.spdx.jsonschema.file_converter.FileConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.snippet_converter.SnippetConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.relationship_converter.RelationshipConverter", autospec=True) +def converter( + relationship_converter_mock: MagicMock, + snippet_converter_mock: MagicMock, + file_converter_mock: MagicMock, + extracted_licensing_info_converter_mock: MagicMock, + annotation_converter_mock: MagicMock, + package_converter_mock: MagicMock, + external_ref_converter_mock: MagicMock, + creation_info_converter_mock: MagicMock, +) -> DocumentConverter: + converter = DocumentConverter() + converter.creation_info_converter = creation_info_converter_mock() + converter.external_document_ref_converter = external_ref_converter_mock() + converter.package_converter = package_converter_mock() + converter.annotation_converter = annotation_converter_mock() + converter.extracted_licensing_info_converter = extracted_licensing_info_converter_mock() + converter.file_converter = file_converter_mock() + converter.snippet_converter = snippet_converter_mock() + converter.relationship_converter = relationship_converter_mock() + return converter + + +@pytest.mark.parametrize( + "document_property,expected", + [ + (DocumentProperty.SPDX_VERSION, "spdxVersion"), + (DocumentProperty.SPDX_ID, "SPDXID"), + (DocumentProperty.NAME, "name"), + (DocumentProperty.DOCUMENT_NAMESPACE, "documentNamespace"), + (DocumentProperty.DATA_LICENSE, "dataLicense"), + (DocumentProperty.EXTERNAL_DOCUMENT_REFS, "externalDocumentRefs"), + (DocumentProperty.COMMENT, "comment"), + (DocumentProperty.CREATION_INFO, "creationInfo"), + (DocumentProperty.PACKAGES, "packages"), + (DocumentProperty.FILES, "files"), + (DocumentProperty.SNIPPETS, "snippets"), + (DocumentProperty.ANNOTATIONS, "annotations"), + (DocumentProperty.RELATIONSHIPS, "relationships"), + (DocumentProperty.HAS_EXTRACTED_LICENSING_INFOS, "hasExtractedLicensingInfos"), + ], +) +def test_json_property_names(converter: DocumentConverter, document_property: DocumentProperty, expected: str): + assert converter.json_property_name(document_property) == expected + + +def test_successful_conversion(converter: DocumentConverter): + creation_info = creation_info_fixture( + spdx_version="spdxVersion", + spdx_id="spdxId", + name="name", + document_namespace="namespace", + document_comment="comment", + data_license="dataLicense", + external_document_refs=[external_document_ref_fixture()], + ) + document = Document( + creation_info, + annotations=[ + Annotation( + "annotationId", + AnnotationType.REVIEW, + Actor(ActorType.PERSON, "reviewerName"), + datetime(2022, 12, 1), + "reviewComment", + ) + ], + extracted_licensing_info=[ExtractedLicensingInfo("licenseId", "licenseText")], + relationships=[ + Relationship(creation_info.spdx_id, RelationshipType.DESCRIBES, "describedElementId"), + Relationship("relationshipOriginId", RelationshipType.AMENDS, "relationShipTargetId"), + ], + packages=[package_fixture()], + files=[file_fixture()], + snippets=[snippet_fixture()], + ) + converter.external_document_ref_converter.convert.return_value = "mock_converted_external_ref" + converter.creation_info_converter.convert.return_value = "mock_converted_creation_info" + converter.package_converter.convert.return_value = "mock_converted_package" + converter.annotation_converter.convert.return_value = "mock_converted_annotation" + converter.extracted_licensing_info_converter.convert.return_value = "mock_converted_extracted_licensing_info" + converter.package_converter.convert.return_value = "mock_converted_package" + converter.file_converter.convert.return_value = "mock_converted_file" + converter.snippet_converter.convert.return_value = "mock_converted_snippet" + converter.relationship_converter.convert.return_value = "mock_converted_relationship" + + converted_dict = converter.convert(document) + + assert converted_dict == { + converter.json_property_name(DocumentProperty.SPDX_ID): "spdxId", + converter.json_property_name(DocumentProperty.ANNOTATIONS): ["mock_converted_annotation"], + converter.json_property_name(DocumentProperty.COMMENT): "comment", + converter.json_property_name(DocumentProperty.CREATION_INFO): "mock_converted_creation_info", + converter.json_property_name(DocumentProperty.DATA_LICENSE): "dataLicense", + converter.json_property_name(DocumentProperty.EXTERNAL_DOCUMENT_REFS): ["mock_converted_external_ref"], + converter.json_property_name(DocumentProperty.HAS_EXTRACTED_LICENSING_INFOS): [ + "mock_converted_extracted_licensing_info" + ], + converter.json_property_name(DocumentProperty.NAME): "name", + converter.json_property_name(DocumentProperty.SPDX_VERSION): "spdxVersion", + converter.json_property_name(DocumentProperty.DOCUMENT_NAMESPACE): "namespace", + converter.json_property_name(DocumentProperty.PACKAGES): ["mock_converted_package"], + converter.json_property_name(DocumentProperty.FILES): ["mock_converted_file"], + converter.json_property_name(DocumentProperty.SNIPPETS): ["mock_converted_snippet"], + converter.json_property_name(DocumentProperty.RELATIONSHIPS): [ + "mock_converted_relationship", + "mock_converted_relationship", + ], + } + + +def test_json_type(converter: DocumentConverter): + assert converter.get_json_type() == DocumentProperty + + +def test_data_model_type(converter: DocumentConverter): + assert converter.get_data_model_type() == Document + + +def test_null_values(converter: DocumentConverter): + document = Document(creation_info_fixture(external_document_refs=[])) + + converted_dict = converter.convert(document) + + assert converter.json_property_name(DocumentProperty.ANNOTATIONS) not in converted_dict + assert converter.json_property_name(DocumentProperty.EXTERNAL_DOCUMENT_REFS) not in converted_dict + assert converter.json_property_name(DocumentProperty.HAS_EXTRACTED_LICENSING_INFOS) not in converted_dict + assert converter.json_property_name(DocumentProperty.PACKAGES) not in converted_dict + assert converter.json_property_name(DocumentProperty.FILES) not in converted_dict + assert converter.json_property_name(DocumentProperty.SNIPPETS) not in converted_dict + assert converter.json_property_name(DocumentProperty.RELATIONSHIPS) not in converted_dict + + +def test_document_annotations(converter: DocumentConverter): + file = file_fixture(spdx_id="fileId") + package = package_fixture(spdx_id="packageId") + snippet = snippet_fixture(spdx_id="snippetId") + document_id = "documentId" + + # There are 5 annotations: one each referencing the document, package, file and snippet, and one with an id + # matching none of the Spdx elements. The writer is expected to add the package, file and snippet annotations to + # those elements, so the document should receive the other two. + document_annotation = annotation_fixture(spdx_id=document_id) + other_annotation = annotation_fixture(spdx_id="otherId") + annotations = [ + annotation_fixture(spdx_id=file.spdx_id), + annotation_fixture(spdx_id=package.spdx_id), + annotation_fixture(spdx_id=snippet.spdx_id), + document_annotation, + other_annotation, + ] + document = Document( + creation_info_fixture(spdx_id=document_id), + files=[file], + packages=[package], + snippets=[snippet], + annotations=annotations, + ) + + # Weird type hint to make warnings about unresolved references from the mock class disappear + annotation_converter: Union[AnnotationConverter, NonCallableMagicMock] = converter.annotation_converter + annotation_converter.convert.return_value = "mock_converted_annotation" + + converted_dict = converter.convert(document) + + assert_mock_method_called_with_arguments(annotation_converter, "convert", document_annotation, other_annotation) + converted_document_annotations = converted_dict.get(converter.json_property_name(DocumentProperty.ANNOTATIONS)) + assert converted_document_annotations == ["mock_converted_annotation", "mock_converted_annotation"] diff --git a/tests/spdx/jsonschema/test_external_document_ref_converter.py b/tests/spdx/jsonschema/test_external_document_ref_converter.py new file mode 100644 index 000000000..fabce5939 --- /dev/null +++ b/tests/spdx/jsonschema/test_external_document_ref_converter.py @@ -0,0 +1,56 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import mock +from unittest.mock import MagicMock + +import pytest + +from spdx_tools.spdx.jsonschema.external_document_ref_converter import ExternalDocumentRefConverter +from spdx_tools.spdx.jsonschema.external_document_ref_properties import ExternalDocumentRefProperty +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, ExternalDocumentRef + + +@pytest.fixture +@mock.patch("spdx_tools.spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) +def converter(checksum_converter_magic_mock: MagicMock) -> ExternalDocumentRefConverter: + mocked_checksum_converter = checksum_converter_magic_mock() + converter = ExternalDocumentRefConverter() + converter.checksum_converter = mocked_checksum_converter + return converter + + +@pytest.mark.parametrize( + "external_document_ref_property,expected", + [ + (ExternalDocumentRefProperty.EXTERNAL_DOCUMENT_ID, "externalDocumentId"), + (ExternalDocumentRefProperty.SPDX_DOCUMENT, "spdxDocument"), + (ExternalDocumentRefProperty.CHECKSUM, "checksum"), + ], +) +def test_json_property_names( + converter: ExternalDocumentRefConverter, external_document_ref_property: ExternalDocumentRefProperty, expected: str +): + assert converter.json_property_name(external_document_ref_property) == expected + + +def test_successful_conversion(converter: ExternalDocumentRefConverter): + converter.checksum_converter.convert.return_value = "mock_converted_checksum" + checksum = Checksum(ChecksumAlgorithm.SHA1, "123") + external_document_ref = ExternalDocumentRef("document_ref_id", "document_uri", checksum) + + converted_dict = converter.convert(external_document_ref) + + assert converted_dict == { + converter.json_property_name(ExternalDocumentRefProperty.EXTERNAL_DOCUMENT_ID): "document_ref_id", + converter.json_property_name(ExternalDocumentRefProperty.SPDX_DOCUMENT): "document_uri", + converter.json_property_name(ExternalDocumentRefProperty.CHECKSUM): "mock_converted_checksum", + } + + +def test_json_type(converter: ExternalDocumentRefConverter): + assert converter.get_json_type() == ExternalDocumentRefProperty + + +def test_data_model_type(converter: ExternalDocumentRefConverter): + assert converter.get_data_model_type() == ExternalDocumentRef diff --git a/tests/spdx/jsonschema/test_external_package_ref_converter.py b/tests/spdx/jsonschema/test_external_package_ref_converter.py new file mode 100644 index 000000000..303eb375d --- /dev/null +++ b/tests/spdx/jsonschema/test_external_package_ref_converter.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.jsonschema.external_package_ref_converter import ExternalPackageRefConverter +from spdx_tools.spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory + + +@pytest.fixture +def converter() -> ExternalPackageRefConverter: + return ExternalPackageRefConverter() + + +@pytest.mark.parametrize( + "external_package_ref_property,expected", + [ + (ExternalPackageRefProperty.COMMENT, "comment"), + (ExternalPackageRefProperty.REFERENCE_CATEGORY, "referenceCategory"), + (ExternalPackageRefProperty.REFERENCE_LOCATOR, "referenceLocator"), + (ExternalPackageRefProperty.REFERENCE_TYPE, "referenceType"), + ], +) +def test_json_property_names( + converter: ExternalPackageRefConverter, external_package_ref_property: ExternalPackageRefProperty, expected: str +): + assert converter.json_property_name(external_package_ref_property) == expected + + +def test_json_type(converter: ExternalPackageRefConverter): + assert converter.get_json_type() == ExternalPackageRefProperty + + +def test_data_model_type(converter: ExternalPackageRefConverter): + assert converter.get_data_model_type() == ExternalPackageRef + + +def test_successful_conversion(converter: ExternalPackageRefConverter): + external_package_ref = ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "type", "locator", "comment") + + converted_dict = converter.convert(external_package_ref) + + assert converted_dict == { + converter.json_property_name(ExternalPackageRefProperty.COMMENT): "comment", + converter.json_property_name(ExternalPackageRefProperty.REFERENCE_CATEGORY): "PACKAGE_MANAGER", + converter.json_property_name(ExternalPackageRefProperty.REFERENCE_LOCATOR): "locator", + converter.json_property_name(ExternalPackageRefProperty.REFERENCE_TYPE): "type", + } diff --git a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py new file mode 100644 index 000000000..ee8488f4a --- /dev/null +++ b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py @@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.jsonschema.extracted_licensing_info_converter import ExtractedLicensingInfoConverter +from spdx_tools.spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty +from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from tests.spdx.fixtures import extracted_licensing_info_fixture + + +@pytest.fixture +def converter() -> ExtractedLicensingInfoConverter: + return ExtractedLicensingInfoConverter() + + +@pytest.mark.parametrize( + "extracted_licensing_info_property,expected", + [ + (ExtractedLicensingInfoProperty.LICENSE_ID, "licenseId"), + (ExtractedLicensingInfoProperty.EXTRACTED_TEXT, "extractedText"), + (ExtractedLicensingInfoProperty.NAME, "name"), + (ExtractedLicensingInfoProperty.COMMENT, "comment"), + (ExtractedLicensingInfoProperty.SEE_ALSOS, "seeAlsos"), + ], +) +def test_json_property_names( + converter: ExtractedLicensingInfoConverter, + extracted_licensing_info_property: ExtractedLicensingInfoProperty, + expected: str, +): + assert converter.json_property_name(extracted_licensing_info_property) == expected + + +def test_json_type(converter: ExtractedLicensingInfoConverter): + assert converter.get_json_type() == ExtractedLicensingInfoProperty + + +def test_data_model_type(converter: ExtractedLicensingInfoConverter): + assert converter.get_data_model_type() == ExtractedLicensingInfo + + +def test_successful_conversion(converter: ExtractedLicensingInfoConverter): + extracted_licensing_info = ExtractedLicensingInfo( + license_id="licenseId", + extracted_text="Extracted text", + license_name="license name", + cross_references=["reference1", "reference2"], + comment="comment", + ) + + converted_dict = converter.convert(extracted_licensing_info) + + assert converted_dict == { + converter.json_property_name(ExtractedLicensingInfoProperty.LICENSE_ID): "licenseId", + converter.json_property_name(ExtractedLicensingInfoProperty.EXTRACTED_TEXT): "Extracted text", + converter.json_property_name(ExtractedLicensingInfoProperty.NAME): "license name", + converter.json_property_name(ExtractedLicensingInfoProperty.SEE_ALSOS): ["reference1", "reference2"], + converter.json_property_name(ExtractedLicensingInfoProperty.COMMENT): "comment", + } + + +def test_null_values(converter: ExtractedLicensingInfoConverter): + extracted_licensing_info = ExtractedLicensingInfo(cross_references=[]) + + converted_dict = converter.convert(extracted_licensing_info) + + assert converter.json_property_name(ExtractedLicensingInfoProperty.LICENSE_ID) not in converted_dict + assert converter.json_property_name(ExtractedLicensingInfoProperty.EXTRACTED_TEXT) not in converted_dict + assert converter.json_property_name(ExtractedLicensingInfoProperty.NAME) not in converted_dict + assert converter.json_property_name(ExtractedLicensingInfoProperty.SEE_ALSOS) not in converted_dict + assert converter.json_property_name(ExtractedLicensingInfoProperty.COMMENT) not in converted_dict + + +def test_spdx_no_assertion(converter: ExtractedLicensingInfoConverter): + extracted_licensing_info = extracted_licensing_info_fixture(license_name=SpdxNoAssertion()) + + converted_dict = converter.convert(extracted_licensing_info) + + assert ( + converted_dict[converter.json_property_name(ExtractedLicensingInfoProperty.NAME)] == SPDX_NO_ASSERTION_STRING + ) diff --git a/tests/spdx/jsonschema/test_file_converter.py b/tests/spdx/jsonschema/test_file_converter.py new file mode 100644 index 000000000..560ecb1a4 --- /dev/null +++ b/tests/spdx/jsonschema/test_file_converter.py @@ -0,0 +1,209 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import Union +from unittest import mock +from unittest.mock import MagicMock, NonCallableMagicMock + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.file_converter import FileConverter +from spdx_tools.spdx.jsonschema.file_properties import FileProperty +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Checksum, + ChecksumAlgorithm, + Document, + File, + FileType, + SpdxNoAssertion, + SpdxNone, +) +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING +from tests.spdx.fixtures import annotation_fixture, creation_info_fixture, document_fixture, file_fixture +from tests.spdx.mock_utils import assert_mock_method_called_with_arguments + + +@pytest.fixture +@mock.patch("spdx_tools.spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +def converter(annotation_converter_mock: MagicMock, checksum_converter_mock: MagicMock) -> FileConverter: + converter = FileConverter() + converter.checksum_converter = checksum_converter_mock() + converter.annotation_converter = annotation_converter_mock() + return converter + + +@pytest.mark.parametrize( + "file_property,expected", + [ + (FileProperty.SPDX_ID, "SPDXID"), + (FileProperty.ANNOTATIONS, "annotations"), + (FileProperty.ARTIFACT_OFS, "artifactOfs"), + (FileProperty.ATTRIBUTION_TEXTS, "attributionTexts"), + (FileProperty.CHECKSUMS, "checksums"), + (FileProperty.COMMENT, "comment"), + (FileProperty.COPYRIGHT_TEXT, "copyrightText"), + (FileProperty.FILE_CONTRIBUTORS, "fileContributors"), + (FileProperty.FILE_DEPENDENCIES, "fileDependencies"), + (FileProperty.FILE_NAME, "fileName"), + (FileProperty.FILE_TYPES, "fileTypes"), + (FileProperty.LICENSE_COMMENTS, "licenseComments"), + (FileProperty.LICENSE_CONCLUDED, "licenseConcluded"), + (FileProperty.LICENSE_INFO_IN_FILES, "licenseInfoInFiles"), + (FileProperty.NOTICE_TEXT, "noticeText"), + ], +) +def test_json_property_names(converter: FileConverter, file_property: FileProperty, expected: str): + assert converter.json_property_name(file_property) == expected + + +def test_json_type(converter: FileConverter): + assert converter.get_json_type() == FileProperty + + +def test_data_model_type(converter: FileConverter): + assert converter.get_data_model_type() == File + + +def test_successful_conversion(converter: FileConverter): + converter.checksum_converter.convert.return_value = "mock_converted_checksum" + converter.annotation_converter.convert.return_value = "mock_converted_annotation" + file = File( + name="name", + spdx_id="spdxId", + checksums=[Checksum(ChecksumAlgorithm.SHA224, "sha224"), Checksum(ChecksumAlgorithm.MD2, "md2")], + file_types=[FileType.SPDX, FileType.OTHER], + license_concluded=spdx_licensing.parse("MIT and GPL-2.0"), + license_info_in_file=[spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()], + license_comment="licenseComment", + copyright_text="copyrightText", + comment="comment", + notice="notice", + contributors=["contributor1", "contributor2"], + attribution_texts=["attributionText1", "attributionText2"], + ) + + annotations = [ + Annotation( + file.spdx_id, + AnnotationType.REVIEW, + Actor(ActorType.PERSON, "annotatorName"), + datetime(2022, 12, 5), + "review comment", + ) + ] + document = Document(creation_info_fixture(), files=[file], annotations=annotations) + + converted_dict = converter.convert(file, document) + + assert converted_dict == { + converter.json_property_name(FileProperty.SPDX_ID): "spdxId", + converter.json_property_name(FileProperty.ANNOTATIONS): ["mock_converted_annotation"], + converter.json_property_name(FileProperty.ATTRIBUTION_TEXTS): ["attributionText1", "attributionText2"], + converter.json_property_name(FileProperty.CHECKSUMS): ["mock_converted_checksum", "mock_converted_checksum"], + converter.json_property_name(FileProperty.COMMENT): "comment", + converter.json_property_name(FileProperty.COPYRIGHT_TEXT): "copyrightText", + converter.json_property_name(FileProperty.FILE_CONTRIBUTORS): ["contributor1", "contributor2"], + converter.json_property_name(FileProperty.FILE_NAME): "name", + converter.json_property_name(FileProperty.FILE_TYPES): ["SPDX", "OTHER"], + converter.json_property_name(FileProperty.LICENSE_COMMENTS): "licenseComment", + converter.json_property_name(FileProperty.LICENSE_CONCLUDED): "MIT AND GPL-2.0-only", + converter.json_property_name(FileProperty.LICENSE_INFO_IN_FILES): ["MIT", "GPL-2.0-only", "NOASSERTION"], + converter.json_property_name(FileProperty.NOTICE_TEXT): "notice", + } + + +def test_null_values(converter: FileConverter): + file = file_fixture( + copyright_text=None, + license_concluded=None, + license_comment=None, + comment=None, + notice=None, + attribution_texts=[], + checksums=[], + contributors=[], + file_types=[], + license_info_in_file=[], + ) + document = Document(creation_info_fixture(), files=[file]) + + converted_dict = converter.convert(file, document) + + assert converter.json_property_name(FileProperty.COPYRIGHT_TEXT) not in converted_dict + assert converter.json_property_name(FileProperty.LICENSE_CONCLUDED) not in converted_dict + assert converter.json_property_name(FileProperty.LICENSE_COMMENTS) not in converted_dict + assert converter.json_property_name(FileProperty.COMMENT) not in converted_dict + assert converter.json_property_name(FileProperty.NOTICE_TEXT) not in converted_dict + assert converter.json_property_name(FileProperty.ANNOTATIONS) not in converted_dict + assert converter.json_property_name(FileProperty.ATTRIBUTION_TEXTS) not in converted_dict + assert converter.json_property_name(FileProperty.CHECKSUMS) not in converted_dict + assert converter.json_property_name(FileProperty.FILE_CONTRIBUTORS) not in converted_dict + assert converter.json_property_name(FileProperty.FILE_TYPES) not in converted_dict + assert converter.json_property_name(FileProperty.LICENSE_INFO_IN_FILES) not in converted_dict + + +def test_spdx_no_assertion(converter: FileConverter): + file = file_fixture( + license_concluded=SpdxNoAssertion(), license_info_in_file=[SpdxNoAssertion()], copyright_text=SpdxNoAssertion() + ) + document = Document(creation_info_fixture(), files=[file]) + + converted_dict = converter.convert(file, document) + + assert converted_dict[converter.json_property_name(FileProperty.COPYRIGHT_TEXT)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(FileProperty.LICENSE_CONCLUDED)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(FileProperty.LICENSE_INFO_IN_FILES)] == [ + SPDX_NO_ASSERTION_STRING + ] + + +def test_spdx_none(converter: FileConverter): + file = file_fixture(license_concluded=SpdxNone(), license_info_in_file=[SpdxNone()], copyright_text=SpdxNone()) + document = Document(creation_info_fixture(), files=[file]) + + converted_dict = converter.convert(file, document) + + assert converted_dict[converter.json_property_name(FileProperty.COPYRIGHT_TEXT)] == SPDX_NONE_STRING + assert converted_dict[converter.json_property_name(FileProperty.LICENSE_CONCLUDED)] == SPDX_NONE_STRING + assert converted_dict[converter.json_property_name(FileProperty.LICENSE_INFO_IN_FILES)] == [SPDX_NONE_STRING] + + +def test_file_annotations(converter: FileConverter): + file = file_fixture(spdx_id="fileId") + document = document_fixture(files=[file]) + first_file_annotation = annotation_fixture(spdx_id=file.spdx_id) + second_file_annotation = annotation_fixture(spdx_id=file.spdx_id) + document_annotation = annotation_fixture(spdx_id=document.creation_info.spdx_id) + package_annotation = annotation_fixture(spdx_id=document.packages[0].spdx_id) + snippet_annotation = annotation_fixture(spdx_id=document.snippets[0].spdx_id) + other_annotation = annotation_fixture(spdx_id="otherId") + annotations = [ + first_file_annotation, + second_file_annotation, + document_annotation, + package_annotation, + snippet_annotation, + other_annotation, + ] + document.annotations = annotations + + # Weird type hint to make warnings about unresolved references from the mock class disappear + annotation_converter: Union[AnnotationConverter, NonCallableMagicMock] = converter.annotation_converter + annotation_converter.convert.return_value = "mock_converted_annotation" + + converted_dict = converter.convert(file, document) + + assert_mock_method_called_with_arguments( + annotation_converter, "convert", first_file_annotation, second_file_annotation + ) + converted_file_annotations = converted_dict.get(converter.json_property_name(FileProperty.ANNOTATIONS)) + assert converted_file_annotations == ["mock_converted_annotation", "mock_converted_annotation"] diff --git a/tests/spdx/jsonschema/test_package_converter.py b/tests/spdx/jsonschema/test_package_converter.py new file mode 100644 index 000000000..c6e63d9f8 --- /dev/null +++ b/tests/spdx/jsonschema/test_package_converter.py @@ -0,0 +1,321 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import Union +from unittest import mock +from unittest.mock import MagicMock, NonCallableMagicMock + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.package_converter import PackageConverter +from spdx_tools.spdx.jsonschema.package_properties import PackageProperty +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Checksum, + ChecksumAlgorithm, + Document, + Package, + PackagePurpose, + PackageVerificationCode, + SpdxNoAssertion, + SpdxNone, +) +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING +from tests.spdx.fixtures import ( + annotation_fixture, + creation_info_fixture, + document_fixture, + external_package_ref_fixture, + package_fixture, +) +from tests.spdx.mock_utils import assert_mock_method_called_with_arguments + + +@pytest.fixture +@mock.patch("spdx_tools.spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +@mock.patch( + "spdx_tools.spdx.jsonschema.package_verification_code_converter.PackageVerificationCodeConverter", autospec=True +) +@mock.patch("spdx_tools.spdx.jsonschema.external_package_ref_converter.ExternalPackageRefConverter", autospec=True) +def converter( + package_ref_converter_mock: MagicMock, + verification_code_converter_mock: MagicMock, + annotation_converter_mock: MagicMock, + checksum_converter_mock: MagicMock, +) -> PackageConverter: + converter = PackageConverter() + converter.checksum_converter = checksum_converter_mock() + converter.annotation_converter = annotation_converter_mock() + converter.package_verification_code_converter = verification_code_converter_mock() + converter.external_package_ref_converter = package_ref_converter_mock() + return converter + + +@pytest.mark.parametrize( + "external_package_ref_property,expected", + [ + (PackageProperty.SPDX_ID, "SPDXID"), + (PackageProperty.ANNOTATIONS, "annotations"), + (PackageProperty.ATTRIBUTION_TEXTS, "attributionTexts"), + (PackageProperty.BUILT_DATE, "builtDate"), + (PackageProperty.CHECKSUMS, "checksums"), + (PackageProperty.COMMENT, "comment"), + (PackageProperty.COPYRIGHT_TEXT, "copyrightText"), + (PackageProperty.DESCRIPTION, "description"), + (PackageProperty.DOWNLOAD_LOCATION, "downloadLocation"), + (PackageProperty.EXTERNAL_REFS, "externalRefs"), + (PackageProperty.FILES_ANALYZED, "filesAnalyzed"), + (PackageProperty.HOMEPAGE, "homepage"), + (PackageProperty.LICENSE_COMMENTS, "licenseComments"), + (PackageProperty.LICENSE_CONCLUDED, "licenseConcluded"), + (PackageProperty.LICENSE_DECLARED, "licenseDeclared"), + (PackageProperty.LICENSE_INFO_FROM_FILES, "licenseInfoFromFiles"), + (PackageProperty.NAME, "name"), + (PackageProperty.ORIGINATOR, "originator"), + (PackageProperty.PACKAGE_FILE_NAME, "packageFileName"), + (PackageProperty.PACKAGE_VERIFICATION_CODE, "packageVerificationCode"), + (PackageProperty.PRIMARY_PACKAGE_PURPOSE, "primaryPackagePurpose"), + (PackageProperty.RELEASE_DATE, "releaseDate"), + (PackageProperty.SOURCE_INFO, "sourceInfo"), + (PackageProperty.SUMMARY, "summary"), + (PackageProperty.SUPPLIER, "supplier"), + (PackageProperty.VALID_UNTIL_DATE, "validUntilDate"), + (PackageProperty.VERSION_INFO, "versionInfo"), + ], +) +def test_json_property_names( + converter: PackageConverter, external_package_ref_property: PackageProperty, expected: str +): + assert converter.json_property_name(external_package_ref_property) == expected + + +def test_json_type(converter: PackageConverter): + assert converter.get_json_type() == PackageProperty + + +def test_data_model_type(converter: PackageConverter): + assert converter.get_data_model_type() == Package + + +def test_successful_conversion(converter: PackageConverter): + converter.checksum_converter.convert.return_value = "mock_converted_checksum" + converter.annotation_converter.convert.return_value = "mock_converted_annotation" + converter.package_verification_code_converter.convert.return_value = "mock_converted_verification_code" + converter.external_package_ref_converter.convert.return_value = "mock_package_ref" + package = Package( + spdx_id="packageId", + name="name", + download_location="downloadLocation", + version="version", + file_name="fileName", + supplier=Actor(ActorType.PERSON, "supplierName"), + originator=Actor(ActorType.PERSON, "originatorName"), + files_analyzed=True, + verification_code=PackageVerificationCode("value"), + checksums=[Checksum(ChecksumAlgorithm.SHA1, "sha1"), Checksum(ChecksumAlgorithm.BLAKE2B_256, "blake")], + homepage="homepage", + source_info="sourceInfo", + license_concluded=spdx_licensing.parse("MIT and GPL-2.0"), + license_info_from_files=[spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0")], + license_declared=spdx_licensing.parse("MIT or GPL-2.0 "), + license_comment="licenseComment", + copyright_text="copyrightText", + summary="summary", + description="description", + comment="comment", + external_references=[external_package_ref_fixture()], + attribution_texts=["attributionText1", "attributionText2"], + primary_package_purpose=PackagePurpose.APPLICATION, + release_date=datetime(2022, 12, 1), + built_date=datetime(2022, 12, 2), + valid_until_date=datetime(2022, 12, 3), + ) + + annotation = Annotation( + package.spdx_id, + AnnotationType.REVIEW, + Actor(ActorType.TOOL, "toolName"), + datetime(2022, 12, 5), + "review comment", + ) + document = Document(creation_info_fixture(), packages=[package], annotations=[annotation]) + + converted_dict = converter.convert(package, document) + + assert converted_dict == { + converter.json_property_name(PackageProperty.SPDX_ID): "packageId", + converter.json_property_name(PackageProperty.ANNOTATIONS): ["mock_converted_annotation"], + converter.json_property_name(PackageProperty.ATTRIBUTION_TEXTS): ["attributionText1", "attributionText2"], + converter.json_property_name(PackageProperty.NAME): "name", + converter.json_property_name(PackageProperty.DOWNLOAD_LOCATION): "downloadLocation", + converter.json_property_name(PackageProperty.VERSION_INFO): "version", + converter.json_property_name(PackageProperty.PACKAGE_FILE_NAME): "fileName", + converter.json_property_name(PackageProperty.SUPPLIER): "Person: supplierName", + converter.json_property_name(PackageProperty.ORIGINATOR): "Person: originatorName", + converter.json_property_name(PackageProperty.FILES_ANALYZED): True, + converter.json_property_name(PackageProperty.PACKAGE_VERIFICATION_CODE): "mock_converted_verification_code", + converter.json_property_name(PackageProperty.CHECKSUMS): [ + "mock_converted_checksum", + "mock_converted_checksum", + ], + converter.json_property_name(PackageProperty.HOMEPAGE): "homepage", + converter.json_property_name(PackageProperty.SOURCE_INFO): "sourceInfo", + converter.json_property_name(PackageProperty.LICENSE_CONCLUDED): "MIT AND GPL-2.0-only", + converter.json_property_name(PackageProperty.LICENSE_INFO_FROM_FILES): ["MIT", "GPL-2.0-only"], + converter.json_property_name(PackageProperty.LICENSE_DECLARED): "MIT OR GPL-2.0-only", + converter.json_property_name(PackageProperty.LICENSE_COMMENTS): "licenseComment", + converter.json_property_name(PackageProperty.COPYRIGHT_TEXT): "copyrightText", + converter.json_property_name(PackageProperty.SUMMARY): "summary", + converter.json_property_name(PackageProperty.DESCRIPTION): "description", + converter.json_property_name(PackageProperty.COMMENT): "comment", + converter.json_property_name(PackageProperty.EXTERNAL_REFS): ["mock_package_ref"], + converter.json_property_name(PackageProperty.PRIMARY_PACKAGE_PURPOSE): "APPLICATION", + converter.json_property_name(PackageProperty.RELEASE_DATE): "2022-12-01T00:00:00Z", + converter.json_property_name(PackageProperty.BUILT_DATE): "2022-12-02T00:00:00Z", + converter.json_property_name(PackageProperty.VALID_UNTIL_DATE): "2022-12-03T00:00:00Z", + } + + +def test_null_values(converter: PackageConverter): + package = package_fixture( + built_date=None, + release_date=None, + valid_until_date=None, + homepage=None, + license_concluded=None, + license_declared=None, + originator=None, + verification_code=None, + primary_package_purpose=None, + supplier=None, + version=None, + file_name=None, + source_info=None, + license_comment=None, + copyright_text=None, + summary=None, + description=None, + comment=None, + attribution_texts=[], + checksums=[], + external_references=[], + license_info_from_files=[], + ) + + document = Document(creation_info_fixture(), packages=[package]) + + converted_dict = converter.convert(package, document) + + assert converter.json_property_name(PackageProperty.VERSION_INFO) not in converted_dict + assert converter.json_property_name(PackageProperty.PACKAGE_FILE_NAME) not in converted_dict + assert converter.json_property_name(PackageProperty.SUPPLIER) not in converted_dict + assert converter.json_property_name(PackageProperty.ORIGINATOR) not in converted_dict + assert converter.json_property_name(PackageProperty.PACKAGE_VERIFICATION_CODE) not in converted_dict + assert converter.json_property_name(PackageProperty.HOMEPAGE) not in converted_dict + assert converter.json_property_name(PackageProperty.SOURCE_INFO) not in converted_dict + assert converter.json_property_name(PackageProperty.LICENSE_CONCLUDED) not in converted_dict + assert converter.json_property_name(PackageProperty.LICENSE_DECLARED) not in converted_dict + assert converter.json_property_name(PackageProperty.LICENSE_COMMENTS) not in converted_dict + assert converter.json_property_name(PackageProperty.COPYRIGHT_TEXT) not in converted_dict + assert converter.json_property_name(PackageProperty.SUMMARY) not in converted_dict + assert converter.json_property_name(PackageProperty.DESCRIPTION) not in converted_dict + assert converter.json_property_name(PackageProperty.COMMENT) not in converted_dict + assert converter.json_property_name(PackageProperty.PRIMARY_PACKAGE_PURPOSE) not in converted_dict + assert converter.json_property_name(PackageProperty.BUILT_DATE) not in converted_dict + assert converter.json_property_name(PackageProperty.RELEASE_DATE) not in converted_dict + assert converter.json_property_name(PackageProperty.VALID_UNTIL_DATE) not in converted_dict + assert converter.json_property_name(PackageProperty.ANNOTATIONS) not in converted_dict + assert converter.json_property_name(PackageProperty.ATTRIBUTION_TEXTS) not in converted_dict + assert converter.json_property_name(PackageProperty.CHECKSUMS) not in converted_dict + assert converter.json_property_name(PackageProperty.EXTERNAL_REFS) not in converted_dict + assert converter.json_property_name(PackageProperty.LICENSE_INFO_FROM_FILES) not in converted_dict + + +def test_spdx_no_assertion(converter: PackageConverter): + package = package_fixture( + download_location=SpdxNoAssertion(), + supplier=SpdxNoAssertion(), + originator=SpdxNoAssertion(), + homepage=SpdxNoAssertion(), + license_concluded=SpdxNoAssertion(), + license_info_from_files=[SpdxNoAssertion()], + license_declared=SpdxNoAssertion(), + copyright_text=SpdxNoAssertion(), + ) + + document = Document(creation_info_fixture(), packages=[package]) + + converted_dict = converter.convert(package, document) + + assert converted_dict[converter.json_property_name(PackageProperty.DOWNLOAD_LOCATION)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(PackageProperty.SUPPLIER)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(PackageProperty.ORIGINATOR)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(PackageProperty.HOMEPAGE)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(PackageProperty.LICENSE_CONCLUDED)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(PackageProperty.LICENSE_INFO_FROM_FILES)] == [ + SPDX_NO_ASSERTION_STRING + ] + assert converted_dict[converter.json_property_name(PackageProperty.LICENSE_DECLARED)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(PackageProperty.COPYRIGHT_TEXT)] == SPDX_NO_ASSERTION_STRING + + +def test_spdx_none(converter: PackageConverter): + package = package_fixture( + download_location=SpdxNone(), + homepage=SpdxNone(), + license_concluded=SpdxNone(), + license_info_from_files=[SpdxNone()], + license_declared=SpdxNone(), + copyright_text=SpdxNone(), + ) + + document = Document(creation_info_fixture(), packages=[package]) + + converted_dict = converter.convert(package, document) + + assert converted_dict[converter.json_property_name(PackageProperty.DOWNLOAD_LOCATION)] == SPDX_NONE_STRING + assert converted_dict[converter.json_property_name(PackageProperty.HOMEPAGE)] == SPDX_NONE_STRING + assert converted_dict[converter.json_property_name(PackageProperty.LICENSE_CONCLUDED)] == SPDX_NONE_STRING + assert converted_dict[converter.json_property_name(PackageProperty.LICENSE_INFO_FROM_FILES)] == [SPDX_NONE_STRING] + assert converted_dict[converter.json_property_name(PackageProperty.LICENSE_DECLARED)] == SPDX_NONE_STRING + assert converted_dict[converter.json_property_name(PackageProperty.COPYRIGHT_TEXT)] == SPDX_NONE_STRING + + +def test_package_annotations(converter: PackageConverter): + package = package_fixture(spdx_id="packageId") + document = document_fixture(packages=[package]) + first_package_annotation = annotation_fixture(spdx_id=package.spdx_id) + second_package_annotation = annotation_fixture(spdx_id=package.spdx_id) + document_annotation = annotation_fixture(spdx_id=document.creation_info.spdx_id) + file_annotation = annotation_fixture(spdx_id=document.files[0].spdx_id) + snippet_annotation = annotation_fixture(spdx_id=document.snippets[0].spdx_id) + other_annotation = annotation_fixture(spdx_id="otherId") + annotations = [ + first_package_annotation, + second_package_annotation, + document_annotation, + file_annotation, + snippet_annotation, + other_annotation, + ] + document.annotations = annotations + + # Weird type hint to make warnings about unresolved references from the mock class disappear + annotation_converter: Union[AnnotationConverter, NonCallableMagicMock] = converter.annotation_converter + annotation_converter.convert.return_value = "mock_converted_annotation" + + converted_dict = converter.convert(package, document) + + assert_mock_method_called_with_arguments( + annotation_converter, "convert", first_package_annotation, second_package_annotation + ) + converted_file_annotations = converted_dict.get(converter.json_property_name(PackageProperty.ANNOTATIONS)) + assert converted_file_annotations == ["mock_converted_annotation", "mock_converted_annotation"] diff --git a/tests/spdx/jsonschema/test_package_verification_code_converter.py b/tests/spdx/jsonschema/test_package_verification_code_converter.py new file mode 100644 index 000000000..e55993dc9 --- /dev/null +++ b/tests/spdx/jsonschema/test_package_verification_code_converter.py @@ -0,0 +1,64 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.jsonschema.package_verification_code_converter import PackageVerificationCodeConverter +from spdx_tools.spdx.jsonschema.package_verification_code_properties import PackageVerificationCodeProperty +from spdx_tools.spdx.model import PackageVerificationCode + + +@pytest.fixture +def converter() -> PackageVerificationCodeConverter: + return PackageVerificationCodeConverter() + + +@pytest.mark.parametrize( + "package_verification_code_property,expected", + [ + ( + PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES, + "packageVerificationCodeExcludedFiles", + ), + (PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_VALUE, "packageVerificationCodeValue"), + ], +) +def test_json_property_names( + converter: PackageVerificationCodeConverter, + package_verification_code_property: PackageVerificationCodeProperty, + expected: str, +): + assert converter.json_property_name(package_verification_code_property) == expected + + +def test_json_type(converter: PackageVerificationCodeConverter): + assert converter.get_json_type() == PackageVerificationCodeProperty + + +def test_data_model_type(converter: PackageVerificationCodeConverter): + assert converter.get_data_model_type() == PackageVerificationCode + + +def test_successful_conversion(converter: PackageVerificationCodeConverter): + package_verification_code = PackageVerificationCode("value", ["file1", "file2"]) + + converted_dict = converter.convert(package_verification_code) + + assert converted_dict == { + converter.json_property_name(PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES): [ + "file1", + "file2", + ], + converter.json_property_name(PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_VALUE): "value", + } + + +def test_null_values(converter: PackageVerificationCodeConverter): + package_verification_code = PackageVerificationCode("value") + + converted_dict = converter.convert(package_verification_code) + + assert ( + converter.json_property_name(PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES) + not in converted_dict + ) diff --git a/tests/spdx/jsonschema/test_relationship_converter.py b/tests/spdx/jsonschema/test_relationship_converter.py new file mode 100644 index 000000000..65b2d8803 --- /dev/null +++ b/tests/spdx/jsonschema/test_relationship_converter.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.jsonschema.relationship_converter import RelationshipConverter +from spdx_tools.spdx.jsonschema.relationship_properties import RelationshipProperty +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING +from tests.spdx.fixtures import relationship_fixture + + +@pytest.fixture +def converter() -> RelationshipConverter: + return RelationshipConverter() + + +@pytest.mark.parametrize( + "relationship_property,expected", + [ + (RelationshipProperty.SPDX_ELEMENT_ID, "spdxElementId"), + (RelationshipProperty.COMMENT, "comment"), + (RelationshipProperty.RELATED_SPDX_ELEMENT, "relatedSpdxElement"), + (RelationshipProperty.RELATIONSHIP_TYPE, "relationshipType"), + ], +) +def test_json_property_names( + converter: RelationshipConverter, relationship_property: RelationshipProperty, expected: str +): + assert converter.json_property_name(relationship_property) == expected + + +def test_json_type(converter: RelationshipConverter): + assert converter.get_json_type() == RelationshipProperty + + +def test_data_model_type(converter: RelationshipConverter): + assert converter.get_data_model_type() == Relationship + + +def test_successful_conversion(converter: RelationshipConverter): + relationship = Relationship("spdxElementId", RelationshipType.COPY_OF, "relatedElementId", "comment") + + converted_dict = converter.convert(relationship) + + assert converted_dict == { + converter.json_property_name(RelationshipProperty.SPDX_ELEMENT_ID): "spdxElementId", + converter.json_property_name(RelationshipProperty.COMMENT): "comment", + converter.json_property_name(RelationshipProperty.RELATED_SPDX_ELEMENT): "relatedElementId", + converter.json_property_name(RelationshipProperty.RELATIONSHIP_TYPE): "COPY_OF", + } + + +def test_spdx_no_assertion(converter: RelationshipConverter): + relationship = relationship_fixture(related_spdx_element_id=SpdxNoAssertion()) + + converted_dict = converter.convert(relationship) + + assert ( + converted_dict[converter.json_property_name(RelationshipProperty.RELATED_SPDX_ELEMENT)] + == SPDX_NO_ASSERTION_STRING + ) + + +def test_spdx_none(converter: RelationshipConverter): + relationship = relationship_fixture(related_spdx_element_id=SpdxNone()) + + converted_dict = converter.convert(relationship) + + assert converted_dict[converter.json_property_name(RelationshipProperty.RELATED_SPDX_ELEMENT)] == SPDX_NONE_STRING diff --git a/tests/spdx/jsonschema/test_snippet_converter.py b/tests/spdx/jsonschema/test_snippet_converter.py new file mode 100644 index 000000000..36eecd4ac --- /dev/null +++ b/tests/spdx/jsonschema/test_snippet_converter.py @@ -0,0 +1,193 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import Union +from unittest import mock +from unittest.mock import MagicMock, NonCallableMagicMock + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.snippet_converter import SnippetConverter +from spdx_tools.spdx.jsonschema.snippet_properties import SnippetProperty +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Document, + Snippet, + SpdxNoAssertion, + SpdxNone, +) +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING +from tests.spdx.fixtures import annotation_fixture, creation_info_fixture, document_fixture, snippet_fixture +from tests.spdx.mock_utils import assert_mock_method_called_with_arguments + + +@pytest.fixture +@mock.patch("spdx_tools.spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +def converter(annotation_converter_mock: MagicMock) -> SnippetConverter: + converter = SnippetConverter() + converter.annotation_converter = annotation_converter_mock() + return converter + + +@pytest.mark.parametrize( + "snippet_property,expected", + [ + (SnippetProperty.SPDX_ID, "SPDXID"), + (SnippetProperty.ANNOTATIONS, "annotations"), + (SnippetProperty.ATTRIBUTION_TEXTS, "attributionTexts"), + (SnippetProperty.COMMENT, "comment"), + (SnippetProperty.COPYRIGHT_TEXT, "copyrightText"), + (SnippetProperty.LICENSE_COMMENTS, "licenseComments"), + (SnippetProperty.LICENSE_CONCLUDED, "licenseConcluded"), + (SnippetProperty.LICENSE_INFO_IN_SNIPPETS, "licenseInfoInSnippets"), + (SnippetProperty.NAME, "name"), + (SnippetProperty.RANGES, "ranges"), + (SnippetProperty.SNIPPET_FROM_FILE, "snippetFromFile"), + ], +) +def test_json_property_names(converter: SnippetConverter, snippet_property: SnippetProperty, expected: str): + assert converter.json_property_name(snippet_property) == expected + + +def test_json_type(converter: SnippetConverter): + assert converter.get_json_type() == SnippetProperty + + +def test_data_model_type(converter: SnippetConverter): + assert converter.get_data_model_type() == Snippet + + +def test_successful_conversion(converter: SnippetConverter): + converter.annotation_converter.convert.return_value = "mock_converted_annotation" + file_spdx_id = "fileSpdxId" + snippet = Snippet( + "spdxId", + file_spdx_id=file_spdx_id, + byte_range=(1, 2), + line_range=(3, 4), + license_concluded=spdx_licensing.parse("MIT and GPL-2.0"), + license_info_in_snippet=[spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0")], + license_comment="licenseComment", + copyright_text="copyrightText", + comment="comment", + name="name", + attribution_texts=["attributionText1", "attributionText2"], + ) + + annotation = Annotation( + snippet.spdx_id, + AnnotationType.OTHER, + Actor(ActorType.PERSON, "annotatorName"), + datetime(2022, 12, 5), + "other comment", + ) + document = Document(creation_info_fixture(), snippets=[snippet], annotations=[annotation]) + converted_dict = converter.convert(snippet, document) + + assert converted_dict == { + converter.json_property_name(SnippetProperty.SPDX_ID): "spdxId", + converter.json_property_name(SnippetProperty.ANNOTATIONS): ["mock_converted_annotation"], + converter.json_property_name(SnippetProperty.ATTRIBUTION_TEXTS): ["attributionText1", "attributionText2"], + converter.json_property_name(SnippetProperty.COMMENT): "comment", + converter.json_property_name(SnippetProperty.COPYRIGHT_TEXT): "copyrightText", + converter.json_property_name(SnippetProperty.LICENSE_COMMENTS): "licenseComment", + converter.json_property_name(SnippetProperty.LICENSE_CONCLUDED): "MIT AND GPL-2.0-only", + converter.json_property_name(SnippetProperty.LICENSE_INFO_IN_SNIPPETS): ["MIT", "GPL-2.0-only"], + converter.json_property_name(SnippetProperty.NAME): "name", + converter.json_property_name(SnippetProperty.RANGES): [ + { + "startPointer": {"reference": file_spdx_id, "offset": 1}, + "endPointer": {"reference": file_spdx_id, "offset": 2}, + }, + { + "startPointer": {"reference": file_spdx_id, "lineNumber": 3}, + "endPointer": {"reference": file_spdx_id, "lineNumber": 4}, + }, + ], + converter.json_property_name(SnippetProperty.SNIPPET_FROM_FILE): file_spdx_id, + } + + +def test_null_values(converter: SnippetConverter): + snippet = snippet_fixture( + license_concluded=None, + license_comment=None, + copyright_text=None, + comment=None, + name=None, + attribution_texts=[], + license_info_in_snippet=[], + ) + + document = Document(creation_info_fixture(), snippets=[snippet]) + converted_dict = converter.convert(snippet, document) + + assert converter.json_property_name(SnippetProperty.LICENSE_CONCLUDED) not in converted_dict + assert converter.json_property_name(SnippetProperty.LICENSE_COMMENTS) not in converted_dict + assert converter.json_property_name(SnippetProperty.COPYRIGHT_TEXT) not in converted_dict + assert converter.json_property_name(SnippetProperty.COMMENT) not in converted_dict + assert converter.json_property_name(SnippetProperty.NAME) not in converted_dict + assert converter.json_property_name(SnippetProperty.ANNOTATIONS) not in converted_dict + assert converter.json_property_name(SnippetProperty.ATTRIBUTION_TEXTS) not in converted_dict + assert converter.json_property_name(SnippetProperty.LICENSE_INFO_IN_SNIPPETS) not in converted_dict + + +def test_spdx_no_assertion(converter: SnippetConverter): + snippet = snippet_fixture(license_concluded=SpdxNoAssertion(), license_info_in_snippet=[SpdxNoAssertion()]) + + document = Document(creation_info_fixture(), snippets=[snippet]) + converted_dict = converter.convert(snippet, document) + + assert converted_dict[converter.json_property_name(SnippetProperty.LICENSE_CONCLUDED)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(SnippetProperty.LICENSE_INFO_IN_SNIPPETS)] == [ + SPDX_NO_ASSERTION_STRING + ] + + +def test_spdx_none(converter: SnippetConverter): + snippet = snippet_fixture(license_concluded=SpdxNone(), license_info_in_snippet=[SpdxNone()]) + + document = Document(creation_info_fixture(), snippets=[snippet]) + converted_dict = converter.convert(snippet, document) + + assert converted_dict[converter.json_property_name(SnippetProperty.LICENSE_CONCLUDED)] == SPDX_NONE_STRING + assert converted_dict[converter.json_property_name(SnippetProperty.LICENSE_INFO_IN_SNIPPETS)] == [SPDX_NONE_STRING] + + +def test_snippet_annotations(converter: SnippetConverter): + snippet = snippet_fixture(spdx_id="snippetId") + document = document_fixture(snippets=[snippet]) + first_snippet_annotation = annotation_fixture(spdx_id=snippet.spdx_id) + second_snippet_annotation = annotation_fixture(spdx_id=snippet.spdx_id) + document_annotation = annotation_fixture(spdx_id=document.creation_info.spdx_id) + package_annotation = annotation_fixture(spdx_id=document.packages[0].spdx_id) + file_annotation = annotation_fixture(spdx_id=document.files[0].spdx_id) + other_annotation = annotation_fixture(spdx_id="otherId") + annotations = [ + first_snippet_annotation, + second_snippet_annotation, + document_annotation, + package_annotation, + file_annotation, + other_annotation, + ] + document.annotations = annotations + + # Weird type hint to make warnings about unresolved references from the mock class disappear + annotation_converter: Union[AnnotationConverter, NonCallableMagicMock] = converter.annotation_converter + annotation_converter.convert.return_value = "mock_converted_annotation" + + converted_dict = converter.convert(snippet, document) + + assert_mock_method_called_with_arguments( + annotation_converter, "convert", first_snippet_annotation, second_snippet_annotation + ) + converted_file_annotations = converted_dict.get(converter.json_property_name(SnippetProperty.ANNOTATIONS)) + assert converted_file_annotations == ["mock_converted_annotation", "mock_converted_annotation"] diff --git a/tests/spdx/mock_utils.py b/tests/spdx/mock_utils.py new file mode 100644 index 000000000..6bea46ffa --- /dev/null +++ b/tests/spdx/mock_utils.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import NonCallableMagicMock + + +def assert_mock_method_called_with_arguments(mock_object: NonCallableMagicMock, method_name: str, *args): + assert len(mock_object.method_calls) == len(args) + for running_index in range(len(args)): + call = mock_object.method_calls[running_index] + assert call[0] == method_name + assert call[1][0] == args[running_index] + + +def assert_no_mock_methods_called(mock_object: NonCallableMagicMock): + assert len(mock_object.method_calls) == 0 diff --git a/tests/spdx/model/__init__.py b/tests/spdx/model/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/model/test_actor.py b/tests/spdx/model/test_actor.py new file mode 100644 index 000000000..e41e40b4e --- /dev/null +++ b/tests/spdx/model/test_actor.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.model import Actor, ActorType + + +def test_correct_initialization(): + actor = Actor(ActorType.TOOL, "tool_name", "mail") + assert actor.actor_type == ActorType.TOOL + assert actor.name == "tool_name" + assert actor.email == "mail" + + +def test_correct_initialization_with_optional_as_none(): + actor = Actor(ActorType.TOOL, "tool_name", None) + assert actor.actor_type == ActorType.TOOL + assert actor.name == "tool_name" + assert actor.email is None + + +def test_wrong_type_in_actor_type(): + with pytest.raises(TypeError): + Actor("PERSON", "name") + + +def test_wrong_type_in_name(): + with pytest.raises(TypeError): + Actor(ActorType.PERSON, 42) + + +def test_wrong_type_in_email(): + with pytest.raises(TypeError): + Actor(ActorType.PERSON, "name", []) + + +def test_wrong_type_in_email_after_initializing(): + with pytest.raises(TypeError): + actor = Actor(ActorType.PERSON, "name") + actor.email = [] + + +@pytest.mark.parametrize( + "actor,expected_string", + [ + (Actor(ActorType.PERSON, "personName"), "Person: personName"), + (Actor(ActorType.PERSON, "personName", "personEmail"), "Person: personName (personEmail)"), + (Actor(ActorType.ORGANIZATION, "orgName"), "Organization: orgName"), + (Actor(ActorType.ORGANIZATION, "orgName", "orgEmail"), "Organization: orgName (orgEmail)"), + (Actor(ActorType.TOOL, "toolName"), "Tool: toolName"), + (Actor(ActorType.TOOL, "toolName", "toolEmail"), "Tool: toolName (toolEmail)"), + ], +) +def test_serialization(actor: Actor, expected_string: str): + assert actor.to_serialized_string() == expected_string diff --git a/tests/spdx/model/test_annotation.py b/tests/spdx/model/test_annotation.py new file mode 100644 index 000000000..5638b0b98 --- /dev/null +++ b/tests/spdx/model/test_annotation.py @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from datetime import datetime +from unittest import mock + +import pytest + +from spdx_tools.spdx.model import Annotation, AnnotationType + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_correct_initialization(actor): + annotation = Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") + assert annotation.spdx_id == "id" + assert annotation.annotation_type == AnnotationType.OTHER + assert annotation.annotator == actor + assert annotation.annotation_date == datetime(2022, 1, 1) + assert annotation.annotation_comment == "comment" + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_spdx_id(actor): + with pytest.raises(TypeError): + Annotation(42, AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_annotation_type(actor): + with pytest.raises(TypeError): + Annotation("id", 42, actor, datetime(2022, 1, 1), "comment") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_annotator(actor): + with pytest.raises(TypeError): + Annotation("id", AnnotationType.OTHER, 42, datetime(2022, 1, 1), "comment") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_annotation_date(actor): + with pytest.raises(TypeError): + Annotation("id", AnnotationType.OTHER, actor, 42, "comment") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_annotation_comment(actor): + with pytest.raises(TypeError): + Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), 42) diff --git a/tests/spdx/model/test_checksum.py b/tests/spdx/model/test_checksum.py new file mode 100644 index 000000000..308d95486 --- /dev/null +++ b/tests/spdx/model/test_checksum.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm + + +def test_correct_initialization(): + checksum = Checksum(ChecksumAlgorithm.BLAKE2B_256, "value") + assert checksum.algorithm == ChecksumAlgorithm.BLAKE2B_256 + assert checksum.value == "value" + + +def test_wrong_type_in_algorithm(): + with pytest.raises(TypeError): + Checksum(42, "value") + + +def test_wrong_type_in_value(): + with pytest.raises(TypeError): + Checksum(ChecksumAlgorithm.BLAKE2B_256, 42) diff --git a/tests/spdx/model/test_creation_info.py b/tests/spdx/model/test_creation_info.py new file mode 100644 index 000000000..c0912005c --- /dev/null +++ b/tests/spdx/model/test_creation_info.py @@ -0,0 +1,112 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from datetime import datetime +from unittest import mock + +import pytest + +from spdx_tools.spdx.model import CreationInfo, Version + + +@mock.patch("spdx_tools.spdx.model.ExternalDocumentRef", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_correct_initialization(actor, ext_ref): + creation_info = CreationInfo( + "version", + "id", + "name", + "namespace", + [actor, actor], + datetime(2022, 1, 1), + "creator_comment", + "CC0-1.1", + [ext_ref, ext_ref], + Version(6, 3), + "doc_comment", + ) + assert creation_info.spdx_version == "version" + assert creation_info.spdx_id == "id" + assert creation_info.name == "name" + assert creation_info.document_namespace == "namespace" + assert creation_info.creators == [actor, actor] + assert creation_info.created == datetime(2022, 1, 1) + assert creation_info.creator_comment == "creator_comment" + assert creation_info.data_license == "CC0-1.1" + assert creation_info.external_document_refs == [ext_ref, ext_ref] + assert creation_info.license_list_version == Version(6, 3) + assert creation_info.document_comment == "doc_comment" + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_spdx_version(actor): + with pytest.raises(TypeError): + CreationInfo(42, "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1)) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_spdx_id(actor): + with pytest.raises(TypeError): + CreationInfo("version", 42, "name", "namespace", [actor, actor], datetime(2022, 1, 1)) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_name(actor): + with pytest.raises(TypeError): + CreationInfo("version", "id", 42, "namespace", [actor, actor], datetime(2022, 1, 1)) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_document_namespace(actor): + with pytest.raises(TypeError): + CreationInfo("version", "id", "name", 42, [actor, actor], datetime(2022, 1, 1)) + + +def test_wrong_type_in_creators(): + with pytest.raises(TypeError): + CreationInfo("version", "id", "name", "namespace", ["person"], datetime(2022, 1, 1)) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_created(actor): + with pytest.raises(TypeError): + CreationInfo("version", "id", "name", "namespace", [actor, actor], "2022-01-01") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_creator_comment(actor): + with pytest.raises(TypeError): + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), creator_comment=["string"] + ) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_data_license(actor): + with pytest.raises(TypeError): + CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), data_license=42) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_external_document_refs(actor): + with pytest.raises(TypeError): + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), external_document_refs=() + ) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_license_list_version(actor): + with pytest.raises(TypeError): + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), license_list_version="6.4" + ) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_document_comment(actor): + with pytest.raises(TypeError): + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), document_comment=["1"] + ) diff --git a/tests/spdx/model/test_document.py b/tests/spdx/model/test_document.py new file mode 100644 index 000000000..9d4079cb4 --- /dev/null +++ b/tests/spdx/model/test_document.py @@ -0,0 +1,88 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from unittest import mock + +import pytest + +from spdx_tools.spdx.model import Document + + +@mock.patch("spdx_tools.spdx.model.ExtractedLicensingInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.Relationship", autospec=True) +@mock.patch("spdx_tools.spdx.model.Annotation", autospec=True) +@mock.patch("spdx_tools.spdx.model.Snippet", autospec=True) +@mock.patch("spdx_tools.spdx.model.File", autospec=True) +@mock.patch("spdx_tools.spdx.model.Package", autospec=True) +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_correct_initialization(creation_info, package, file, snippet, annotation, relationship, extracted_lic): + document = Document( + creation_info, + [package, package], + [file, file], + [snippet, snippet], + [annotation, annotation], + [relationship, relationship], + [extracted_lic, extracted_lic], + ) + assert document.creation_info == creation_info + assert document.packages == [package, package] + assert document.files == [file, file] + assert document.snippets == [snippet, snippet] + assert document.annotations == [annotation, annotation] + assert document.relationships == [relationship, relationship] + assert document.extracted_licensing_info == [extracted_lic, extracted_lic] + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_correct_initialization_with_default_values(creation_info): + document = Document(creation_info) + assert document.creation_info == creation_info + assert document.packages == [] + assert document.files == [] + assert document.snippets == [] + assert document.annotations == [] + assert document.relationships == [] + assert document.extracted_licensing_info == [] + + +def test_wrong_type_in_creation_info(): + with pytest.raises(TypeError): + Document("string") + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_packages(creation_info): + with pytest.raises(TypeError): + Document(creation_info, packages=["string"]) + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_files(creation_info): + with pytest.raises(TypeError): + Document(creation_info, files={}) + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_snippets(creation_info): + with pytest.raises(TypeError): + Document(creation_info, snippets=()) + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_annotations(creation_info): + with pytest.raises(TypeError): + Document(creation_info, annotations=["string"]) + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_relationships(creation_info): + with pytest.raises(TypeError): + Document(creation_info, relationships="string") + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_extracted_licensing_info(creation_info): + with pytest.raises(TypeError): + Document(creation_info, extracted_licensing_info=42) diff --git a/tests/spdx/model/test_external_document_ref.py b/tests/spdx/model/test_external_document_ref.py new file mode 100644 index 000000000..4b32d6bf3 --- /dev/null +++ b/tests/spdx/model/test_external_document_ref.py @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from unittest import mock + +import pytest + +from spdx_tools.spdx.model import ExternalDocumentRef + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_correct_initialization(checksum): + external_document_ref = ExternalDocumentRef("id", "uri", checksum) + assert external_document_ref.document_ref_id == "id" + assert external_document_ref.document_uri == "uri" + assert external_document_ref.checksum == checksum + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_spdx_id(checksum): + with pytest.raises(TypeError): + ExternalDocumentRef(42, "uri", checksum) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_document_uri(checksum): + with pytest.raises(TypeError): + ExternalDocumentRef("id", 42, checksum) + + +def test_wrong_type_in_checksum(): + with pytest.raises(TypeError): + ExternalDocumentRef("id", "uri", 42) diff --git a/tests/spdx/model/test_external_package_reference.py b/tests/spdx/model/test_external_package_reference.py new file mode 100644 index 000000000..d81bcc221 --- /dev/null +++ b/tests/spdx/model/test_external_package_reference.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory + + +def test_correct_initialization(): + external_package_reference = ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", "locator", "comment") + assert external_package_reference.category == ExternalPackageRefCategory.OTHER + assert external_package_reference.reference_type == "type" + assert external_package_reference.locator == "locator" + assert external_package_reference.comment == "comment" + + +def test_wrong_type_in_category(): + with pytest.raises(TypeError): + ExternalPackageRef([ExternalPackageRefCategory.OTHER], "type", "locator") + + +def test_wrong_type_in_reference_type(): + with pytest.raises(TypeError): + ExternalPackageRef(ExternalPackageRefCategory.OTHER, 42, "locator") + + +def test_wrong_type_in_locator(): + with pytest.raises(TypeError): + ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", 42) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", "locator", []) diff --git a/tests/spdx/model/test_extracted_licensing_info.py b/tests/spdx/model/test_extracted_licensing_info.py new file mode 100644 index 000000000..203d13df3 --- /dev/null +++ b/tests/spdx/model/test_extracted_licensing_info.py @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.model import ExtractedLicensingInfo + + +def test_correct_initialization(): + extracted_licensing_info = ExtractedLicensingInfo("id", "text", "name", ["reference"], "comment") + assert extracted_licensing_info.license_id == "id" + assert extracted_licensing_info.extracted_text == "text" + assert extracted_licensing_info.license_name == "name" + assert extracted_licensing_info.cross_references == ["reference"] + assert extracted_licensing_info.comment == "comment" + + +def test_wrong_type_in_license_id(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(license_id=42) + + +def test_wrong_type_in_extracted_text(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(extracted_text=42) + + +def test_wrong_type_in_license_name(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(license_name=42) + + +def test_wrong_type_in_cross_references(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(cross_references=[41, 42]) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(comment=42) diff --git a/tests/spdx/model/test_file.py b/tests/spdx/model/test_file.py new file mode 100644 index 000000000..287c16635 --- /dev/null +++ b/tests/spdx/model/test_file.py @@ -0,0 +1,128 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from unittest import mock + +import pytest + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, File, FileType, SpdxNoAssertion, SpdxNone + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_correct_initialization(checksum): + file = File( + "name", + "id", + [checksum, checksum], + [FileType.OTHER, FileType.SPDX], + SpdxNone(), + [SpdxNoAssertion()], + "comment on license", + "copyright", + "comment", + "notice", + ["contributor"], + ["attribution"], + ) + assert file.name == "name" + assert file.spdx_id == "id" + assert file.checksums == [checksum, checksum] + assert file.file_types == [FileType.OTHER, FileType.SPDX] + assert file.license_concluded == SpdxNone() + assert file.license_info_in_file == [SpdxNoAssertion()] + assert file.license_comment == "comment on license" + assert file.copyright_text == "copyright" + assert file.comment == "comment" + assert file.notice == "notice" + assert file.contributors == ["contributor"] + assert file.attribution_texts == ["attribution"] + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_correct_initialization_with_default_values(checksum): + file = File("name", "id", [checksum, checksum]) + assert file.name == "name" + assert file.spdx_id == "id" + assert file.checksums == [checksum, checksum] + assert file.file_types == [] + assert file.license_concluded is None + assert file.license_info_in_file == [] + assert file.license_comment is None + assert file.copyright_text is None + assert file.comment is None + assert file.notice is None + assert file.contributors == [] + assert file.attribution_texts == [] + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_name(checksum): + with pytest.raises(TypeError): + File(42, "id", [checksum]) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_spdx_id(checksum): + with pytest.raises(TypeError): + File("name", 42, [checksum]) + + +def test_wrong_type_in_checksum(): + checksum = Checksum(ChecksumAlgorithm.BLAKE2B_256, "value") + with pytest.raises(TypeError): + File("name", "id", checksum) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_file_type(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], file_types=FileType.OTHER) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_license_concluded(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], license_concluded="NONE") + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_license_info_in_file(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], license_info_in_file=[SpdxNone]) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_license_comment(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], license_comment=42) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_copyright_text(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], copyright_text=[SpdxNone()]) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_comment(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], comment=42) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_notice(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], notice=["notice"]) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_contributors(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], contributors="contributor") + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_attribution_texts(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], attribution_texts=[41, 42]) diff --git a/tests/spdx/model/test_package.py b/tests/spdx/model/test_package.py new file mode 100644 index 000000000..2f015f1e0 --- /dev/null +++ b/tests/spdx/model/test_package.py @@ -0,0 +1,233 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from datetime import datetime +from unittest import mock + +import pytest +from license_expression import LicenseExpression + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, Package, PackagePurpose, SpdxNoAssertion, SpdxNone + + +@mock.patch("spdx_tools.spdx.model.ExternalPackageRef", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.PackageVerificationCode", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_correct_initialization(actor, verif_code, checksum, ext_ref): + package = Package( + "id", + "name", + SpdxNoAssertion(), + "version", + "file_name", + SpdxNoAssertion(), + actor, + True, + verif_code, + [checksum], + "homepage", + "source_info", + None, + [spdx_licensing.parse("license and expression"), SpdxNoAssertion()], + SpdxNone(), + "comment on license", + "copyright", + "summary", + "description", + "comment", + [ext_ref, ext_ref], + ["text"], + PackagePurpose.OTHER, + datetime(2022, 1, 1), + None, + None, + ) + assert package.spdx_id == "id" + assert package.name == "name" + assert package.download_location == SpdxNoAssertion() + assert package.version == "version" + assert package.file_name == "file_name" + assert package.supplier == SpdxNoAssertion() + assert package.originator == actor + assert package.files_analyzed + assert package.verification_code == verif_code + assert package.checksums == [checksum] + assert package.homepage == "homepage" + assert package.source_info == "source_info" + assert package.license_concluded is None + assert package.license_info_from_files == [spdx_licensing.parse("license and expression"), SpdxNoAssertion()] + assert package.license_declared == SpdxNone() + assert package.license_comment == "comment on license" + assert package.copyright_text == "copyright" + assert package.summary == "summary" + assert package.description == "description" + assert package.comment == "comment" + assert package.external_references == [ext_ref, ext_ref] + assert package.attribution_texts == ["text"] + assert package.primary_package_purpose == PackagePurpose.OTHER + assert package.release_date == datetime(2022, 1, 1) + assert package.built_date is None + assert package.valid_until_date is None + + +def test_correct_initialization_with_default_values(): + package = Package("id", "name", "location") + assert package.spdx_id == "id" + assert package.name == "name" + assert package.download_location == "location" + assert package.version is None + assert package.file_name is None + assert package.supplier is None + assert package.originator is None + assert package.files_analyzed + assert package.verification_code is None + assert package.checksums == [] + assert package.homepage is None + assert package.source_info is None + assert package.license_concluded is None + assert package.license_info_from_files == [] + assert package.license_declared is None + assert package.license_comment is None + assert package.copyright_text is None + assert package.summary is None + assert package.description is None + assert package.comment is None + assert package.external_references == [] + assert package.attribution_texts == [] + assert package.primary_package_purpose is None + assert package.release_date is None + assert package.built_date is None + assert package.valid_until_date is None + + +def test_wrong_type_in_spdx_id(): + with pytest.raises(TypeError): + Package(42, "name", "location") + + +def test_wrong_type_in_name(): + with pytest.raises(TypeError): + Package("id", 42, "location") + + +def test_wrong_type_in_download_location(): + with pytest.raises(TypeError): + Package("id", "name", 42) + + +def test_wrong_type_in_version(): + with pytest.raises(TypeError): + Package("id", "name", "location", version=42) + + +def test_wrong_type_in_file_name(): + with pytest.raises(TypeError): + Package("id", "name", "location", file_name=42) + + +def test_wrong_type_in_supplier(): + with pytest.raises(TypeError): + Package("id", "name", "location", supplier=SpdxNone()) + + +def test_wrong_type_in_originator(): + with pytest.raises(TypeError): + Package("id", "name", "location", originator=SpdxNone()) + + +def test_wrong_type_in_files_analyzed(): + with pytest.raises(TypeError): + Package("id", "name", "location", files_analyzed=None) + + +def test_wrong_type_in_verification_code(): + with pytest.raises(TypeError): + Package("id", "name", "location", verification_code=[]) + + +def test_wrong_type_in_checksums(): + with pytest.raises(TypeError): + Package("id", "name", "location", checksums=Checksum(ChecksumAlgorithm.MD2, "value")) + + +def test_wrong_type_in_homepage(): + with pytest.raises(TypeError): + Package("id", "name", "location", homepage=42) + + +def test_wrong_type_in_source_info(): + with pytest.raises(TypeError): + Package("id", "name", "location", source_info=42) + + +def test_wrong_type_in_license_concluded(): + with pytest.raises(TypeError): + Package("id", "name", "location", license_concluded=[]) + + +def test_wrong_type_in_license_info_from_files(): + with pytest.raises(TypeError): + Package("id", "name", "location", license_info_from_files=LicenseExpression("string")) + + +def test_wrong_type_in_license_declared(): + with pytest.raises(TypeError): + Package("id", "name", "location", license_declared=[]) + + +def test_wrong_type_in_license_comment(): + with pytest.raises(TypeError): + Package("id", "name", "location", license_comment=42) + + +def test_wrong_type_in_copyright_text(): + with pytest.raises(TypeError): + Package("id", "name", "location", copyright_text=42) + + +def test_wrong_type_in_summary(): + with pytest.raises(TypeError): + Package("id", "name", "location", summary=42) + + +def test_wrong_type_in_description(): + with pytest.raises(TypeError): + Package("id", "name", "location", description=42) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + Package("id", "name", "location", comment=[]) + + +def test_wrong_type_in_external_references(): + with pytest.raises(TypeError): + Package("id", "name", "location", external_references=["external_ref"]) + + +def test_wrong_type_in_attribution_texts(): + with pytest.raises(TypeError): + Package("id", "name", "location", attribution_texts="text") + + +def test_wrong_type_in_primary_package_purpose(): + with pytest.raises(TypeError): + Package("id", "name", "location", primary_package_purpose=[]) + + +def test_wrong_type_in_release_date(): + with pytest.raises(TypeError): + Package("id", "name", "location", release_date=42) + + +def test_wrong_type_in_built_date(): + with pytest.raises(TypeError): + Package("id", "name", "location", built_date="2022-01-01") + + +def test_wrong_type_in_valid_until_date(): + with pytest.raises(TypeError): + Package("id", "name", "location", valid_until_date=SpdxNone()) diff --git a/tests/spdx/model/test_package_verification_code.py b/tests/spdx/model/test_package_verification_code.py new file mode 100644 index 000000000..e1492a91d --- /dev/null +++ b/tests/spdx/model/test_package_verification_code.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.model import PackageVerificationCode + + +def test_correct_initialization(): + package_verification_code = PackageVerificationCode("value", ["file1", "file2"]) + assert package_verification_code.value == "value" + assert package_verification_code.excluded_files == ["file1", "file2"] + + +def test_wrong_type_in_value(): + with pytest.raises(TypeError): + PackageVerificationCode(42, ["file1", "file2"]) + + +def test_wrong_type_in_excluded_files(): + with pytest.raises(TypeError): + PackageVerificationCode("value", "file1") diff --git a/tests/spdx/model/test_relationship.py b/tests/spdx/model/test_relationship.py new file mode 100644 index 000000000..0ffb62482 --- /dev/null +++ b/tests/spdx/model/test_relationship.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion + + +def test_correct_initialization(): + relationship = Relationship("id", RelationshipType.OTHER, SpdxNoAssertion(), "comment") + assert relationship.spdx_element_id == "id" + assert relationship.relationship_type == RelationshipType.OTHER + assert relationship.related_spdx_element_id == SpdxNoAssertion() + assert relationship.comment == "comment" + + +def test_wrong_type_in_spdx_element_id(): + with pytest.raises(TypeError): + Relationship(SpdxNoAssertion(), RelationshipType.OTHER, "other_id") + + +def test_wrong_type_in_relationship_type(): + with pytest.raises(TypeError): + Relationship("id", 42, "other_id") + + +def test_wrong_type_in_related_spdx_element_id(): + with pytest.raises(TypeError): + Relationship("id", RelationshipType.OTHER, 42) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + Relationship("id", RelationshipType.OTHER, "other_id", 42) diff --git a/tests/spdx/model/test_snippet.py b/tests/spdx/model/test_snippet.py new file mode 100644 index 000000000..7fcf21581 --- /dev/null +++ b/tests/spdx/model/test_snippet.py @@ -0,0 +1,104 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.model import Snippet, SpdxNoAssertion, SpdxNone + + +def test_correct_initialization(): + snippet = Snippet( + "id", + "file_id", + (200, 400), + (20, 40), + SpdxNone(), + [SpdxNoAssertion()], + "comment on license", + "copyright", + "comment", + "name", + ["attribution"], + ) + assert snippet.spdx_id == "id" + assert snippet.file_spdx_id == "file_id" + assert snippet.byte_range == (200, 400) + assert snippet.line_range == (20, 40) + assert snippet.license_concluded == SpdxNone() + assert snippet.license_info_in_snippet == [SpdxNoAssertion()] + assert snippet.license_comment == "comment on license" + assert snippet.copyright_text == "copyright" + assert snippet.comment == "comment" + assert snippet.name == "name" + assert snippet.attribution_texts == ["attribution"] + + +def test_correct_initialization_with_default_values(): + snippet = Snippet("id", "file_id", (200, 400)) + assert snippet.spdx_id == "id" + assert snippet.file_spdx_id == "file_id" + assert snippet.byte_range == (200, 400) + assert snippet.line_range is None + assert snippet.license_concluded is None + assert snippet.license_info_in_snippet == [] + assert snippet.license_comment is None + assert snippet.copyright_text is None + assert snippet.comment is None + assert snippet.name is None + assert snippet.attribution_texts == [] + + +def test_wrong_type_in_spdx_id(): + with pytest.raises(TypeError): + Snippet(42, "file_id", (200, 400)) + + +def test_wrong_type_in_file_spdx_id(): + with pytest.raises(TypeError): + Snippet("id", 42, (200, 400)) + + +def test_wrong_type_in_byte_range(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 300, 400)) + + +def test_wrong_type_in_line_range(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), line_range=(20, "40")) + + +def test_wrong_type_in_license_concluded(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), license_concluded="NONE") + + +def test_wrong_type_in_license_info_in_snippet(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), license_info_in_snippet=SpdxNoAssertion()) + + +def test_wrong_type_in_license_comment(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), license_comment=[]) + + +def test_wrong_type_in_copyright_text(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), copyright_text=["copyright"]) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), comment=["comment"]) + + +def test_wrong_type_in_name(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), name=42) + + +def test_wrong_type_in_attribution_texts(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), attribution_texts="attribution") diff --git a/tests/spdx/model/test_version.py b/tests/spdx/model/test_version.py new file mode 100644 index 000000000..a10817b7e --- /dev/null +++ b/tests/spdx/model/test_version.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.model import Version + + +@pytest.mark.parametrize("input_string,expected", [("1.2", Version(1, 2)), ("12.345", Version(12, 345))]) +def test_version_from_string(input_string, expected): + assert Version.is_valid_version_string(input_string) + version: Version = Version.from_string(input_string) + assert version == expected + + +@pytest.mark.parametrize("input_string", ["1", "1-2", "1.a", "a", "a.b", "a.1", "v1.2", "1.2v"]) +def test_invalid_version_string(input_string): + assert not Version.is_valid_version_string(input_string) + with pytest.raises(ValueError) as error: + Version.from_string(input_string) + assert str(error.value) == f"{input_string} is not a valid version string" diff --git a/tests/spdx/parser/__init__.py b/tests/spdx/parser/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/parser/all_formats/__init__.py b/tests/spdx/parser/all_formats/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/parser/all_formats/test_parse_from_file.py b/tests/spdx/parser/all_formats/test_parse_from_file.py new file mode 100644 index 000000000..5a62fb357 --- /dev/null +++ b/tests/spdx/parser/all_formats/test_parse_from_file.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import os + +import pytest + +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.parser.json import json_parser +from spdx_tools.spdx.parser.rdf import rdf_parser +from spdx_tools.spdx.parser.tagvalue import tagvalue_parser +from spdx_tools.spdx.parser.xml import xml_parser +from spdx_tools.spdx.parser.yaml import yaml_parser + + +@pytest.mark.parametrize( + "parser, format_name, extension", + [ + (json_parser, "JSON", ".json"), + (xml_parser, "XML", ".xml"), + (yaml_parser, "YAML", ".yaml"), + (rdf_parser, "Rdf", ".rdf.xml"), + (tagvalue_parser, "Tag", ""), + ], +) +class TestParseFromFile: + def test_parse_from_file_not_found(self, parser, format_name, extension): + with pytest.raises(FileNotFoundError) as err: + wrong_file_path = os.path.join(os.path.dirname(__file__), f"hnjfkjsedhnflsiafg.spdx{extension}") + parser.parse_from_file(wrong_file_path) + + assert err.value.args[1] == "No such file or directory" + + def test_parse_from_file_with_2_3_example(self, parser, format_name, extension): + doc = parser.parse_from_file( + os.path.join(os.path.dirname(__file__), f"../../data/SPDX{format_name}Example-v2.3.spdx{extension}") + ) + assert isinstance(doc, Document) + assert len(doc.annotations) == 5 + assert len(doc.files) == 5 + assert len(doc.packages) == 4 + assert len(doc.snippets) == 1 + assert len(doc.relationships) == 13 + assert len(doc.extracted_licensing_info) == 5 + + def test_parse_from_file_with_2_2_example(self, parser, format_name, extension): + doc = parser.parse_from_file( + os.path.join(os.path.dirname(__file__), f"../../data/SPDX{format_name}Example-v2.2.spdx{extension}") + ) + assert isinstance(doc, Document) + assert len(doc.annotations) == 5 + assert len(doc.files) == 4 + assert len(doc.packages) == 4 + assert len(doc.snippets) == 1 + assert len(doc.relationships) == 11 + assert len(doc.extracted_licensing_info) == 5 + + def test_parse_from_file_with_encoding_example(self, parser, format_name, extension): + doc = parser.parse_from_file( + os.path.join(os.path.dirname(__file__), f"../../data/SPDX{format_name}Example-UTF-16.spdx{extension}"), + "utf-16", + ) + assert isinstance(doc, Document) + assert len(doc.annotations) == 5 + assert len(doc.files) == 4 + assert len(doc.packages) == 4 + assert len(doc.snippets) == 1 + assert len(doc.relationships) == 11 + assert len(doc.extracted_licensing_info) == 5 diff --git a/tests/spdx/parser/jsonlikedict/__init__.py b/tests/spdx/parser/jsonlikedict/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py new file mode 100644 index 000000000..ac814d6cd --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -0,0 +1,132 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import datetime +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import Actor, ActorType, Annotation, AnnotationType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.annotation_parser import AnnotationParser + + +def test_parse_annotation(): + annotation_parser = AnnotationParser() + annotation_dict = { + "annotationDate": "2010-01-29T18:30:22Z", + "annotationType": "OTHER", + "annotator": "Person: Jane Doe ()", + "comment": "Document level annotation", + } + + annotation = annotation_parser.parse_annotation(annotation_dict, spdx_id=DOCUMENT_SPDX_ID) + + assert annotation.annotator == Actor(ActorType.PERSON, name="Jane Doe") + assert annotation.annotation_type == AnnotationType.OTHER + assert annotation.annotation_date == datetime.datetime(2010, 1, 29, 18, 30, 22) + assert annotation.annotation_comment == "Document level annotation" + assert annotation.spdx_id == DOCUMENT_SPDX_ID + + +def test_parse_all_annotations(): + annotation_parser = AnnotationParser() + doc_dict = { + "SPDXID": DOCUMENT_SPDX_ID, + "packages": [ + { + "SPDXID": "SPDXRef-Package", + "annotations": [ + { + "annotationDate": "2010-01-29T17:30:22Z", + "annotationType": "REVIEW", + "annotator": "Person: Mick Doe ()", + "comment": "Package level annotation", + } + ], + } + ], + "files": [ + { + "SPDXID": "SPDXRef-File", + "annotations": [ + { + "annotationDate": "2010-01-29T18:30:22Z", + "annotationType": "OTHER", + "annotator": "Person: Jane Doe ()", + "comment": "File level annotation", + } + ], + } + ], + "snippets": [ + { + "SPDXID": "SPDXRef-Snippet", + "annotations": [ + { + "annotationDate": "2022-01-29T18:30:32Z", + "annotationType": "REVIEW", + "annotator": "Person: Jonas Rie (jonas@example.com)", + "comment": "Snippet level annotation", + } + ], + } + ], + "revieweds": [ + {"reviewDate": "2010-01-29T18:30:22Z", "reviewer": "Person: Jane Doe ()", "comment": "Review annotation"} + ], + } + + annotations = annotation_parser.parse_all_annotations(input_doc_dict=doc_dict) + + assert len(annotations) == 4 + test_case = TestCase() + test_case.maxDiff = None + test_case.assertCountEqual( + annotations, + [ + Annotation( + spdx_id=DOCUMENT_SPDX_ID, + annotation_type=AnnotationType.REVIEW, + annotator=Actor(actor_type=ActorType.PERSON, name="Jane Doe", email=None), + annotation_date=datetime.datetime(2010, 1, 29, 18, 30, 22), + annotation_comment="Review annotation", + ), + Annotation( + spdx_id="SPDXRef-Package", + annotation_type=AnnotationType.REVIEW, + annotator=Actor(actor_type=ActorType.PERSON, name="Mick Doe", email=None), + annotation_date=datetime.datetime(2010, 1, 29, 17, 30, 22), + annotation_comment="Package level annotation", + ), + Annotation( + spdx_id="SPDXRef-File", + annotation_type=AnnotationType.OTHER, + annotator=Actor(actor_type=ActorType.PERSON, name="Jane Doe", email=None), + annotation_date=datetime.datetime(2010, 1, 29, 18, 30, 22), + annotation_comment="File level annotation", + ), + Annotation( + spdx_id="SPDXRef-Snippet", + annotation_type=AnnotationType.REVIEW, + annotator=Actor(actor_type=ActorType.PERSON, name="Jonas Rie", email="jonas@example.com"), + annotation_date=datetime.datetime(2022, 1, 29, 18, 30, 32), + annotation_comment="Snippet level annotation", + ), + ], + ) + + +@pytest.mark.parametrize( + "incomplete_annotation_dict", + [ + {"annotator": "Person: Jane Doe ()"}, + {"annotationDate": "2010-01-29T18:30:22Z"}, + ], +) +def test_parse_incomplete_annotation(incomplete_annotation_dict): + annotation_parser = AnnotationParser() + + with pytest.raises(SPDXParsingError): + annotation_parser.parse_annotation(incomplete_annotation_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py new file mode 100644 index 000000000..24676cccf --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.model import ChecksumAlgorithm +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser + + +def test_parse_checksum(): + checksum_parser = ChecksumParser() + checksum_dict = {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759"} + + checksum = checksum_parser.parse_checksum(checksum_dict) + + assert checksum.value == "d6a770ba38583ed4bb4525bd96e50461655d2759" + assert checksum.algorithm == ChecksumAlgorithm.SHA1 + + +def test_parse_invalid_checksum(): + checksum_parser = ChecksumParser() + checksum_dict = {"algorithm": "SHA", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759"} + + with pytest.raises(SPDXParsingError) as err: + checksum_parser.parse_checksum(checksum_dict) + + TestCase().assertCountEqual( + err.value.get_messages(), ["Error while parsing Checksum: ['Invalid ChecksumAlgorithm: SHA']"] + ) + + +def test_parse_incomplete_checksum(): + checksum_parser = ChecksumParser() + checksum_dict = {"algorithm": "SHA1"} + + with pytest.raises(SPDXParsingError): + checksum_parser.parse_checksum(checksum_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py new file mode 100644 index 000000000..1a9851016 --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -0,0 +1,90 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import Actor, ActorType, Checksum, ChecksumAlgorithm, ExternalDocumentRef, Version +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser + + +def test_parse_creation_info(): + creation_info_parser = CreationInfoParser() + doc_dict = { + "spdxVersion": "2.3", + "SPDXID": DOCUMENT_SPDX_ID, + "name": "Example Document", + "dataLicense": "CC0-1.0", + "documentNamespace": "namespace", + "externalDocumentRefs": [ + { + "externalDocumentId": "DocumentRef-spdx-tool-1.2", + "checksum": {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759"}, + "spdxDocument": "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301", + } + ], + "creationInfo": { + "created": "2010-01-29T18:30:22Z", + "creators": ["Tool: LicenseFind-1.0", "Organization: ExampleCodeInspect ()", "Person: Jane Doe ()"], + "licenseListVersion": "3.7", + "comment": "Some comment.", + }, + } + creation_info = creation_info_parser.parse_creation_info(doc_dict) + + assert creation_info.spdx_version == "2.3" + assert creation_info.spdx_id == DOCUMENT_SPDX_ID + assert creation_info.name == "Example Document" + assert creation_info.document_namespace == "namespace" + assert creation_info.created == datetime(2010, 1, 29, 18, 30, 22) + TestCase().assertCountEqual( + creation_info.creators, + [ + Actor(ActorType.TOOL, "LicenseFind-1.0"), + Actor(ActorType.ORGANIZATION, "ExampleCodeInspect"), + Actor(ActorType.PERSON, "Jane Doe"), + ], + ) + assert creation_info.license_list_version == Version(3, 7) + assert creation_info.external_document_refs == [ + ExternalDocumentRef( + document_ref_id="DocumentRef-spdx-tool-1.2", + checksum=Checksum(algorithm=ChecksumAlgorithm.SHA1, value="d6a770ba38583ed4bb4525bd96e50461655d2759"), + document_uri="http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301", + ) + ] + + +@pytest.mark.parametrize( + "incomplete_dict", + [ + {"spdxVersion": "2.3", "SPDXID": DOCUMENT_SPDX_ID, "name": "Example Document"}, + {"creationInfo": {"created": "2019-02-01T11:30:40Z"}}, + ], +) +def test_parse_incomplete_document_info(incomplete_dict): + creation_info_parser = CreationInfoParser() + + with pytest.raises(SPDXParsingError): + creation_info_parser.parse_creation_info(incomplete_dict) + + +def test_parse_invalid_creation_info(): + creation_info_parser = CreationInfoParser() + doc_dict = { + "spdxVersion": "2.3", + "SPDXID": DOCUMENT_SPDX_ID, + "name": "Example Document", + "creationInfo": { + "created": "2010-01-29T18:30:22Z", + "creators": ["Tool: LicenseFind-1.0", "Organization: ExampleCodeInspect ()", "Person: Jane Doe ()"], + }, + "dataLicense": None, + } + + with pytest.raises(SPDXParsingError): + creation_info_parser.parse_creation_info(doc_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py new file mode 100644 index 000000000..6f98816ca --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( + json_str_to_enum_name, + parse_field_or_no_assertion, + parse_field_or_no_assertion_or_none, +) + + +def test_json_str_to_enum(): + json_str = "BLAKE2b-256" + + enum_name = json_str_to_enum_name(json_str) + + assert enum_name == "BLAKE2B_256" + + +@pytest.mark.parametrize("invalid_json_str,expected_message", [(5, ["Type for enum must be str not int"])]) +def test_invalid_json_str_to_enum(invalid_json_str, expected_message): + with pytest.raises(SPDXParsingError) as err: + json_str_to_enum_name(invalid_json_str) + + TestCase().assertCountEqual(err.value.get_messages(), expected_message) + + +@pytest.mark.parametrize("input_str,expected_type", [("NOASSERTION", SpdxNoAssertion), ("example string", str)]) +def test_parse_field_or_no_assertion(input_str, expected_type): + resulting_value = parse_field_or_no_assertion(input_str, lambda x: x) + + assert isinstance(resulting_value, expected_type) + + +@pytest.mark.parametrize( + "input_str,expected_type", [("NOASSERTION", SpdxNoAssertion), ("NONE", SpdxNone), ("example string", str)] +) +def test_parse_field_or_no_assertion_or_none(input_str, expected_type): + resulting_value = parse_field_or_no_assertion_or_none(input_str, lambda x: x) + + assert isinstance(resulting_value, expected_type) diff --git a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py new file mode 100644 index 000000000..a2d4491c8 --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.extracted_licensing_info_parser import ExtractedLicensingInfoParser + + +def test_parse_extracted_licensing_info(): + extracted_licensing_info_parser = ExtractedLicensingInfoParser() + + extracted_licensing_infos_dict = { + "licenseId": "LicenseRef-Beerware-4.2", + "comment": "The beerware license has a couple of other standard variants.", + "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you ' + "retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and " + "you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "name": "Beer-Ware License (Version 42)", + "seeAlsos": ["http://people.freebsd.org/~phk/"], + } + + extracted_licensing_info = extracted_licensing_info_parser.parse_extracted_licensing_info( + extracted_licensing_infos_dict + ) + + assert extracted_licensing_info.license_id == "LicenseRef-Beerware-4.2" + assert extracted_licensing_info.comment == "The beerware license has a couple of other standard variants." + assert ( + extracted_licensing_info.extracted_text + == '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this ' + "notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is " + "worth it, you can buy me a beer in return Poul-Henning Kamp" + ) + assert extracted_licensing_info.license_name == "Beer-Ware License (Version 42)" + assert extracted_licensing_info.cross_references == ["http://people.freebsd.org/~phk/"] + + +def test_parse_invalid_extracted_licensing_info(): + extracted_licensing_info_parser = ExtractedLicensingInfoParser() + + extracted_licensing_infos_dict = { + "licenseId": "LicenseRef-Beerware-4.2", + "comment": 56, + "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you ' + "retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and " + "you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "name": "Beer-Ware License (Version 42)", + "seeAlsos": ["http://people.freebsd.org/~phk/"], + } + + with pytest.raises(SPDXParsingError): + extracted_licensing_info_parser.parse_extracted_licensing_info(extracted_licensing_infos_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py new file mode 100644 index 000000000..bbe5b70ca --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -0,0 +1,141 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, FileType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements +from spdx_tools.spdx.parser.jsonlikedict.file_parser import FileParser + + +@pytest.mark.parametrize( + "copyright_text, expected_copyright_text", + [ + ("Copyright 2008-2010 John Smith", "Copyright 2008-2010 John Smith"), + ("NOASSERTION", SpdxNoAssertion()), + ("NONE", SpdxNone()), + ], +) +def test_parse_file(copyright_text, expected_copyright_text): + file_parser = FileParser() + file_dict = { + "SPDXID": "SPDXRef-File", + "attributionTexts": ["Some attribution text."], + "checksums": [ + {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758"}, + {"algorithm": "MD5", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, + ], + "comment": "The concluded license was taken from the package level that the file was included in.\nThis " + "information was found in the COPYING.txt file in the xyz directory.", + "copyrightText": copyright_text, + "fileContributors": [ + "The Regents of the University of California", + "Modified by Paul Mundt lethal@linux-sh.org", + "IBM Corporation", + ], + "fileName": "./package/foo.c", + "fileTypes": ["SOURCE"], + "licenseComments": "The concluded license was taken from the package level that the file was included in.", + "licenseConcluded": "(LGPL-2.0-only OR LicenseRef-2)", + "licenseInfoInFiles": ["GPL-2.0-only", "LicenseRef-2", "NOASSERTION"], + "noticeText": "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is hereby granted, free of " + "charge, to any person obtaining a copy of this software and associated documentation files " + '(the "Software"), to deal in the Software without restriction, including without limitation ' + "the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of " + "the Software, and to permit persons to whom the Software is furnished to do so, subject to the " + "following conditions: \nThe above copyright notice and this permission notice shall be " + "included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED " + '"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE ' + "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO " + "EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER " + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN " + "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + } + + file = file_parser.parse_file(file_dict) + + assert file.name == "./package/foo.c" + assert file.spdx_id == "SPDXRef-File" + TestCase().assertCountEqual( + file.checksums, + [ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + ) + assert ( + file.comment + == "The concluded license was taken from the package level that the file was included in.\nThis information " + "was found in the COPYING.txt file in the xyz directory." + ) + assert file.copyright_text == expected_copyright_text + assert file.file_types == [FileType.SOURCE] + TestCase().assertCountEqual( + file.contributors, + [ + "The Regents of the University of California", + "Modified by Paul Mundt lethal@linux-sh.org", + "IBM Corporation", + ], + ) + assert file.license_concluded == spdx_licensing.parse("(LGPL-2.0-only OR LicenseRef-2)") + TestCase().assertCountEqual( + file.license_info_in_file, + [spdx_licensing.parse("GPL-2.0-only"), spdx_licensing.parse("LicenseRef-2"), SpdxNoAssertion()], + ) + assert ( + file.license_comment == "The concluded license was taken from the package level that the file was included in." + ) + assert file.attribution_texts == ["Some attribution text."] + + +def test_parse_invalid_files(): + file_parser = FileParser() + files = [ + {"SPDXID": "SPDXRef-File", "fileName": "Incomplete File"}, + { + "SPDXID": "SPDXRef-File", + "attributionTexts": ["Some attribution text."], + "checksums": [ + {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758"}, + {"algorithm": "MD5", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, + ], + }, + { + "SPDXID": "SPDXRef-File", + "attributionTexts": ["Some attribution text."], + "checksums": [ + {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758"}, + {"algorithm": "MD", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, + ], + }, + {"SPDXID": "SPDXRef-File", "fileName": "Incomplete File"}, + ] + + with pytest.raises(SPDXParsingError): + parse_list_of_elements(files, file_parser.parse_file) + + +def test_parse_file_types(): + file_parser = FileParser() + file_types_list = ["OTHER", "APPLICATION"] + + file_types = file_parser.parse_file_types(file_types_list) + + TestCase().assertCountEqual(file_types, [FileType.OTHER, FileType.APPLICATION]) + + +def test_parse_invalid_file_types(): + file_parser = FileParser() + file_types_list = ["OTHER", "APPLICAON"] + + with pytest.raises(SPDXParsingError) as err: + file_parser.parse_file_types(file_types_list) + + TestCase().assertCountEqual( + err.value.get_messages(), ["Error while parsing FileType: ['Invalid FileType: APPLICAON']"] + ) diff --git a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py new file mode 100644 index 000000000..d78a88af3 --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser + + +@pytest.mark.parametrize( + "license_expression_str, expected_license", + [ + ("First License", spdx_licensing.parse("First License")), + ("Second License", spdx_licensing.parse("Second License")), + ("Apache-1.1", spdx_licensing.parse("Apache-1.1")), + ("Zlib", spdx_licensing.parse("zlib")), + ("NOASSERTION", SpdxNoAssertion()), + ("NONE", SpdxNone()), + ], +) +def test_parse_license_expression(license_expression_str, expected_license): + license_expression_parser = LicenseExpressionParser() + license_expression = license_expression_parser.parse_license_expression(license_expression_str) + + assert license_expression == expected_license + + +@pytest.mark.parametrize( + "invalid_license_expression,expected_message", + [ + (56, ["Error parsing LicenseExpression: \"56\": expression must be a string and not: "]), + ( + "LGPL-2.1, GPL-2.0, GPL-3.0", + [ + # the error message we receive from the license_expression library somehow cuts off the last license + "Error parsing LicenseExpression: \"LGPL-2.1, GPL-2.0, GPL-3.0\": Invalid license key: the valid characters are: letters and numbers, underscore, dot, colon or hyphen signs and spaces: 'LGPL-2.1, GPL-2.0,'" # noqa: E501 + ], + ), + ("Apache License (2.0)", ['Error parsing LicenseExpression: "Apache License (2.0)"']), + ], +) +def test_parse_invalid_license_expression(invalid_license_expression, expected_message): + license_expression_parser = LicenseExpressionParser() + + with pytest.raises(SPDXParsingError) as err: + license_expression_parser.parse_license_expression(invalid_license_expression) + + TestCase().assertCountEqual(err.value.get_messages(), expected_message) diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py new file mode 100644 index 000000000..209cf5c0c --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -0,0 +1,282 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from unittest import TestCase + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, + ExternalPackageRef, + ExternalPackageRefCategory, + PackagePurpose, + PackageVerificationCode, + SpdxNoAssertion, + SpdxNone, +) +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements +from spdx_tools.spdx.parser.jsonlikedict.package_parser import PackageParser + + +@pytest.mark.parametrize( + "homepage, expected_homepage, download_location, expected_download_location, " + "copyright_text, expected_copyright_text, originator, expected_originator, supplier, expected_supplier", + [ + ( + "http://ftp.gnu.org/gnu/glibc", + "http://ftp.gnu.org/gnu/glibc", + "NOASSERTION", + SpdxNoAssertion(), + "NONE", + SpdxNone(), + "Organization: ExampleCodeInspect (contact@example.com)", + Actor(ActorType.ORGANIZATION, "ExampleCodeInspect", "contact@example.com"), + "NOASSERTION", + SpdxNoAssertion(), + ), + ( + "NOASSERTION", + SpdxNoAssertion(), + "NONE", + SpdxNone(), + "Copyright 2008-2010 John Smith", + "Copyright 2008-2010 John Smith", + None, + None, + None, + None, + ), + ( + "NONE", + SpdxNone(), + "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "NOASSERTION", + SpdxNoAssertion(), + "NOASSERTION", + SpdxNoAssertion(), + "Person: Jane Doe (jane.doe@example.com)", + Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com"), + ), + ], +) +def test_parse_package( + homepage, + expected_homepage, + download_location, + expected_download_location, + copyright_text, + expected_copyright_text, + originator, + expected_originator, + supplier, + expected_supplier, +): + package_parser = PackageParser() + + package_dict = { + "SPDXID": "SPDXRef-Package", + "attributionTexts": [ + "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for " + "notices about a few contributions that require these additional notices to be distributed. License " + "copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the " + "range, inclusive, is a copyrightable year that would otherwise be listed individually." + ], + "builtDate": "2011-01-29T18:30:22Z", + "checksums": [ + {"algorithm": "MD5", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, + {"algorithm": "SHA1", "checksumValue": "85ed0817af83a24ad8da68c2b5094de69833983c"}, + { + "algorithm": "SHA256", + "checksumValue": "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd", + }, + { + "algorithm": "BLAKE2b-384", + "checksumValue": "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8" + "086984af8706", + }, + ], + "comment": "This is a comment.", + "copyrightText": copyright_text, + "description": "The GNU C Library defines functions that are specified by the ISO C standard, as well as " + "additional features specific to POSIX and other derivatives of the Unix operating system, and " + "extensions specific to GNU systems.", + "downloadLocation": download_location, + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type", + }, + { + "comment": "This is the external ref for Acme", + "referenceCategory": "OTHER", + "referenceLocator": "acmecorp/acmenator/4.1.3-alpha", + "referenceType": "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" + "#LocationRef-acmeforge", + }, + ], + "filesAnalyzed": True, + "homepage": homepage, + "licenseComments": "The license for this project changed with the release of version x.y. The version of the " + "project included here post-dates the license change.", + "licenseConcluded": "(LGPL-2.0-only OR LicenseRef-3)", + "licenseDeclared": "(LGPL-2.0-only AND LicenseRef-3)", + "licenseInfoFromFiles": ["GPL-2.0-only", "LicenseRef-2", "LicenseRef-1", "NOASSERTION"], + "name": "glibc", + "originator": originator, + "packageFileName": "glibc-2.11.1.tar.gz", + "packageVerificationCode": { + "packageVerificationCodeExcludedFiles": ["./package.spdx"], + "packageVerificationCodeValue": "d6a770ba38583ed4bb4525bd96e50461655d2758", + }, + "primaryPackagePurpose": "SOURCE", + "releaseDate": "2012-01-29T18:30:22Z", + "sourceInfo": "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git.", + "summary": "GNU C library.", + "supplier": supplier, + "validUntilDate": "2014-01-29T18:30:22Z", + "versionInfo": "2.11.1", + } + + package = package_parser.parse_package(package_dict) + + assert package.spdx_id == "SPDXRef-Package" + assert package.name == "glibc" + assert package.download_location == expected_download_location + assert package.version == "2.11.1" + assert package.file_name == "glibc-2.11.1.tar.gz" + assert package.supplier == expected_supplier + assert package.originator == expected_originator + assert package.files_analyzed is True + assert package.verification_code == PackageVerificationCode( + value="d6a770ba38583ed4bb4525bd96e50461655d2758", excluded_files=["./package.spdx"] + ) + assert len(package.checksums) == 4 + TestCase().assertCountEqual( + package.checksums, + [ + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + Checksum(ChecksumAlgorithm.SHA1, "85ed0817af83a24ad8da68c2b5094de69833983c"), + Checksum(ChecksumAlgorithm.SHA256, "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd"), + Checksum( + ChecksumAlgorithm.BLAKE2B_384, + "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706", + ), + ], + ) + assert package.homepage == expected_homepage + assert package.source_info == "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git." + assert package.license_concluded == spdx_licensing.parse("(LGPL-2.0-only OR LicenseRef-3)") + TestCase().assertCountEqual( + package.license_info_from_files, + [ + spdx_licensing.parse("GPL-2.0-only"), + spdx_licensing.parse("LicenseRef-2"), + spdx_licensing.parse("LicenseRef-1"), + SpdxNoAssertion(), + ], + ) + assert package.license_declared == spdx_licensing.parse("(LGPL-2.0-only AND LicenseRef-3)") + assert ( + package.license_comment + == "The license for this project changed with the release of version x.y. The version of the project included" + " here post-dates the license change." + ) + assert package.copyright_text == expected_copyright_text + assert package.summary == "GNU C library." + assert ( + package.description + == "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional " + "features specific to POSIX and other derivatives of the Unix operating system, and extensions specific " + "to GNU systems." + ) + assert package.comment == "This is a comment." + assert len(package.external_references) == 2 + TestCase().assertCountEqual( + package.external_references, + [ + ExternalPackageRef( + ExternalPackageRefCategory.SECURITY, + "cpe23Type", + "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*", + ), + ExternalPackageRef( + ExternalPackageRefCategory.OTHER, + "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge", + locator="acmecorp/acmenator/4.1.3-alpha", + comment="This is the external ref for Acme", + ), + ], + ) + assert package.attribution_texts == [ + "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for " + "notices about a few contributions that require these additional notices to be distributed. License " + "copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the " + "range, inclusive, is a copyrightable year that would otherwise be listed individually." + ] + assert package.primary_package_purpose == PackagePurpose.SOURCE + assert package.release_date == datetime(2012, 1, 29, 18, 30, 22) + assert package.built_date == datetime(2011, 1, 29, 18, 30, 22) + assert package.valid_until_date == datetime(2014, 1, 29, 18, 30, 22) + + +@pytest.mark.parametrize( + "incomplete_package_dict", + [ + {"SPDXID": "SPDXRef-Package"}, + {"SPDXID": "SPDXRef-Package", "name": 5, "downloadLocation": "NONE"}, + { + "SPDXID": "SPDXRef-Package", + "name": "Example Package", + "downloadLocation": "NONE", + "checksums": [{"algorithm": "SHA", "value": "1234"}], + }, + ], +) +def test_parse_invalid_package(incomplete_package_dict): + package_parser = PackageParser() + + with pytest.raises(SPDXParsingError): + package_parser.parse_package(incomplete_package_dict) + + +def test_parse_packages(): + package_parser = PackageParser() + packages_list = [ + { + "SPDXID": "SPDXRef-Package", + "name": "Example Package", + "downloadLocation": "NONE", + "checksums": [{"algorithm": "SHA", "value": "1234"}], + }, + {"SPDXID": "SPDXRef-Package", "name": 5, "downloadLocation": "NONE"}, + {"SPDXID": "SPDXRef-Package", "name": "Example Package", "downloadLocation": "NONE"}, + ] + + with pytest.raises(SPDXParsingError): + parse_list_of_elements(packages_list, package_parser.parse_package) + + +def test_parse_external_ref(): + package_parser = PackageParser() + external_ref = {"referenceType": "fix"} + + with pytest.raises(SPDXParsingError): + package_parser.parse_external_ref(external_ref) + + +def test_parse_invalid_external_package_ref_category(): + package_parser = PackageParser() + external_package_ref_category = "TEST" + + with pytest.raises(SPDXParsingError) as err: + package_parser.parse_external_ref_category(external_package_ref_category) + + TestCase().assertCountEqual(err.value.get_messages(), ["Invalid ExternalPackageRefCategory: TEST"]) diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py new file mode 100644 index 000000000..dae0e90d7 --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -0,0 +1,215 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.relationship_parser import RelationshipParser + + +def test_parse_relationship(): + relationship_parser = RelationshipParser() + + relationship_dict = { + "spdxElementId": DOCUMENT_SPDX_ID, + "relationshipType": "CONTAINS", + "relatedSpdxElement": "NOASSERTION", + "comment": "Comment.", + } + + relationship = relationship_parser.parse_relationship(relationship_dict) + + assert relationship.relationship_type == RelationshipType.CONTAINS + assert relationship.spdx_element_id == DOCUMENT_SPDX_ID + assert relationship.related_spdx_element_id == SpdxNoAssertion() + assert relationship.comment == "Comment." + + +def test_parse_incomplete_relationship(): + relationship_parser = RelationshipParser() + relationship_dict = { + "spdxElementId": DOCUMENT_SPDX_ID, + "relatedSpdxElement": "SPDXRef-Package", + "comment": "Comment.", + } + + with pytest.raises(SPDXParsingError): + relationship_parser.parse_relationship(relationship_dict) + + +def test_parse_relationship_type(): + relationship_parser = RelationshipParser() + relationship_type_str = "DEPENDENCY_OF" + + relationship_type = relationship_parser.parse_relationship_type(relationship_type_str) + assert relationship_type == RelationshipType.DEPENDENCY_OF + + +def test_parse_document_describes(): + relationship_parser = RelationshipParser() + + document_dict = { + "SPDXID": DOCUMENT_SPDX_ID, + "documentDescribes": ["SPDXRef-Package", "SPDXRef-File", "SPDXRef-Snippet"], + } + + relationships = relationship_parser.parse_document_describes( + doc_spdx_id=DOCUMENT_SPDX_ID, + described_spdx_ids=document_dict.get("documentDescribes"), + existing_relationships=[], + ) + + assert len(relationships) == 3 + TestCase().assertCountEqual( + relationships, + [ + Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-Package"), + Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-File"), + Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-Snippet"), + ], + ) + + +@pytest.mark.parametrize( + "document_describes,relationships,parsed_relationships", + [ + ( + ["SPDXRef-Package", "SPDXRef-File"], + [ + { + "spdxElementId": DOCUMENT_SPDX_ID, + "relatedSpdxElement": "SPDXRef-Package", + "relationshipType": "DESCRIBES", + "comment": "This relationship has a comment.", + }, + { + "spdxElementId": "SPDXRef-File", + "relatedSpdxElement": DOCUMENT_SPDX_ID, + "relationshipType": "DESCRIBED_BY", + "comment": "This relationship has a comment.", + }, + ], + [ + Relationship( + related_spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.DESCRIBES, + spdx_element_id=DOCUMENT_SPDX_ID, + comment="This relationship has a comment.", + ), + Relationship( + related_spdx_element_id=DOCUMENT_SPDX_ID, + relationship_type=RelationshipType.DESCRIBED_BY, + spdx_element_id="SPDXRef-File", + comment="This relationship has a comment.", + ), + ], + ), + ( + ["SPDXRef-Package", "SPDXRef-File", "SPDXRef-Package"], + [], + [ + Relationship( + related_spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.DESCRIBES, + spdx_element_id=DOCUMENT_SPDX_ID, + ), + Relationship( + related_spdx_element_id="SPDXRef-File", + relationship_type=RelationshipType.DESCRIBES, + spdx_element_id=DOCUMENT_SPDX_ID, + ), + ], + ), + ], +) +def test_parse_document_describes_without_duplicating_relationships( + document_describes, relationships, parsed_relationships +): + relationship_parser = RelationshipParser() + document_dict = { + "SPDXID": DOCUMENT_SPDX_ID, + "documentDescribes": document_describes, + "relationships": relationships, + } + + relationships = relationship_parser.parse_all_relationships(document_dict) + + assert len(relationships) == len(parsed_relationships) + TestCase().assertCountEqual(relationships, parsed_relationships) + + +def test_parse_has_files(): + relationship_parser = RelationshipParser() + document_dict = {"packages": [{"SPDXID": "SPDXRef-Package", "hasFiles": ["SPDXRef-File1", "SPDXRef-File2"]}]} + + relationships = relationship_parser.parse_has_files(document_dict.get("packages"), existing_relationships=[]) + + assert len(relationships) == 2 + TestCase().assertCountEqual( + relationships, + [ + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File1", + ), + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File2", + ), + ], + ) + + +@pytest.mark.parametrize( + "has_files,existing_relationships,contains_relationships", + [ + # pre-requisite for parse_has_files requires that comments in relationships are stripped + ( + ["SPDXRef-File1", "SPDXRef-File2"], + [ + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File1", + ), + Relationship( + spdx_element_id="SPDXRef-File2", + relationship_type=RelationshipType.CONTAINED_BY, + related_spdx_element_id="SPDXRef-Package", + ), + ], + [], + ), + ( + ["SPDXRef-File1", "SPDXRef-File2", "SPDXRef-File1"], + [], + [ + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File1", + ), + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File2", + ), + ], + ), + ], +) +def test_parse_has_files_without_duplicating_relationships(has_files, existing_relationships, contains_relationships): + relationship_parser = RelationshipParser() + document_dict = {"packages": [{"SPDXID": "SPDXRef-Package", "hasFiles": has_files}]} + relationships = relationship_parser.parse_has_files( + document_dict.get("packages"), existing_relationships=existing_relationships + ) + + assert len(relationships) == len(contains_relationships) + TestCase().assertCountEqual(relationships, contains_relationships) diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py new file mode 100644 index 000000000..3b9b62a19 --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -0,0 +1,121 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.snippet_parser import SnippetParser + + +@pytest.mark.parametrize( + "copyright_text, expected_copyright_text", + [ + ("Copyright 2008-2010 John Smith", "Copyright 2008-2010 John Smith"), + ("NOASSERTION", SpdxNoAssertion()), + ("NONE", SpdxNone()), + ], +) +def test_parse_snippet(copyright_text, expected_copyright_text): + snippet_parser = SnippetParser() + + snippet_dict = { + "SPDXID": "SPDXRef-Snippet", + "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a " + "commercial scanner identified it as being derived from file foo.c in package xyz which is licensed" + " under GPL-2.0.", + "copyrightText": copyright_text, + "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into " + "the current file. The concluded license information was found in the COPYING.txt file in " + "package xyz.", + "licenseConcluded": "GPL-2.0-only", + "licenseInfoInSnippets": ["GPL-2.0-only", "NOASSERTION"], + "name": "from linux kernel", + "ranges": [ + { + "endPointer": {"offset": 420, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"offset": 310, "reference": "SPDXRef-DoapSource"}, + }, + { + "endPointer": {"lineNumber": 23, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"lineNumber": 5, "reference": "SPDXRef-DoapSource"}, + }, + ], + "snippetFromFile": "SPDXRef-DoapSource", + "attributionTexts": ["Some example attibution text."], + } + snippet = snippet_parser.parse_snippet(snippet_dict) + + assert snippet.spdx_id == "SPDXRef-Snippet" + assert snippet.name == "from linux kernel" + assert ( + snippet.comment + == "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial " + "scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0." + ) + assert snippet.copyright_text == expected_copyright_text + assert ( + snippet.license_comment + == "The concluded license was taken from package xyz, from which the snippet was copied into the current file." + " The concluded license information was found in the COPYING.txt file in package xyz." + ) + assert snippet.byte_range == (310, 420) + assert snippet.line_range == (5, 23) + assert snippet.file_spdx_id == "SPDXRef-DoapSource" + assert snippet.license_info_in_snippet == [spdx_licensing.parse("GPL-2.0-only"), SpdxNoAssertion()] + assert snippet.license_concluded == spdx_licensing.parse("GPL-2.0-only") + assert snippet.attribution_texts == ["Some example attibution text."] + + +def test_parse_incomplete_snippet(): + snippet_parser = SnippetParser() + incomplete_snippet_dict = {"SPDXID": "SPDXRef-Snippet", "file_spdx_id": "SPDXRef-File"} + + with pytest.raises(SPDXParsingError): + snippet_parser.parse_snippet(incomplete_snippet_dict) + + +def test_parse_snippet_with_invalid_snippet_range(): + snippet_parser = SnippetParser() + snippet_with_invalid_ranges_list = { + "SPDXID": "SPDXRef-Snippet", + "file_spdx_id": "SPDXRef-File", + "ranges": [ + { + "endPointer": {"offset": 23, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"offset": "310s", "reference": "SPDXRef-DoapSource"}, + } + ], + } + + with pytest.raises(SPDXParsingError): + snippet_parser.parse_snippet(snippet_with_invalid_ranges_list) + + +def test_parse_invalid_snippet_range(): + snippet_parser = SnippetParser() + + ranges = [ + { + "endPointer": {"lineNumber": 23, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"offset": 310, "reference": "SPDXRef-DoapSource"}, + }, + { + "endPointer": {"offset": 420, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"lineNumber": 5, "reference": "SPDXRef-DoapSource"}, + }, + ] + + with pytest.raises(SPDXParsingError) as err: + snippet_parser.parse_ranges(ranges) + + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while parsing snippet ranges: ['Type of startpointer is not the same as type of endpointer.', " + "'Type of startpointer is not the same as type of endpointer.']" + ], + ) diff --git a/tests/spdx/parser/rdf/__init__.py b/tests/spdx/parser/rdf/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml b/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml new file mode 100644 index 000000000..b8843af02 --- /dev/null +++ b/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml @@ -0,0 +1,215 @@ + + + + SPDX-2.3 + + + https://see.also + extractedText + LicenseRef-1 + licenseComment + licenseName + + + documentComment + documentName + + + + + + fileNotice + + + annotationComment + Person: annotatorName (some@mail.com) + 2022-12-01T00:00:00Z + + + + fileAttributionText + + + + + + + + + + fileContributor + + copyrightText + + + + 71c4025dd9897b364f3ebbb42c484ff43d00791c + + + fileComment + ./fileName.py + licenseComment + + + relationshipComment + + + + + + creatorComment + Person: creatorName (some@mail.com) + 3.19 + 2022-12-01T00:00:00Z + + + + + + + + 71c4025dd9897b364f3ebbb42c484ff43d00791c + + + + + + + + + + + + + + 12.2 + ./packageFileName + Person: supplierName (some@mail.com) + https://download.com + + + + Person: originatorName (some@mail.com) + + + + + + + 2022-12-03T00:00:00Z + true + packageDescription + + sourceInfo + packageLicenseComment + + + ./exclude.py + 85ed0817af83a24ad8da68c2b5094de69833983c + + + + 2022-12-02T00:00:00Z + packageComment + packageAttributionText + https://homepage.com + 2022-12-01T00:00:00Z + packageName + packageSummary + + + 71c4025dd9897b364f3ebbb42c484ff43d00791c + + + + packageCopyrightText + + + org.apache.tomcat:tomcat:9.0.0.M4 + + + externalPackageRefComment + + + + + + + + packageName + http://differentdownload.com + + + + This is the external ref for Acme + acmecorp/acmenator/4.1.3-alpha + + + + + + https://see.also + extractedText + licenseComment + another license + + + + + + + + + + + + 3 + + + + + + 4 + + + + + + + + + 1 + + + + + + + 2 + + + + + + + + + snippetAttributionText + snippetName + snippetLicenseComment + snippetComment + licenseCopyrightText + + + + + + + + diff --git a/tests/spdx/parser/rdf/data/invalid_documents/file_without_spdx_ids.xml b/tests/spdx/parser/rdf/data/invalid_documents/file_without_spdx_ids.xml new file mode 100644 index 000000000..23fe6c7de --- /dev/null +++ b/tests/spdx/parser/rdf/data/invalid_documents/file_without_spdx_ids.xml @@ -0,0 +1,53 @@ + + + + documentComment + documentName + + + + 3.19 + 2022-12-01T00:00:00Z + + + + + packageName + http://differentdownload.com + + + + + + 71c4025dd9897b364f3ebbb42c484ff43d00791c + + + ./fileName.py + + + + + + + 1 + + + + + + + 2 + + + + + + + + + diff --git a/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info.rdf.xml b/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info.rdf.xml new file mode 100644 index 000000000..60178b010 --- /dev/null +++ b/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info.rdf.xml @@ -0,0 +1,18 @@ + + + + documentComment + documentName + + + + 3.19 + + + + + diff --git a/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info_with_snippet.rdf.xml b/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info_with_snippet.rdf.xml new file mode 100644 index 000000000..4cccb26e8 --- /dev/null +++ b/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info_with_snippet.rdf.xml @@ -0,0 +1,79 @@ + + + + SPDX-2.3 + + + https://see.also + extractedText + LicenseRef-1 + licenseComment + licenseName + + + documentComment + documentName + + + + creatorComment + 3.19 + + + + + + + + + + + 3 + + + + + + 4 + + + + + + + + + 1 + + + + + + + 2 + + + + + + + + + snippetAttributionText + snippetName + snippetLicenseComment + snippetComment + licenseCopyrightText + + + + + + + + diff --git a/tests/spdx/parser/rdf/test_annotation_parser.py b/tests/spdx/parser/rdf/test_annotation_parser.py new file mode 100644 index 000000000..c0ed4b1b6 --- /dev/null +++ b/tests/spdx/parser/rdf/test_annotation_parser.py @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os +from datetime import datetime + +from rdflib import BNode, Graph, URIRef + +from spdx_tools.spdx.model import Actor, ActorType, AnnotationType +from spdx_tools.spdx.parser.rdf.annotation_parser import parse_annotation +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def test_parse_annotation(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + doc_namespace = "https://some.namespace" + file_node = URIRef(f"{doc_namespace}#SPDXRef-File") + annotation_node = graph.value(subject=file_node, predicate=SPDX_NAMESPACE.annotation) + assert isinstance(annotation_node, BNode) + + annotation = parse_annotation(annotation_node, graph, file_node, doc_namespace) + + assert annotation.spdx_id == "SPDXRef-File" + assert annotation.annotation_type == AnnotationType.REVIEW + assert annotation.annotator == Actor(ActorType.PERSON, "annotatorName", "some@mail.com") + assert annotation.annotation_date == datetime(2022, 12, 1, 0, 0) + assert annotation.annotation_comment == "annotationComment" diff --git a/tests/spdx/parser/rdf/test_checksum_parser.py b/tests/spdx/parser/rdf/test_checksum_parser.py new file mode 100644 index 000000000..904febb35 --- /dev/null +++ b/tests/spdx/parser/rdf/test_checksum_parser.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os + +import pytest +from rdflib import BNode, Graph, URIRef + +from spdx_tools.spdx.model import ChecksumAlgorithm +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.rdf.checksum_parser import convert_rdf_to_algorithm, parse_checksum +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def test_parse_checksum(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + checksum_node = graph.value( + subject=URIRef("https://some.namespace#DocumentRef-external"), predicate=SPDX_NAMESPACE.checksum + ) + assert isinstance(checksum_node, BNode) + + checksum = parse_checksum(checksum_node, graph) + + assert checksum.algorithm == ChecksumAlgorithm.SHA1 + assert checksum.value == "71c4025dd9897b364f3ebbb42c484ff43d00791c" + + +@pytest.mark.parametrize( + "rdf_element,expected", + [ + (SPDX_NAMESPACE.checksumAlgorithm_sha1, ChecksumAlgorithm.SHA1), + (SPDX_NAMESPACE.checksumAlgorithm_sha224, ChecksumAlgorithm.SHA224), + (SPDX_NAMESPACE.checksumAlgorithm_sha256, ChecksumAlgorithm.SHA256), + (SPDX_NAMESPACE.checksumAlgorithm_sha384, ChecksumAlgorithm.SHA384), + (SPDX_NAMESPACE.checksumAlgorithm_sha512, ChecksumAlgorithm.SHA512), + (SPDX_NAMESPACE.checksumAlgorithm_sha3_256, ChecksumAlgorithm.SHA3_256), + (SPDX_NAMESPACE.checksumAlgorithm_sha3_384, ChecksumAlgorithm.SHA3_384), + (SPDX_NAMESPACE.checksumAlgorithm_sha3_512, ChecksumAlgorithm.SHA3_512), + (SPDX_NAMESPACE.checksumAlgorithm_blake2b256, ChecksumAlgorithm.BLAKE2B_256), + (SPDX_NAMESPACE.checksumAlgorithm_blake2b384, ChecksumAlgorithm.BLAKE2B_384), + (SPDX_NAMESPACE.checksumAlgorithm_blake2b512, ChecksumAlgorithm.BLAKE2B_512), + (SPDX_NAMESPACE.checksumAlgorithm_blake3, ChecksumAlgorithm.BLAKE3), + (SPDX_NAMESPACE.checksumAlgorithm_md2, ChecksumAlgorithm.MD2), + (SPDX_NAMESPACE.checksumAlgorithm_md4, ChecksumAlgorithm.MD4), + (SPDX_NAMESPACE.checksumAlgorithm_md5, ChecksumAlgorithm.MD5), + (SPDX_NAMESPACE.checksumAlgorithm_md6, ChecksumAlgorithm.MD6), + (SPDX_NAMESPACE.checksumAlgorithm_adler32, ChecksumAlgorithm.ADLER32), + ], +) +def test_convert_rdf_to_algorithm(rdf_element, expected): + algorithm = convert_rdf_to_algorithm(rdf_element) + + assert algorithm == expected + + +@pytest.mark.parametrize( + "invalid_rdf_element", + [ + SPDX_NAMESPACE.checksumAlgorithm_blake2b_512, + SPDX_NAMESPACE.checksumAlgorithm_BLAKE2b_512, + SPDX_NAMESPACE.checksumAlgorithm_sha3512, + SPDX_NAMESPACE.checksumAlgorithm_sha513, + SPDX_NAMESPACE.checksumalgorithm_blake2b_512, + ], +) +def test_convert_invalid_rdf_to_algorithm(invalid_rdf_element): + with pytest.raises(SPDXParsingError): + convert_rdf_to_algorithm(invalid_rdf_element) diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py new file mode 100644 index 000000000..d6fbcf81f --- /dev/null +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -0,0 +1,111 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os +from datetime import datetime +from typing import List, Tuple + +import pytest +from rdflib import RDF, Graph, URIRef +from rdflib.term import Node + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import Actor, ActorType, Checksum, ChecksumAlgorithm, Version +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.rdf.creation_info_parser import ( + parse_creation_info, + parse_external_document_refs, + parse_namespace_and_spdx_id, +) +from spdx_tools.spdx.parser.rdf.rdf_parser import parse_from_file +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def test_parse_creation_info(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + + creation_info, _ = parse_creation_info(graph) + assert creation_info.spdx_id == DOCUMENT_SPDX_ID + assert creation_info.spdx_version == "SPDX-2.3" + assert creation_info.name == "documentName" + assert creation_info.document_namespace == "https://some.namespace" + assert creation_info.creators == [Actor(ActorType.PERSON, "creatorName", "some@mail.com")] + assert creation_info.created == datetime(2022, 12, 1, 0, 0) + assert creation_info.creator_comment == "creatorComment" + assert creation_info.data_license == "CC0-1.0" + assert creation_info.license_list_version == Version(3, 19) + assert creation_info.document_comment == "documentComment" + + +def test_parse_namespace_and_spdx_id(): + graph = Graph().add((URIRef("docNamespace#spdxID"), RDF.type, SPDX_NAMESPACE.SpdxDocument)) + + namespace, spdx_id, _ = parse_namespace_and_spdx_id(graph) + + assert namespace == "docNamespace" + assert spdx_id == "spdxID" + + +@pytest.mark.parametrize( + "triples,error_message", + [ + ( + [(URIRef("docNamespace"), RDF.type, SPDX_NAMESPACE.SpdxDocument)], + r"No '#' found in the URI of SpdxDocument", + ), + ([(URIRef(""), RDF.type, URIRef(""))], r"No SpdxDocument found, can't parse rdf file."), + ([(URIRef(f"#{DOCUMENT_SPDX_ID}"), RDF.type, SPDX_NAMESPACE.SpdxDocument)], "No namespace found"), + ( + [ + (URIRef("docNamespace1"), RDF.type, SPDX_NAMESPACE.SpdxDocument), + (URIRef("docNamespace2"), RDF.type, SPDX_NAMESPACE.SpdxDocument), + ], + "Multiple SpdxDocuments found", + ), + ], +) +def test_parse_namespace_and_spdx_id_with_system_exit( + triples: List[Tuple[Node, Node, Node]], error_message: str, caplog +): + graph = Graph() + for triple in triples: + graph = graph.add(triple) + + with pytest.raises(SystemExit): + parse_namespace_and_spdx_id(graph) + + assert error_message in caplog.text + + +def test_parse_external_document_refs(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + doc_namespace = "https://some.namespace" + external_doc_ref_node = graph.value( + subject=URIRef(f"{doc_namespace}#{DOCUMENT_SPDX_ID}"), predicate=SPDX_NAMESPACE.externalDocumentRef + ) + assert isinstance(external_doc_ref_node, URIRef) + + external_document_ref = parse_external_document_refs(external_doc_ref_node, graph, doc_namespace) + + assert external_document_ref.document_ref_id == "DocumentRef-external" + assert external_document_ref.checksum == Checksum( + ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c" + ) + assert external_document_ref.document_uri == "https://namespace.com" + + +@pytest.mark.parametrize( + "file, error_message", + [ + ( + "invalid_creation_info.rdf.xml", + "Error while parsing CreationInfo: ['No creators provided.']", + ), + ("invalid_creation_info_with_snippet.rdf.xml", "Error while parsing CreationInfo: ['No creators provided.']"), + ], +) +def test_parse_invalid_creation_info(file, error_message): + with pytest.raises(SPDXParsingError) as err: + parse_from_file(os.path.join(os.path.dirname(__file__), f"data/invalid_documents/{file}")) + + assert err.value.get_messages() == [error_message] diff --git a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py new file mode 100644 index 000000000..d6027aa7b --- /dev/null +++ b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os + +import pytest +from rdflib import RDF, Graph + +from spdx_tools.spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +@pytest.mark.parametrize( + "license_id, extracted_text, comment, license_name, cross_references", + [ + ( + "LicenseRef-1", + "extractedText", + "licenseComment", + "licenseName", + ["https://see.also"], + ), + ( + "LicenseRef-2", + "extractedText", + "licenseComment", + "another license", + ["https://see.also"], + ), + ], +) +# In rdf, as a short form, the explicit node for licenseId can be omitted, since the ID is also encoded in the URIRef +# of the ExtractedLicensingInfo node. The first test case has an explicit licenseId node whereas the second test case +# does not. This behaviour is similar to the externalDocumentRefId, see the discussion here: +# https://github.com/spdx/spdx-spec/issues/816 +def test_parse_extracted_licensing_info(license_id, extracted_text, comment, license_name, cross_references): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + doc_namespace = "https://some.namespace" + extracted_licensing_info_node = get_extracted_licensing_info_node_by_license_id(graph, license_id) + + extracted_licensing_info = parse_extracted_licensing_info(extracted_licensing_info_node, graph, doc_namespace) + + assert extracted_licensing_info.license_id == license_id + assert extracted_licensing_info.extracted_text == extracted_text + assert extracted_licensing_info.comment == comment + assert extracted_licensing_info.license_name == license_name + assert extracted_licensing_info.cross_references == cross_references + + +def get_extracted_licensing_info_node_by_license_id(graph, license_id): + for extracted_licensing_info_node, _, _ in graph.triples((None, RDF.type, SPDX_NAMESPACE.ExtractedLicensingInfo)): + if extracted_licensing_info_node.fragment == license_id: + return extracted_licensing_info_node diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py new file mode 100644 index 000000000..2d99a5d0a --- /dev/null +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os +from unittest import TestCase + +import pytest +from rdflib import RDF, BNode, Graph, URIRef + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, FileType, SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.rdf.file_parser import parse_file +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def test_parse_file(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + file_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.File) + doc_namespace = "https://some.namespace" + assert isinstance(file_node, URIRef) + + file = parse_file(file_node, graph, doc_namespace) + + assert file.name == "./fileName.py" + assert file.spdx_id == "SPDXRef-File" + assert file.checksums == [Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c")] + assert file.file_types == [FileType.TEXT] + assert file.comment == "fileComment" + assert file.copyright_text == "copyrightText" + assert file.contributors == ["fileContributor"] + assert file.license_concluded == spdx_licensing.parse("MIT AND GPL-2.0") + TestCase().assertCountEqual( + file.license_info_in_file, + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()], + ) + assert file.license_comment == "licenseComment" + assert file.notice == "fileNotice" + assert file.attribution_texts == ["fileAttributionText"] + + +def test_parse_invalid_file(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) + file_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.File) + doc_namespace = "https://some.namespace" + + assert isinstance(file_node, BNode) + with pytest.raises(SPDXParsingError): + parse_file(file_node, graph, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_graph_parsing_function.py b/tests/spdx/parser/rdf/test_graph_parsing_function.py new file mode 100644 index 000000000..2a9fc8a43 --- /dev/null +++ b/tests/spdx/parser/rdf/test_graph_parsing_function.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest +from rdflib import Graph, Namespace, URIRef + +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import parse_spdx_id, remove_prefix + + +@pytest.mark.parametrize( + "resource,doc_namespace,ext_namespace_mapping,expected", + [ + (URIRef("docNamespace#SPDXRef-Test"), "docNamespace", ("", Namespace("")), "SPDXRef-Test"), + (URIRef("docNamespaceSPDXRef-Test"), "docNamespace", ("", Namespace("")), "docNamespaceSPDXRef-Test"), + ( + URIRef("differentNamespace#SPDXRef-Test"), + "docNamespace", + ("extDoc", Namespace("differentNamespace#")), + "extDoc:SPDXRef-Test", + ), + (None, "", ("", Namespace("")), None), + ], +) +def test_parse_spdx_id(resource, doc_namespace, ext_namespace_mapping, expected): + graph = Graph() + graph.bind(*ext_namespace_mapping) + spdx_id = parse_spdx_id(resource, doc_namespace, graph) + + assert spdx_id == expected + + +@pytest.mark.parametrize( + "string,prefix,expected", [("prefixString", "prefix", "String"), ("prefixString", "refix", "prefixString")] +) +def test_remove_prefix(string, prefix, expected): + shorten_string = remove_prefix(string, prefix) + + assert expected == shorten_string diff --git a/tests/spdx/parser/rdf/test_license_expression_parser.py b/tests/spdx/parser/rdf/test_license_expression_parser.py new file mode 100644 index 000000000..d9e7d5986 --- /dev/null +++ b/tests/spdx/parser/rdf/test_license_expression_parser.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os +from unittest import TestCase + +from rdflib import RDF, Graph + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.parser.rdf import rdf_parser +from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def test_license_expression_parser(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + package_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Package) + license_expression_node = graph.value(subject=package_node, predicate=SPDX_NAMESPACE.licenseConcluded) + + license_expression = parse_license_expression(license_expression_node, graph, "https://some.namespace#") + + assert license_expression == spdx_licensing.parse("GPL-2.0 AND MIT") + + +def test_license_expression_parser_with_coupled_licenses(): + doc = rdf_parser.parse_from_file( + os.path.join(os.path.dirname(__file__), "../../data/SPDXRdfExample-v2.3.spdx.rdf.xml") + ) + + packages_by_spdx_id = {package.spdx_id: package for package in doc.packages} + files_by_spdx_id = {file.spdx_id: file for file in doc.files} + + assert packages_by_spdx_id["SPDXRef-Package"].license_declared == spdx_licensing.parse( + "LGPL-2.0-only AND LicenseRef-3" + ) + assert packages_by_spdx_id["SPDXRef-Package"].license_concluded == spdx_licensing.parse( + "LGPL-2.0-only OR LicenseRef-3" + ) + TestCase().assertCountEqual( + packages_by_spdx_id["SPDXRef-Package"].license_info_from_files, + [ + spdx_licensing.parse("GPL-2.0"), + spdx_licensing.parse("LicenseRef-1"), + spdx_licensing.parse("LicenseRef-2"), + ], + ) + + assert files_by_spdx_id["SPDXRef-JenaLib"].license_concluded == spdx_licensing.parse("LicenseRef-1") diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py new file mode 100644 index 000000000..df1907ad1 --- /dev/null +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -0,0 +1,108 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os +from unittest import TestCase + +import pytest +from rdflib import RDF, BNode, Graph, Literal, URIRef + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, + ExternalPackageRefCategory, + PackagePurpose, + PackageVerificationCode, + SpdxNoAssertion, +) +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.rdf.package_parser import parse_external_package_ref, parse_package +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def test_package_parser(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + # we have two packages in the test file, graph.value() will return the first package + package_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Package) + doc_namespace = "https://some.namespace" + assert isinstance(package_node, URIRef) + + package = parse_package(package_node, graph, doc_namespace) + + assert package.spdx_id == "SPDXRef-Package" + assert package.name == "packageName" + assert package.download_location == "https://download.com" + assert package.version == "12.2" + assert package.file_name == "./packageFileName" + assert package.homepage == "https://homepage.com" + assert package.files_analyzed is True + assert package.checksums == [Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c")] + assert package.source_info == "sourceInfo" + assert package.license_concluded == spdx_licensing.parse("MIT AND GPL-2.0") + assert package.license_declared == spdx_licensing.parse("MIT AND GPL-2.0") + TestCase().assertCountEqual( + package.license_info_from_files, + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()], + ) + assert package.license_comment == "packageLicenseComment" + assert package.copyright_text == "packageCopyrightText" + assert package.verification_code == PackageVerificationCode( + value="85ed0817af83a24ad8da68c2b5094de69833983c", excluded_files=["./exclude.py"] + ) + assert len(package.external_references) == 1 + assert package.summary == "packageSummary" + assert package.description == "packageDescription" + assert package.comment == "packageComment" + assert package.attribution_texts == ["packageAttributionText"] + assert package.primary_package_purpose == PackagePurpose.SOURCE + assert package.supplier == Actor(ActorType.PERSON, "supplierName", "some@mail.com") + assert package.originator == Actor(ActorType.PERSON, "originatorName", "some@mail.com") + + +@pytest.mark.parametrize( + "download_location,category,locator,type,comment", + [ + ( + "https://download.com", + ExternalPackageRefCategory.PACKAGE_MANAGER, + "org.apache.tomcat:tomcat:9.0.0.M4", + "maven-central", + "externalPackageRefComment", + ), + ( + "http://differentdownload.com", + ExternalPackageRefCategory.OTHER, + "acmecorp/acmenator/4.1.3-alpha", + "LocationRef-acmeforge", + "This is the external ref for Acme", + ), + ], +) +def test_external_package_ref_parser(download_location, category, locator, type, comment): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + doc_namespace = "https://some.namespace" + # we use the download location to identify the package node + # in the test file we have two different external package refs depending on the package + package_node = graph.value(predicate=SPDX_NAMESPACE.downloadLocation, object=Literal(download_location)) + external_package_ref_node = graph.value(package_node, SPDX_NAMESPACE.externalRef) + assert isinstance(external_package_ref_node, BNode) + + external_package_ref = parse_external_package_ref(external_package_ref_node, graph, doc_namespace) + + assert external_package_ref.category == category + assert external_package_ref.locator == locator + assert external_package_ref.reference_type == type + assert external_package_ref.comment == comment + + +def test_parse_invalid_package(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) + package_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Package) + doc_namespace = "https://some.namespace" + + assert isinstance(package_node, BNode) + with pytest.raises(SPDXParsingError): + parse_package(package_node, graph, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_relationship_parser.py b/tests/spdx/parser/rdf/test_relationship_parser.py new file mode 100644 index 000000000..33024fad3 --- /dev/null +++ b/tests/spdx/parser/rdf/test_relationship_parser.py @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os + +import pytest +from rdflib import RDF, Graph, URIRef + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import RelationshipType +from spdx_tools.spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE + + +def test_relationship_parser(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + parent_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.SpdxDocument) + relationship_node = graph.value(subject=parent_node, predicate=SPDX_NAMESPACE.relationship) + doc_namespace = "https://some.namespace" + assert isinstance(parent_node, URIRef) + + relationship = parse_relationship(relationship_node, graph, parent_node, doc_namespace) + + assert relationship.spdx_element_id == DOCUMENT_SPDX_ID + assert relationship.relationship_type == RelationshipType.DESCRIBES + assert relationship.related_spdx_element_id == "SPDXRef-File" + assert relationship.comment == "relationshipComment" + + +@pytest.mark.parametrize( + "parent_node, predicate, spdx_element_id, relationship_type, related_spdx_element_id", + [ + ( + SPDX_NAMESPACE.SpdxDocument, + SPDX_NAMESPACE.describesPackage, + DOCUMENT_SPDX_ID, + RelationshipType.DESCRIBES, + "SPDXRef-Package", + ), + (SPDX_NAMESPACE.Package, SPDX_NAMESPACE.hasFile, "SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File"), + ], +) +def test_parse_implicit_relationship( + parent_node, predicate, spdx_element_id, relationship_type, related_spdx_element_id +): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + parent_node = graph.value(predicate=RDF.type, object=parent_node) + relationship_node = graph.value(subject=parent_node, predicate=predicate) + assert isinstance(relationship_node, URIRef) + assert isinstance(parent_node, URIRef) + + doc_namespace = "https://some.namespace" + + relationship = parse_implicit_relationship(parent_node, relationship_type, relationship_node, graph, doc_namespace) + + assert relationship.spdx_element_id == spdx_element_id + assert relationship.relationship_type == relationship_type + assert relationship.related_spdx_element_id == related_spdx_element_id diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py new file mode 100644 index 000000000..e3256e4bd --- /dev/null +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -0,0 +1,171 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os +from unittest import TestCase + +import pytest +from rdflib import RDF, BNode, Graph, Literal, URIRef + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.rdf.snippet_parser import parse_ranges, parse_snippet +from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE + + +def test_parse_snippet(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + snippet_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Snippet) + doc_namespace = "https://some.namespace" + assert isinstance(snippet_node, URIRef) + + snippet = parse_snippet(snippet_node, graph, doc_namespace) + + assert snippet.spdx_id == "SPDXRef-Snippet" + assert snippet.file_spdx_id == "SPDXRef-File" + assert snippet.byte_range == (1, 2) + assert snippet.line_range == (3, 4) + assert snippet.license_concluded == spdx_licensing.parse("MIT AND GPL-2.0") + TestCase().assertCountEqual( + snippet.license_info_in_snippet, + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()], + ) + assert snippet.license_comment == "snippetLicenseComment" + assert snippet.copyright_text == "licenseCopyrightText" + assert snippet.comment == "snippetComment" + assert snippet.name == "snippetName" + assert snippet.attribution_texts == ["snippetAttributionText"] + + +@pytest.mark.parametrize( + "predicate_value_class_member", + [ + ( + [ + (POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ] + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + ] + ), + ], +) +def test_parse_ranges(predicate_value_class_member): + graph = Graph() + pointer_class = predicate_value_class_member[0][2] + + add_range_to_graph_helper(graph, predicate_value_class_member) + + range_node = graph.value(predicate=RDF.type, object=POINTER_NAMESPACE.StartEndPointer) + assert isinstance(range_node, BNode) + range_dict = parse_ranges(range_node, graph) + + assert pointer_class.fragment in range_dict.keys() + assert range_dict[pointer_class.fragment][0] == predicate_value_class_member[0][1] + assert range_dict[pointer_class.fragment][1] == predicate_value_class_member[1][1] + + +@pytest.mark.parametrize( + "predicate_value_class_member", + [ + ( + [ + (POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.lineNumber), + (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.lineNumber), + ] + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.offset), + ] + ), + ], +) +def test_parse_ranges_wrong_pair_of_pointer_classes(predicate_value_class_member): + graph = Graph() + pointer_class = predicate_value_class_member[0][2] + + add_range_to_graph_helper(graph, predicate_value_class_member) + + range_node = graph.value(predicate=RDF.type, object=POINTER_NAMESPACE.StartEndPointer) + assert isinstance(range_node, BNode) + range_dict = parse_ranges(range_node, graph) + + assert pointer_class.fragment in range_dict.keys() + assert range_dict[pointer_class.fragment][0] is None + assert range_dict[pointer_class.fragment][1] is None + + +@pytest.mark.parametrize( + "predicate_value_class_member,expected_message", + [ + ( + [ + (POINTER_NAMESPACE.endPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ], + "Couldn't find pointer of type startPointer.", + ), + ( + [(POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset)], + "Couldn't find pointer of type endPointer.", + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 3, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ], + "Multiple values for endPointer.", + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + (POINTER_NAMESPACE.startPointer, 200, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + ], + "Multiple values for startPointer", + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ], + "Types of startPointer and endPointer don't match", + ), + ], +) +def test_parse_ranges_error(predicate_value_class_member, expected_message): + graph = Graph() + + add_range_to_graph_helper(graph, predicate_value_class_member) + + with pytest.raises(SPDXParsingError, match=expected_message): + range_node = graph.value(predicate=RDF.type, object=POINTER_NAMESPACE.StartEndPointer) + assert isinstance(range_node, BNode) + parse_ranges(range_node, graph) + + +def add_range_to_graph_helper(graph, predicate_value_class_member): + start_end_pointer = BNode() + graph.add((start_end_pointer, RDF.type, POINTER_NAMESPACE.StartEndPointer)) + for predicate, value, pointer_class, pointer_member in predicate_value_class_member: + pointer_node = BNode() + graph.add((pointer_node, RDF.type, pointer_class)) + graph.add((start_end_pointer, predicate, pointer_node)) + graph.add((pointer_node, pointer_member, Literal(value))) + + +def test_parse_invalid_file(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) + snippet_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Snippet) + doc_namespace = "https://some.namespace" + + assert isinstance(snippet_node, BNode) + with pytest.raises(SPDXParsingError): + parse_snippet(snippet_node, graph, doc_namespace) diff --git a/tests/spdx/parser/tagvalue/__init__.py b/tests/spdx/parser/tagvalue/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/parser/tagvalue/test_annotation_parser.py b/tests/spdx/parser/tagvalue/test_annotation_parser.py new file mode 100644 index 000000000..f10ebe8c6 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_annotation_parser.py @@ -0,0 +1,95 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import AnnotationType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser +from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR + + +def test_parse_annotation(): + parser = Parser() + annotation_str = "\n".join( + [ + "Annotator: Person: Jane Doe()", + "AnnotationDate: 2010-01-29T18:30:22Z", + "AnnotationComment: Document level annotation", + "AnnotationType: OTHER", + f"SPDXREF: {DOCUMENT_SPDX_ID}", + ] + ) + document = parser.parse("\n".join([DOCUMENT_STR, annotation_str])) + assert document is not None + assert len(document.annotations) == 1 + annotation = document.annotations[0] + assert annotation.annotator.name == "Jane Doe" + assert annotation.annotation_date == datetime(2010, 1, 29, 18, 30, 22) + assert annotation.annotation_comment == "Document level annotation" + assert annotation.annotation_type == AnnotationType.OTHER + assert annotation.spdx_id == DOCUMENT_SPDX_ID + + +def test_parse_annotation_with_organization_as_annotator(): + parser = Parser() + annotation_str = "\n".join( + [ + "Annotator: Organization: some-organization", + "AnnotationDate: 2010-01-29T18:30:22Z", + "AnnotationComment: Document level annotation", + "AnnotationType: OTHER", + f"SPDXREF: {DOCUMENT_SPDX_ID}", + ] + ) + document = parser.parse("\n".join([DOCUMENT_STR, annotation_str])) + assert document is not None + assert len(document.annotations) == 1 + annotation = document.annotations[0] + assert annotation.annotator.name == "some-organization" + assert annotation.annotation_date == datetime(2010, 1, 29, 18, 30, 22) + assert annotation.annotation_comment == "Document level annotation" + assert annotation.annotation_type == AnnotationType.OTHER + assert annotation.spdx_id == DOCUMENT_SPDX_ID + + +@pytest.mark.parametrize( + "annotation_str, expected_message", + [ + ( + "Annotator: Person: Jane Doe()", + r"__init__() missing 4 " + "required positional arguments: 'spdx_id', 'annotation_type', " + "'annotation_date', and 'annotation_comment'", + ), + ( + "Annotator: Person: Jane Doe()\nAnnotationType: SOURCE\nAnnotationDate: 201001-2912:23", + "Error while parsing Annotation: ['Invalid AnnotationType: SOURCE. Line: 2', " + "'Error while parsing AnnotationDate: Token did not match specified grammar " + "rule. Line: 3']", + ), + ( + "Annotator: Jane Doe()\nAnnotationDate: 201001-29T18:30:22Z\n" + "AnnotationComment: Document level annotation\nAnnotationType: OTHER\n" + f"SPDXREF: {DOCUMENT_SPDX_ID}", + "Error while parsing Annotation: ['Error while parsing Annotator: Token did " + "not match specified grammar rule. Line: 1', 'Error while parsing " + "AnnotationDate: Token did not match specified grammar rule. Line: 2']", + ), + ("Annotator: Person: ()", "Error while parsing Annotation: [['No name for Actor provided: Person: ().']]"), + ( + "AnnotationType: REVIEW", + "Element Annotation is not the current element in scope, probably the " + "expected tag to start the element (Annotator) is missing. Line: 1", + ), + ], +) +def test_parse_invalid_annotation(annotation_str, expected_message): + parser = Parser() + with pytest.raises(SPDXParsingError) as err: + parser.parse(annotation_str) + + assert expected_message in err.value.get_messages()[0] diff --git a/tests/spdx/parser/tagvalue/test_creation_info_parser.py b/tests/spdx/parser/tagvalue/test_creation_info_parser.py new file mode 100644 index 000000000..45f472642 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_creation_info_parser.py @@ -0,0 +1,124 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import Actor, ActorType, Checksum, ChecksumAlgorithm, ExternalDocumentRef, Version +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser + +DOCUMENT_STR = "\n".join( + [ + "SPDXVersion: SPDX-2.3", + "DataLicense: CC0-1.0", + "DocumentName: Sample_Document-V2.3", + f"SPDXID: {DOCUMENT_SPDX_ID}", + "DocumentComment: Sample Comment", + "DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", + "ExternalDocumentRef: DocumentRef-spdx-tool-1.2 " + "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 " + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "Creator: Person: Bob (bob@example.com)", + "Creator: Organization: Acme.", + "Created: 2010-02-03T00:00:00Z", + "CreatorComment: Sample Comment \nwith multiple \nlines.", + "LicenseListVersion: 3.17", + ] +) + + +def test_parse_creation_info(): + parser = Parser() + document = parser.parse(DOCUMENT_STR) + assert document is not None + creation_info = document.creation_info + assert creation_info is not None + assert creation_info.spdx_version == "SPDX-2.3" + assert creation_info.data_license == "CC0-1.0" + assert creation_info.name == "Sample_Document-V2.3" + assert creation_info.spdx_id == DOCUMENT_SPDX_ID + assert creation_info.document_comment == "Sample Comment" + assert ( + creation_info.document_namespace + == "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" + ) + TestCase().assertCountEqual( + creation_info.creators, + [Actor(ActorType.PERSON, "Bob", "bob@example.com"), Actor(ActorType.ORGANIZATION, "Acme.")], + ) + assert creation_info.creator_comment == "Sample Comment \nwith multiple \nlines." + assert creation_info.created == datetime(2010, 2, 3) + assert creation_info.license_list_version == Version(3, 17) + assert creation_info.external_document_refs == [ + ExternalDocumentRef( + "DocumentRef-spdx-tool-1.2", + "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301", + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"), + ) + ] + + +@pytest.mark.parametrize( + "document_str, expected_message", + ( + [ + ( + "\n".join( + [ + "SPDXVersion: SPDX-2.3", + "DataLicense: CC0-1.0", + "DocumentName: Sample_Document-V2.3", + f"SPDXID: {DOCUMENT_SPDX_ID}", + "DocumentComment: Sample Comment", + "DocumentNamespace: Sample Comment", + "ExternalDocumentRef: DocumentRef-spdx-tool-1.2:htp://spdx.org:SHA1: " + "d6a770ba38583ed4bb4525bd96e50461655d2759", + "Creator: Person Bob (bob@example.com)", + "Creator: Organization: Acme [email]", + "Created: 2010-02-03T00:00:0Z", + "CreatorComment: Sample Comment", + "LicenseListVersion: 7", + ] + ), + ( + "Error while parsing CreationInfo: ['Error while parsing DocumentNamespace: " + "Token did not match specified grammar rule. Line: 6', \"Error while parsing " + "ExternalDocumentRef: Couldn't split the first part of the value into " + "document_ref_id and document_uri. Line: 7\", 'Error while parsing Creator: " + "Token did not match specified grammar rule. Line: 8', 'Error while parsing " + "Created: Token did not match specified grammar rule. Line: 10', '7 is not a " + "valid version string']" + ), + ), + ( + "\n".join( + [ + "SPDXVersion: SPDX-2.3", + "DataLicense: CC0-1.0", + "DocumentName: Sample_Document-V2.3", + f"SPDXID: {DOCUMENT_SPDX_ID}", + ] + ), + r"__init__() missing 3 required positional arguments: 'document_namespace', 'creators', and 'created'", + ), + ( + "LicenseListVersion: 3.5\nLicenseListVersion: 3.7", + "Error while parsing CreationInfo: ['Multiple values for LicenseListVersion found. Line: 2']", + ), + ( + "ExternalDocumentRef: Document_ref document_uri SHA1: afded", + "Error while parsing CreationInfo: [\"Error while parsing ExternalDocumentRef: Couldn't match " + 'Checksum. Line: 1"]', + ), + ] + ), +) +def test_parse_invalid_creation_info(document_str, expected_message): + parser = Parser() + with pytest.raises(SPDXParsingError) as err: + parser.parse(document_str) + assert expected_message in err.value.get_messages()[0] diff --git a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py new file mode 100644 index 000000000..06fb85520 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser +from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR + + +def test_parse_extracted_licensing_info(): + parser = Parser() + extracted_licensing_info_str = "\n".join( + [ + "LicenseID: LicenseRef-Beerware-4.2", + 'ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): phk@FreeBSD.ORG wrote this file. As long as' + " you retain this notice you can do whatever you want with this stuff. If we meet some day, and you think " + "this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "LicenseName: Beer-Ware License (Version 42)", + "LicenseCrossReference: http://people.freebsd.org/~phk/", + "LicenseCrossReference: http://another.cross.reference/", + "LicenseComment: The beerware license has a couple of other standard variants.", + ] + ) + document = parser.parse("\n".join([DOCUMENT_STR, extracted_licensing_info_str])) + assert document is not None + assert len(document.extracted_licensing_info) == 1 + extracted_licensing_info = document.extracted_licensing_info[0] + assert extracted_licensing_info.license_id == "LicenseRef-Beerware-4.2" + assert ( + extracted_licensing_info.extracted_text + == '"THE BEER-WARE LICENSE" (Revision 42): phk@FreeBSD.ORG wrote this file. ' + "As long as you retain this notice you can do whatever you want with this stuff. " + "If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp" + ) + assert extracted_licensing_info.license_name == "Beer-Ware License (Version 42)" + TestCase().assertCountEqual( + extracted_licensing_info.cross_references, + ["http://people.freebsd.org/~phk/", "http://another.cross.reference/"], + ) + assert extracted_licensing_info.comment == "The beerware license has a couple of other standard variants." + + +def test_parse_invalid_extracted_licensing_info(): + parser = Parser() + extracted_licensing_info_str = "\n".join( + [ + 'ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): phk@FreeBSD.ORG wrote this file. ' + "As long as you retain this notice you can do whatever you want with this stuff. If we meet some day, " + "and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "LicenseName: Beer-Ware License (Version 42)", + "LicenseCrossReference: http://people.freebsd.org/~phk/", + "LicenseComment: The beerware license has a couple of other standard variants.", + ] + ) + + with pytest.raises(SPDXParsingError) as err: + parser.parse(extracted_licensing_info_str) + + assert err.value.get_messages() == [ + "Element ExtractedLicensingInfo is not the current element in scope, probably " + "the expected tag to start the element (LicenseID) is missing. Line: 1", + "Element ExtractedLicensingInfo is not the current element in scope, probably " + "the expected tag to start the element (LicenseID) is missing. Line: 2", + "Element ExtractedLicensingInfo is not the current element in scope, probably " + "the expected tag to start the element (LicenseID) is missing. Line: 3", + "Element ExtractedLicensingInfo is not the current element in scope, probably " + "the expected tag to start the element (LicenseID) is missing. Line: 4", + ] diff --git a/tests/spdx/parser/tagvalue/test_file_parser.py b/tests/spdx/parser/tagvalue/test_file_parser.py new file mode 100644 index 000000000..aedf197b5 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_file_parser.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import FileType, SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser +from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR + + +def test_parse_file(): + parser = Parser() + file_str = "\n".join( + [ + "FileName: testfile.java", + "SPDXID: SPDXRef-File", + "FileType: SOURCE", + "FileType: TEXT", + "FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "LicenseConcluded: Apache-2.0", + "LicenseInfoInFile: Apache-2.0", + "LicenseInfoInFile: NOASSERTION", + "FileCopyrightText: Copyright 2014 Acme Inc.", + "FileComment: Very long file", + "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts." + "", + ] + ) + document = parser.parse("\n".join([DOCUMENT_STR, file_str])) + assert document is not None + assert len(document.files) == 1 + spdx_file = document.files[0] + assert spdx_file.name == "testfile.java" + assert spdx_file.spdx_id == "SPDXRef-File" + assert spdx_file.file_types == [FileType.SOURCE, FileType.TEXT] + assert spdx_file.comment == "Very long file" + assert spdx_file.attribution_texts == [ + "Acknowledgements that might be required to be communicated in some contexts." + ] + assert spdx_file.license_info_in_file == [spdx_licensing.parse("Apache-2.0"), SpdxNoAssertion()] + assert spdx_file.license_concluded == spdx_licensing.parse("Apache-2.0") + + +def test_parse_invalid_file(): + parser = Parser() + file_str = "\n".join( + [ + "FileName: testfile.java", + "SPDXID: SPDXRef-File", + "FileType: SOUCE", + "FileType: TEXT", + "FileChecksum: SHA3: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "LicenseConcluded: Apache-2.0", + "LicenseInfoInFile: Apache-2.0", + "FileCopyrightText: Copyright 2014 Acme Inc.", + "FileComment: Very long file", + "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts." + "", + ] + ) + + with pytest.raises(SPDXParsingError) as err: + parser.parse(file_str) + + assert err.value.get_messages() == [ + "Error while parsing File: ['Invalid FileType: SOUCE. Line 3', 'Error while " + "parsing FileChecksum: Token did not match specified grammar rule. Line: 5']" + ] diff --git a/tests/spdx/parser/tagvalue/test_helper_methods.py b/tests/spdx/parser/tagvalue/test_helper_methods.py new file mode 100644 index 000000000..8ca601828 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_helper_methods.py @@ -0,0 +1,100 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.model import ChecksumAlgorithm +from spdx_tools.spdx.parser.tagvalue.helper_methods import parse_checksum + + +@pytest.mark.parametrize( + "checksum_str, algorithm, value", + [ + ( + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ChecksumAlgorithm.SHA1, + "d6a770ba38583ed4bb4525bd96e50461655d2759", + ), + ( + "SHA224: 9c9f4e27d957a123cc32d86afe33ae53b1184192cccb23b0f257f588", + ChecksumAlgorithm.SHA224, + "9c9f4e27d957a123cc32d86afe33ae53b1184192cccb23b0f257f588", + ), + ( + "SHA256: fbea580d286bbbbb41314430d58ba887716a74d7134119c5307cdc9f0c7a4299", + ChecksumAlgorithm.SHA256, + "fbea580d286bbbbb41314430d58ba887716a74d7134119c5307cdc9f0c7a4299", + ), + ( + "SHA384: 73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933", + ChecksumAlgorithm.SHA384, + "73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933", + ), + ( + "SHA512: c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34a" + "eb7ac10f15af43e7cb5547f1a464053", + ChecksumAlgorithm.SHA512, + "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f" + "15af43e7cb5547f1a464053", + ), + ( + "SHA3-256: 1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce", + ChecksumAlgorithm.SHA3_256, + "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce", + ), + ( + "SHA3-384: dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c16" + "6", + ChecksumAlgorithm.SHA3_384, + "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", + ), + ( + "SHA3-512: 906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd" + "3a101e1d111310266a5d46e2bc1ffbb36", + ChecksumAlgorithm.SHA3_512, + "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d11" + "1310266a5d46e2bc1ffbb36", + ), + ( + "BLAKE2b-256: a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7", + ChecksumAlgorithm.BLAKE2B_256, + "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7", + ), + ( + "BLAKE2B-384: 902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4" + "d0b2", + ChecksumAlgorithm.BLAKE2B_384, + "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", + ), + ( + "BLAKE2B-512: 72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945" + "470842d90b5e8c4af74dce531ca8ebd8824c", + ChecksumAlgorithm.BLAKE2B_512, + "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8" + "c4af74dce531ca8ebd8824c", + ), + ( + "BLAKE3: a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67" + "239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967" + "a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", + ChecksumAlgorithm.BLAKE3, + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dc" + "ec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a1300685" + "7d3b9985174bf67239874dcec4cbbc9839496179feafed", + ), + ("MD2: af1eec2a1b18886c3f3cc244349d91d8", ChecksumAlgorithm.MD2, "af1eec2a1b18886c3f3cc244349d91d8"), + ("MD4: d4c41ce30a517d6ce9d79c8c17bb4b66", ChecksumAlgorithm.MD4, "d4c41ce30a517d6ce9d79c8c17bb4b66"), + ("MD5: 0d7f61beb7018b3924c6b8f96549fa39", ChecksumAlgorithm.MD5, "0d7f61beb7018b3924c6b8f96549fa39"), + ( + "MD6: af1eec2a1b18886c3f3cc244349d91d8d4c41ce30a517d6ce9d79c8c17bb4b660d7f61beb7018b3924c6b8f96549fa39", + ChecksumAlgorithm.MD6, + "af1eec2a1b18886c3f3cc244349d91d8d4c41ce30a517d6ce9d79c8c17bb4b660d7f61beb7018b3924c6b8f96549fa39", + ), + ("ADLER32: 02ec0130", ChecksumAlgorithm.ADLER32, "02ec0130"), + ], +) +def test_parse_checksum(checksum_str, algorithm, value): + checksum = parse_checksum(checksum_str) + + assert checksum.algorithm == algorithm + assert checksum.value == value diff --git a/tests/spdx/parser/tagvalue/test_package_parser.py b/tests/spdx/parser/tagvalue/test_package_parser.py new file mode 100644 index 000000000..470f1e2f7 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_package_parser.py @@ -0,0 +1,140 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from unittest import TestCase + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser +from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR + + +def test_parse_package(): + parser = Parser() + package_str = "\n".join( + [ + "PackageName: Test", + "SPDXID: SPDXRef-Package", + "PackageVersion: 1:22.36.1-8+deb11u1", + "PackageDownloadLocation: http://example.com/test", + "FilesAnalyzed: true", + "PackageSummary: Test package", + "PackageSourceInfo: Version 1.0 of test", + "PackageFileName: test-1.0.zip", + "PackageSupplier: Organization:ACME", + "PackageOriginator: Organization:ACME", + "PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)", + "PackageDescription: A package.", + "PackageComment: Comment on the package.", + "PackageCopyrightText: Copyright 2014 Acme Inc.", + "PackageLicenseDeclared: Apache-2.0", + "PackageLicenseConcluded: (LicenseRef-2.0 and Apache-2.0)", + "PackageLicenseInfoFromFiles: Apache-1.0", + "PackageLicenseInfoFromFiles: Apache-2.0", + "PackageLicenseInfoFromFiles: NONE", + "PackageLicenseComments: License Comments", + "ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", + "ExternalRefComment: Some comment about the package.", + "ExternalRef: OTHER LocationRef-acmeforge acmecorp/acmenator/4.1.3-alpha", + "PrimaryPackagePurpose: OPERATING-SYSTEM", + "BuiltDate: 2020-01-01T12:00:00Z", + "ReleaseDate: 2021-01-01T12:00:00Z", + "ValidUntilDate: 2022-01-01T12:00:00Z", + ] + ) + document = parser.parse("\n".join([DOCUMENT_STR, package_str])) + assert document is not None + package = document.packages[0] + assert package.name == "Test" + assert package.spdx_id == "SPDXRef-Package" + assert package.version == "1:22.36.1-8+deb11u1" + assert len(package.license_info_from_files) == 3 + TestCase().assertCountEqual( + package.license_info_from_files, + [spdx_licensing.parse("Apache-1.0"), spdx_licensing.parse("Apache-2.0"), SpdxNone()], + ) + assert package.license_concluded == spdx_licensing.parse("LicenseRef-2.0 AND Apache-2.0") + assert package.files_analyzed is True + assert package.comment == "Comment on the package." + assert len(package.external_references) == 2 + TestCase().assertCountEqual( + package.external_references, + [ + ExternalPackageRef( + ExternalPackageRefCategory.SECURITY, + "cpe23Type", + "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", + "Some comment about the package.", + ), + ExternalPackageRef( + ExternalPackageRefCategory.OTHER, "LocationRef-acmeforge", "acmecorp/acmenator/4.1.3-alpha" + ), + ], + ) + assert package.primary_package_purpose == PackagePurpose.OPERATING_SYSTEM + assert package.built_date == datetime(2020, 1, 1, 12) + assert package.release_date == datetime(2021, 1, 1, 12) + assert package.valid_until_date == datetime(2022, 1, 1, 12) + + +@pytest.mark.parametrize( + "package_str, expected_message", + [ + ( + "PackageDownloadLocation: SPDXRef-Package", + "Element Package is not the current element in scope, probably the expected " + "tag to start the element (PackageName) is missing. Line: 1", + ), + ( + "PackageName: TestPackage", + r"__init__() missing 2 required positional arguments: 'spdx_id' and 'download_location'", + ), + ( + "PackageName: TestPackage\nPackageCopyrightText:This is a copyright\n" + "PackageCopyrightText:MultipleCopyright", + "Error while parsing Package: ['Multiple values for PackageCopyrightText " "found. Line: 3']", + ), + ( + "PackageName: TestPackage\nExternalRef: reference locator", + ( + "Error while parsing Package: [\"Couldn't split PackageExternalRef in category, " + 'reference_type and locator. Line: 2"]' + ), + ), + ( + "PackageName: TestPackage\nExternalRef: category reference locator", + "Error while parsing Package: ['Invalid ExternalPackageRefCategory: " "category. Line: 2']", + ), + ( + f"SPDXID:{DOCUMENT_SPDX_ID}\nPackageName: TestPackage\nSPDXID:SPDXRef-Package\n" + "PackageDownloadLocation: download.com\nPackageVerificationCode: category reference locator", + "Error while parsing Package: ['Error while parsing PackageVerificationCode: " + "Value did not match expected format. Line: 5']", + ), + ( + "PackageName: TestPackage\nBuiltDate: 2012\nValidUntilDate:202-11-02T00:00", + "Error while parsing Package: ['Error while parsing BuiltDate: Token did not " + "match specified grammar rule. Line: 2', 'Error while parsing " + "ValidUntilDate: Token did not match specified grammar rule. Line: 3']", + ), + ( + f"SPDXID:{DOCUMENT_SPDX_ID}\nPackageName: TestPackage\nSPDXID:SPDXRef-Package\n" + "PackageDownloadLocation: download.com\nFilesAnalyzed: FALSE", + "Error while parsing Package: " + '[\'The value of FilesAnalyzed must be either "true" or "false", but is: FALSE\']', + ), + ], +) +def test_parse_invalid_package(package_str, expected_message): + parser = Parser() + + with pytest.raises(SPDXParsingError) as err: + parser.parse(package_str) + + assert expected_message in err.value.get_messages()[0] diff --git a/tests/spdx/parser/tagvalue/test_relationship_parser.py b/tests/spdx/parser/tagvalue/test_relationship_parser.py new file mode 100644 index 000000000..d351a0c06 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_relationship_parser.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser +from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR + + +@pytest.mark.parametrize( + "relationship_str, expected_relationship", + [ + ( + "\n".join( + [f"Relationship: {DOCUMENT_SPDX_ID} DESCRIBES SPDXRef-File", "RelationshipComment: This is a comment."] + ), + Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-File", "This is a comment."), + ), + ( + f"Relationship: {DOCUMENT_SPDX_ID} PATCH_FOR NOASSERTION", + Relationship(DOCUMENT_SPDX_ID, RelationshipType.PATCH_FOR, SpdxNoAssertion()), + ), + ( + "Relationship: SPDXRef-CarolCompression DEPENDS_ON NONE", + Relationship("SPDXRef-CarolCompression", RelationshipType.DEPENDS_ON, SpdxNone()), + ), + ( + "Relationship: DocumentRef-ExternalDocument:SPDXRef-Test DEPENDS_ON DocumentRef:AnotherRef", + Relationship( + "DocumentRef-ExternalDocument:SPDXRef-Test", RelationshipType.DEPENDS_ON, "DocumentRef:AnotherRef" + ), + ), + ], +) +def test_parse_relationship(relationship_str, expected_relationship): + parser = Parser() + document = parser.parse("\n".join([DOCUMENT_STR, relationship_str])) + assert document is not None + assert len(document.relationships) == 1 + relationship = document.relationships[0] + assert relationship == expected_relationship + + +@pytest.mark.parametrize( + "relationship_str, expected_message", + [ + ( + "Relationship: spdx_id DESCRIBES", + [ + "Error while parsing Relationship: [\"Relationship couldn't be split in " + 'spdx_element_id, relationship_type and related_spdx_element. Line: 1"]' + ], + ), + ( + "Relationship: spdx_id IS spdx_id", + ["Error while parsing Relationship: ['Invalid RelationshipType IS. Line: 1']"], + ), + ], +) +def test_parse_invalid_relationship(relationship_str, expected_message): + parser = Parser() + with pytest.raises(SPDXParsingError) as err: + parser.parse(relationship_str) + + assert err.value.get_messages() == expected_message diff --git a/tests/spdx/parser/tagvalue/test_snippet_parser.py b/tests/spdx/parser/tagvalue/test_snippet_parser.py new file mode 100644 index 000000000..79d5de670 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_snippet_parser.py @@ -0,0 +1,88 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser +from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR + + +def test_parse_snippet(): + parser = Parser() + snippet_str = "\n".join( + [ + "SnippetSPDXID: SPDXRef-Snippet", + "SnippetLicenseComments: Some lic comment.", + "SnippetCopyrightText: Copyright 2008-2010 John Smith ", + "SnippetComment: Some snippet comment.", + "SnippetName: from linux kernel", + "SnippetFromFileSPDXID: SPDXRef-DoapSource", + "SnippetLicenseConcluded: Apache-2.0", + "LicenseInfoInSnippet: NOASSERTION", + "SnippetByteRange: 310:420", + "SnippetLineRange: 5:23", + "SnippetAttributionText: This is a text\nthat spans multiple lines.", + "SnippetAttributionText: This text spans one line but has trailing and leading whitespaces. ", + ] + ) + + document = parser.parse("\n".join([DOCUMENT_STR, snippet_str])) + assert document is not None + assert len(document.snippets) == 1 + snippet = document.snippets[0] + assert snippet.spdx_id == "SPDXRef-Snippet" + assert snippet.name == "from linux kernel" + assert snippet.comment == "Some snippet comment." + assert snippet.copyright_text == " Copyright 2008-2010 John Smith " + assert snippet.license_comment == "Some lic comment." + assert snippet.file_spdx_id == "SPDXRef-DoapSource" + assert snippet.license_concluded == spdx_licensing.parse("Apache-2.0") + assert snippet.license_info_in_snippet == [SpdxNoAssertion()] + assert snippet.byte_range[0] == 310 + assert snippet.byte_range[1] == 420 + assert snippet.line_range[0] == 5 + assert snippet.line_range[1] == 23 + TestCase().assertCountEqual( + snippet.attribution_texts, + [ + "This is a text\nthat spans multiple lines.", + "This text spans one line but has trailing and leading whitespaces.", + ], + ) + + +@pytest.mark.parametrize( + "snippet_str, expected_message", + [ + ( + "SnippetName: TestSnippet", + "Element Snippet is not the current element in scope, probably the expected " + "tag to start the element (SnippetSPDXID) is missing. Line: 1", + ), + ( + "SnippetSPDXID: SPDXDRef-Snippet\nSnippetByteRange: 1,4", + "Error while parsing Snippet: [\"Value for SnippetByteRange doesn't match " + 'valid range pattern. Line: 2"]', + ), + ( + "SnippetSPDXID: SPDXDRef-Snippet\nSnippetByteRange: 1:4\nSnippetByteRange:10:23", + "Error while parsing Snippet: ['Multiple values for SnippetByteRange found. " "Line: 3']", + ), + ( + "SnippetSPDXID: SPDXRef-Snippet", + r"__init__() missing 2 required " r"positional arguments: 'file_spdx_id' and 'byte_range'", + ), + ], +) +def test_parse_invalid_snippet(snippet_str, expected_message): + parser = Parser() + + with pytest.raises(SPDXParsingError) as err: + parser.parse(snippet_str) + + assert expected_message in err.value.get_messages()[0] diff --git a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py new file mode 100644 index 000000000..c61ee6200 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py @@ -0,0 +1,321 @@ +# Copyright (c) 2014 Ahmed H. Ismail +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.parser.tagvalue.lexer import SPDXLexer + + +@pytest.fixture +def lexer(): + lexer = SPDXLexer() + lexer.build() + return lexer + + +def token_assert_helper(token, token_type, value, line_number): + assert token.type == token_type + assert token.value == value + assert token.lineno == line_number + + +def test_tokenization_of_document(lexer): + document_str = "\n".join( + [ + "SPDXVersion: SPDX-2.1", + "DataLicense: CC0-1.0", + "DocumentName: Sample_Document-V2.1", + f"SPDXID: {DOCUMENT_SPDX_ID}", + "DocumentComment: Sample Comment", + "DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", + ] + ) + lexer.input(document_str) + token_assert_helper(lexer.token(), "DOC_VERSION", "SPDXVersion", 1) + token_assert_helper(lexer.token(), "LINE", "SPDX-2.1", 1) + token_assert_helper(lexer.token(), "DOC_LICENSE", "DataLicense", 2) + token_assert_helper(lexer.token(), "LINE", "CC0-1.0", 2) + token_assert_helper(lexer.token(), "DOC_NAME", "DocumentName", 3) + token_assert_helper(lexer.token(), "LINE", "Sample_Document-V2.1", 3) + token_assert_helper(lexer.token(), "SPDX_ID", "SPDXID", 4) + token_assert_helper(lexer.token(), "LINE", DOCUMENT_SPDX_ID, 4) + token_assert_helper(lexer.token(), "DOC_COMMENT", "DocumentComment", 5) + token_assert_helper(lexer.token(), "TEXT", "Sample Comment", 5) + token_assert_helper(lexer.token(), "DOC_NAMESPACE", "DocumentNamespace", 6) + token_assert_helper( + lexer.token(), "LINE", "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", 6 + ) + + +def test_tokenization_of_external_document_references(lexer): + data = "\n".join( + [ + "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3" + "-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one " + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ] + ) + lexer.input(data) + token_assert_helper(lexer.token(), "EXT_DOC_REF", "ExternalDocumentRef", 1) + token_assert_helper( + lexer.token(), + "LINE", + "DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 " + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + 1, + ) + token_assert_helper(lexer.token(), "EXT_DOC_REF", "ExternalDocumentRef", 2) + token_assert_helper( + lexer.token(), + "LINE", + "DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one " + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + 2, + ) + + +def test_tokenization_of_file(lexer): + file_str = "\n".join( + [ + "FileName: testfile.java", + "SPDXID: SPDXRef-File", + "FileType: SOURCE", + "FileType: TEXT", + "FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "LicenseConcluded: Apache-2.0", + "LicenseInfoInFile: Apache-2.0", + "FileCopyrightText: Copyright 2014 Acme Inc.", + "FileComment: Very long file", + "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts." + "", + ] + ) + + lexer.input(file_str) + token_assert_helper(lexer.token(), "FILE_NAME", "FileName", 1) + token_assert_helper(lexer.token(), "LINE", "testfile.java", 1) + token_assert_helper(lexer.token(), "SPDX_ID", "SPDXID", 2) + token_assert_helper(lexer.token(), "LINE", "SPDXRef-File", 2) + token_assert_helper(lexer.token(), "FILE_TYPE", "FileType", 3) + token_assert_helper(lexer.token(), "LINE", "SOURCE", 3) + token_assert_helper(lexer.token(), "FILE_TYPE", "FileType", 4) + token_assert_helper(lexer.token(), "LINE", "TEXT", 4) + token_assert_helper(lexer.token(), "FILE_CHECKSUM", "FileChecksum", 5) + token_assert_helper(lexer.token(), "CHECKSUM", "SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", 5) + token_assert_helper(lexer.token(), "FILE_LICENSE_CONCLUDED", "LicenseConcluded", 6) + token_assert_helper(lexer.token(), "LINE", "Apache-2.0", 6) + token_assert_helper(lexer.token(), "FILE_LICENSE_INFO", "LicenseInfoInFile", 7) + token_assert_helper(lexer.token(), "LINE", "Apache-2.0", 7) + token_assert_helper(lexer.token(), "FILE_COPYRIGHT_TEXT", "FileCopyrightText", 8) + token_assert_helper(lexer.token(), "TEXT", "Copyright 2014 Acme Inc.", 8) + token_assert_helper(lexer.token(), "FILE_COMMENT", "FileComment", 9) + token_assert_helper(lexer.token(), "TEXT", "Very long file", 9) + token_assert_helper(lexer.token(), "FILE_ATTRIBUTION_TEXT", "FileAttributionText", 10) + token_assert_helper( + lexer.token(), + "TEXT", + "Acknowledgements that might be required to be communicated in some contexts.", + 10, + ) + + +def test_tokenization_of_creation_info(lexer): + creation_str = "\n".join( + [ + "Creator: Person: Bob (bob@example.com)", + "Creator: Organization: Acme.", + "Created: 2010-02-03T00:00:00Z", + "CreatorComment: Sample Comment", + ] + ) + + lexer.input(creation_str) + token_assert_helper(lexer.token(), "CREATOR", "Creator", 1) + token_assert_helper(lexer.token(), "PERSON_VALUE", "Person: Bob (bob@example.com)", 1) + token_assert_helper(lexer.token(), "CREATOR", "Creator", 2) + token_assert_helper(lexer.token(), "ORGANIZATION_VALUE", "Organization: Acme.", 2) + token_assert_helper(lexer.token(), "CREATED", "Created", 3) + token_assert_helper(lexer.token(), "ISO8601_DATE", "2010-02-03T00:00:00Z", 3) + token_assert_helper(lexer.token(), "CREATOR_COMMENT", "CreatorComment", 4) + token_assert_helper(lexer.token(), "TEXT", "Sample Comment", 4) + + +def test_tokenization_of_package(lexer): + package_str = "\n".join( + [ + "PackageName: Test", + "SPDXID: SPDXRef-Package", + "PackageVersion: Version 0.9.2", + "PackageDownloadLocation: http://example.com/test", + "FilesAnalyzed: True", + "PackageSummary: Test package", + "PackageSourceInfo: Version 1.0 of test", + "PackageFileName: test-1.0.zip", + "PackageSupplier: Organization:ACME", + "PackageOriginator: Organization:ACME", + "PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)", + "PackageDescription: A package.", + "PackageComment: Comment on the package.", + "PackageCopyrightText: Copyright 2014 Acme Inc.", + "PackageLicenseDeclared: Apache-2.0", + "PackageLicenseConcluded: (LicenseRef-2.0 and Apache-2.0)", + "PackageLicenseInfoFromFiles: Apache-1.0", + "PackageLicenseInfoFromFiles: Apache-2.0", + "PackageLicenseComments: License Comments", + "ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", + "ExternalRefComment: Some comment about the package.", + "PrimaryPackagePurpose: OPERATING-SYSTEM", + "BuiltDate: 2020-01-01T12:00:00Z", + "ReleaseDate: 2021-01-01T12:00:00Z", + "ValidUntilDate: 2022-01-01T12:00:00Z", + ] + ) + + lexer.input(package_str) + token_assert_helper(lexer.token(), "PKG_NAME", "PackageName", 1) + token_assert_helper(lexer.token(), "LINE", "Test", 1) + token_assert_helper(lexer.token(), "SPDX_ID", "SPDXID", 2) + token_assert_helper(lexer.token(), "LINE", "SPDXRef-Package", 2) + token_assert_helper(lexer.token(), "PKG_VERSION", "PackageVersion", 3) + token_assert_helper(lexer.token(), "LINE", "Version 0.9.2", 3) + token_assert_helper(lexer.token(), "PKG_DOWNLOAD_LOCATION", "PackageDownloadLocation", 4) + token_assert_helper(lexer.token(), "LINE", "http://example.com/test", 4) + token_assert_helper(lexer.token(), "PKG_FILES_ANALYZED", "FilesAnalyzed", 5) + token_assert_helper(lexer.token(), "LINE", "True", 5) + token_assert_helper(lexer.token(), "PKG_SUMMARY", "PackageSummary", 6) + token_assert_helper(lexer.token(), "TEXT", "Test package", 6) + token_assert_helper(lexer.token(), "PKG_SOURCE_INFO", "PackageSourceInfo", 7) + token_assert_helper(lexer.token(), "TEXT", "Version 1.0 of test", 7) + token_assert_helper(lexer.token(), "PKG_FILE_NAME", "PackageFileName", 8) + token_assert_helper(lexer.token(), "LINE", "test-1.0.zip", 8) + token_assert_helper(lexer.token(), "PKG_SUPPLIER", "PackageSupplier", 9) + token_assert_helper(lexer.token(), "ORGANIZATION_VALUE", "Organization:ACME", 9) + token_assert_helper(lexer.token(), "PKG_ORIGINATOR", "PackageOriginator", 10) + token_assert_helper(lexer.token(), "ORGANIZATION_VALUE", "Organization:ACME", 10) + token_assert_helper(lexer.token(), "PKG_CHECKSUM", "PackageChecksum", 11) + token_assert_helper(lexer.token(), "CHECKSUM", "SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", 11) + token_assert_helper(lexer.token(), "PKG_VERIFICATION_CODE", "PackageVerificationCode", 12) + token_assert_helper( + lexer.token(), "LINE", "4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)", 12 + ) + token_assert_helper(lexer.token(), "PKG_DESCRIPTION", "PackageDescription", 13) + token_assert_helper(lexer.token(), "TEXT", "A package.", 13) + token_assert_helper(lexer.token(), "PKG_COMMENT", "PackageComment", 14) + token_assert_helper(lexer.token(), "TEXT", "Comment on the package.", 14) + token_assert_helper(lexer.token(), "PKG_COPYRIGHT_TEXT", "PackageCopyrightText", 15) + token_assert_helper(lexer.token(), "TEXT", " Copyright 2014 Acme Inc.", 15) + token_assert_helper(lexer.token(), "PKG_LICENSE_DECLARED", "PackageLicenseDeclared", 16) + token_assert_helper(lexer.token(), "LINE", "Apache-2.0", 16) + token_assert_helper(lexer.token(), "PKG_LICENSE_CONCLUDED", "PackageLicenseConcluded", 17) + token_assert_helper(lexer.token(), "LINE", "(LicenseRef-2.0 and Apache-2.0)", 17) + token_assert_helper(lexer.token(), "PKG_LICENSE_INFO", "PackageLicenseInfoFromFiles", 18) + token_assert_helper(lexer.token(), "LINE", "Apache-1.0", 18) + token_assert_helper(lexer.token(), "PKG_LICENSE_INFO", "PackageLicenseInfoFromFiles", 19) + token_assert_helper(lexer.token(), "LINE", "Apache-2.0", 19) + token_assert_helper(lexer.token(), "PKG_LICENSE_COMMENT", "PackageLicenseComments", 20) + token_assert_helper(lexer.token(), "TEXT", "License Comments", 20) + token_assert_helper(lexer.token(), "PKG_EXTERNAL_REF", "ExternalRef", 21) + token_assert_helper( + lexer.token(), "LINE", "SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", 21 + ) + token_assert_helper(lexer.token(), "PKG_EXTERNAL_REF_COMMENT", "ExternalRefComment", 22) + token_assert_helper(lexer.token(), "TEXT", "Some comment about the package.", 22) + token_assert_helper(lexer.token(), "PRIMARY_PACKAGE_PURPOSE", "PrimaryPackagePurpose", 23) + token_assert_helper(lexer.token(), "LINE", "OPERATING-SYSTEM", 23) + token_assert_helper(lexer.token(), "BUILT_DATE", "BuiltDate", 24) + token_assert_helper(lexer.token(), "ISO8601_DATE", "2020-01-01T12:00:00Z", 24) + token_assert_helper(lexer.token(), "RELEASE_DATE", "ReleaseDate", 25) + token_assert_helper(lexer.token(), "ISO8601_DATE", "2021-01-01T12:00:00Z", 25) + token_assert_helper(lexer.token(), "VALID_UNTIL_DATE", "ValidUntilDate", 26) + token_assert_helper(lexer.token(), "ISO8601_DATE", "2022-01-01T12:00:00Z", 26) + + +def test_tokenization_of_unknown_tag(lexer): + unknown_tag_str = "SomeUnknownTag: SomeUnknownValue" + lexer.input(unknown_tag_str) + token_assert_helper(lexer.token(), "UNKNOWN_TAG", "SomeUnknownTag", 1) + token_assert_helper(lexer.token(), "LINE", "SomeUnknownValue", 1) + + +def test_tokenization_of_snippet(lexer): + snippet_str = "\n".join( + [ + "SnippetSPDXID: SPDXRef-Snippet", + "SnippetLicenseComments: Some lic comment.", + "SnippetCopyrightText: Copyright 2008-2010 John Smith ", + "SnippetComment: Some snippet comment.", + "SnippetName: from linux kernel", + "SnippetFromFileSPDXID: SPDXRef-DoapSource", + "SnippetLicenseConcluded: Apache-2.0", + "LicenseInfoInSnippet: Apache-2.0", + "SnippetByteRange: 310:420", + "SnippetLineRange: 5:23", + ] + ) + lexer.input(snippet_str) + token_assert_helper(lexer.token(), "SNIPPET_SPDX_ID", "SnippetSPDXID", 1) + token_assert_helper(lexer.token(), "LINE", "SPDXRef-Snippet", 1) + token_assert_helper(lexer.token(), "SNIPPET_LICENSE_COMMENT", "SnippetLicenseComments", 2) + token_assert_helper(lexer.token(), "TEXT", "Some lic comment.", 2) + token_assert_helper(lexer.token(), "SNIPPET_COPYRIGHT_TEXT", "SnippetCopyrightText", 3) + token_assert_helper(lexer.token(), "TEXT", " Copyright 2008-2010 John Smith ", 3) + token_assert_helper(lexer.token(), "SNIPPET_COMMENT", "SnippetComment", 4) + token_assert_helper(lexer.token(), "TEXT", "Some snippet comment.", 4) + token_assert_helper(lexer.token(), "SNIPPET_NAME", "SnippetName", 5) + token_assert_helper(lexer.token(), "LINE", "from linux kernel", 5) + token_assert_helper(lexer.token(), "SNIPPET_FILE_SPDXID", "SnippetFromFileSPDXID", 6) + token_assert_helper(lexer.token(), "LINE", "SPDXRef-DoapSource", 6) + token_assert_helper(lexer.token(), "SNIPPET_LICENSE_CONCLUDED", "SnippetLicenseConcluded", 7) + token_assert_helper(lexer.token(), "LINE", "Apache-2.0", 7) + token_assert_helper(lexer.token(), "SNIPPET_LICENSE_INFO", "LicenseInfoInSnippet", 8) + token_assert_helper(lexer.token(), "LINE", "Apache-2.0", 8) + token_assert_helper(lexer.token(), "SNIPPET_BYTE_RANGE", "SnippetByteRange", 9) + token_assert_helper(lexer.token(), "LINE", "310:420", 9) + token_assert_helper(lexer.token(), "SNIPPET_LINE_RANGE", "SnippetLineRange", 10) + token_assert_helper(lexer.token(), "LINE", "5:23", 10) + + +def test_tokenization_of_annotation(lexer): + annotation_str = "\n".join( + [ + "Annotator: Person: Jane Doe()", + "AnnotationDate: 2010-01-29T18:30:22Z", + "AnnotationComment: Document level annotation", + "AnnotationType: OTHER", + f"SPDXREF: {DOCUMENT_SPDX_ID}", + ] + ) + + lexer.input(annotation_str) + token_assert_helper(lexer.token(), "ANNOTATOR", "Annotator", 1) + token_assert_helper(lexer.token(), "PERSON_VALUE", "Person: Jane Doe()", 1) + token_assert_helper(lexer.token(), "ANNOTATION_DATE", "AnnotationDate", 2) + token_assert_helper(lexer.token(), "ISO8601_DATE", "2010-01-29T18:30:22Z", 2) + token_assert_helper(lexer.token(), "ANNOTATION_COMMENT", "AnnotationComment", 3) + token_assert_helper(lexer.token(), "TEXT", "Document level annotation", 3) + token_assert_helper(lexer.token(), "ANNOTATION_TYPE", "AnnotationType", 4) + token_assert_helper(lexer.token(), "LINE", "OTHER", 4) + token_assert_helper(lexer.token(), "ANNOTATION_SPDX_ID", "SPDXREF", 5) + token_assert_helper(lexer.token(), "LINE", DOCUMENT_SPDX_ID, 5) + + +def test_tokenization_of_relationship(lexer): + relationship_str = "\n".join( + [ + f"Relationship: {DOCUMENT_SPDX_ID} DESCRIBES NONE", + "RelationshipComment: This is a comment.", + "Relationship: DocumentRef-extern:SPDXRef-Package DESCRIBES NONE", + ] + ) + + lexer.input(relationship_str) + token_assert_helper(lexer.token(), "RELATIONSHIP", "Relationship", 1) + token_assert_helper(lexer.token(), "LINE", f"{DOCUMENT_SPDX_ID} DESCRIBES NONE", 1) + token_assert_helper(lexer.token(), "RELATIONSHIP_COMMENT", "RelationshipComment", 2) + token_assert_helper(lexer.token(), "LINE", "This is a comment.", 2) + token_assert_helper(lexer.token(), "RELATIONSHIP", "Relationship", 3) + token_assert_helper(lexer.token(), "LINE", "DocumentRef-extern:SPDXRef-Package DESCRIBES NONE", 3) diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py new file mode 100644 index 000000000..c866e2726 --- /dev/null +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -0,0 +1,164 @@ +# Copyright (c) 2014 Ahmed H. Ismail +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser +from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR + + +def test_parse_unknown_tag(): + parser = Parser() + unknown_tag_str = "UnknownTag: This is an example for an unknown tag." + + with pytest.raises(SPDXParsingError, match="Unknown tag"): + parser.parse(unknown_tag_str) + + +def test_building_contains_relationship(): + parser = Parser() + document_str = "\n".join( + [ + DOCUMENT_STR, + "FileName: File without package", + "SPDXID: SPDXRef-File", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "PackageName: Package with two files", + "SPDXID: SPDXRef-Package-with-two-files", + "PackageDownloadLocation: https://download.com", + "FileName: File in package", + "SPDXID: SPDXRef-File-in-Package", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "FileName: Second file in package", + "SPDXID: SPDXRef-Second-File-in-Package", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "PackageName: Second package with file", + "SPDXID: SPDXRef-Package-with-one-file", + "PackageDownloadLocation: https://download.com", + "FileName: File in package", + "SPDXID: SPDXRef-File-in-different-Package", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ] + ) + document = parser.parse(document_str) + + assert document.relationships == [ + Relationship("SPDXRef-Package-with-two-files", RelationshipType.CONTAINS, "SPDXRef-File-in-Package"), + Relationship("SPDXRef-Package-with-two-files", RelationshipType.CONTAINS, "SPDXRef-Second-File-in-Package"), + Relationship("SPDXRef-Package-with-one-file", RelationshipType.CONTAINS, "SPDXRef-File-in-different-Package"), + ] + + +def test_build_contains_relationship_with_error(): + parser = Parser() + file_spdx_ids = ["SPDXRef-File-in-Package", "SPDXRef-Second-File-in-Package"] + document_str = "\n".join( + [ + DOCUMENT_STR, + "PackageName: Package with two files", + "PackageDownloadLocation: https://download.com", + "FileName: File in package", + f"SPDXID: {file_spdx_ids[0]}", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "FileName: Second file in package", + f"SPDXID: {file_spdx_ids[1]}", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ] + ) + with pytest.raises(SPDXParsingError) as err: + parser.parse(document_str) + for file_spdx_id in file_spdx_ids: + assert ( + f"Error while building contains relationship for file {file_spdx_id}, preceding package was not " + "parsed successfully." in err.value.get_messages() + ) + + +def test_document_with_mixed_values(): + parser = Parser() + document_str = "\n".join( + [ + f"SPDXID:{DOCUMENT_SPDX_ID}", + "FileName: File without package", + "SPDXID: SPDXRef-File", + "PackageDownloadLocation: https://download.com", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ] + ) + + with pytest.raises(SPDXParsingError) as err: + parser.parse(document_str) + + assert err.value.get_messages() == [ + "Element Package is not the current element in scope, probably the expected " + "tag to start the element (PackageName) is missing. Line: 4" + ] + + +def test_faulty_license_expression(): + parser = Parser() + document_str = "\n".join( + [ + f"SPDXID:{DOCUMENT_SPDX_ID}", + "FileName: File with faulty license expression", + "SPDXID: SPDXRef-File", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "LicenseConcluded: LicenseRef-foo/bar", + "PackageName: Package with faulty license expression", + "SPDXID: SPDXRef-Package", + "PackageDownloadLocation: www.download.com", + "PackageLicenseConcluded: LicenseRef-bar/foo", + "SnippetSPDXID: SPDXRef-Snippet", + "SnippetName: Snippet with faulty license expression", + "SnippetLicenseConcluded: LicenseRef-foo/foo", + ] + ) + + with pytest.raises(SPDXParsingError) as err: + parser.parse(document_str) + + assert err.value.get_messages() == [ + 'Error while parsing File: ["Error while parsing license expression: ' + "LicenseRef-foo/bar: Invalid license key: the valid characters are: letters " + "and numbers, underscore, dot, colon or hyphen signs and spaces: " + "'LicenseRef-foo/bar'\"]", + 'Error while parsing Package: ["Error while parsing license expression: ' + "LicenseRef-bar/foo: Invalid license key: the valid characters are: letters " + "and numbers, underscore, dot, colon or hyphen signs and spaces: " + "'LicenseRef-bar/foo'\"]", + 'Error while parsing Snippet: ["Error while parsing license expression: ' + "LicenseRef-foo/foo: Invalid license key: the valid characters are: letters " + "and numbers, underscore, dot, colon or hyphen signs and spaces: " + "'LicenseRef-foo/foo'\"]", + ] + + +def test_parse_none_or_no_assertion_as_text(): + parser = Parser() + document_str = "\n".join( + [ + DOCUMENT_STR, + "PackageName: Test", + "SPDXID: SPDXRef-Package", + "PackageDownloadLocation: http://example.com/test", + "FilesAnalyzed: true", + "PackageSummary: NONE", + "PackageSourceInfo: NOASSERTION", + "PackageLicenseConcluded: NONE", + "PackageLicenseDeclared: NOASSERTION", + ] + ) + document = parser.parse(document_str) + assert document is not None + package = document.packages[0] + assert package.name == "Test" + assert package.spdx_id == "SPDXRef-Package" + assert package.source_info == "NOASSERTION" + assert package.summary == "NONE" + assert package.license_concluded == SpdxNone() + assert package.license_declared == SpdxNoAssertion() diff --git a/tests/spdx/test_actor_parser.py b/tests/spdx/test_actor_parser.py new file mode 100644 index 000000000..24002794c --- /dev/null +++ b/tests/spdx/test_actor_parser.py @@ -0,0 +1,65 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.model import ActorType +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError + + +@pytest.mark.parametrize( + "actor_string,expected_type,expected_name,expected_mail", + [ + ("Person: Jane Doe (jane.doe@example.com)", ActorType.PERSON, "Jane Doe", "jane.doe@example.com"), + ( + "Organization: Example organization (organization@example.com)", + ActorType.ORGANIZATION, + "Example organization", + "organization@example.com", + ), + ("Organization: Example organization ( )", ActorType.ORGANIZATION, "Example organization", None), + ("Person: Example person ()", ActorType.PERSON, "Example person", None), + ("Person: Example person ", ActorType.PERSON, "Example person", None), + ("Tool: Example tool ", ActorType.TOOL, "Example tool", None), + ("Tool: Example tool (email@mail.com)", ActorType.TOOL, "Example tool (email@mail.com)", None), + ( + "Organization: (c) Chris Sainty (chris@sainty.com)", + ActorType.ORGANIZATION, + "(c) Chris Sainty", + "chris@sainty.com", + ), + ], +) +def test_parse_actor(actor_string, expected_type, expected_name, expected_mail): + actor_parser = ActorParser() + + actor = actor_parser.parse_actor(actor_string) + + assert actor.actor_type == expected_type + assert actor.name == expected_name + assert actor.email == expected_mail + + +@pytest.mark.parametrize( + "actor_string,expected_message", + [ + ( + "Perso: Jane Doe (jane.doe@example.com)", + ["Actor Perso: Jane Doe (jane.doe@example.com) doesn't match any of person, organization or tool."], + ), + ("Toole Example Tool ()", ["Actor Toole Example Tool () doesn't match any of person, organization or tool."]), + ("Organization:", ["No name for Actor provided: Organization:."]), + ("Person: ( )", ["No name for Actor provided: Person: ( )."]), + ], +) +def test_parse_invalid_actor(actor_string, expected_message): + actor_parser = ActorParser() + actor_string = actor_string + + with pytest.raises(SPDXParsingError) as err: + actor_parser.parse_actor(actor_string) + + TestCase().assertCountEqual(err.value.get_messages(), expected_message) diff --git a/tests/spdx/test_casing_tools.py b/tests/spdx/test_casing_tools.py new file mode 100644 index 000000000..928935e94 --- /dev/null +++ b/tests/spdx/test_casing_tools.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.casing_tools import camel_case_to_snake_case, snake_case_to_camel_case + + +@pytest.mark.parametrize("snake_case_str,camel_case_str", [("snake_case", "snakeCase")]) +def test_snake_case_to_camel_case(snake_case_str, camel_case_str): + camel_case = snake_case_to_camel_case(snake_case_str) + + assert camel_case == camel_case_str + + +@pytest.mark.parametrize( + "camel_case_str,snake_case_str", + [("camelCase", "camel_case"), ("camelCaseMore", "camel_case_more"), ("CamelCase", "camel_case")], +) +def test_camel_case_to_snake_case(camel_case_str, snake_case_str): + snake_case = camel_case_to_snake_case(camel_case_str) + + assert snake_case == snake_case_str diff --git a/tests/spdx/test_checksum_calculation.py b/tests/spdx/test_checksum_calculation.py new file mode 100644 index 000000000..0e45b11c9 --- /dev/null +++ b/tests/spdx/test_checksum_calculation.py @@ -0,0 +1,76 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, File, PackageVerificationCode +from spdx_tools.spdx.spdx_element_utils import calculate_file_checksum, calculate_package_verification_code + + +@pytest.fixture +def generate_test_files(tmp_path): + file_path_1 = tmp_path.joinpath("file1") + file_path_2 = tmp_path.joinpath("file2") + + with open(file_path_1, "wb") as file: + file.write(bytes(111)) + with open(file_path_2, "wb") as file: + file.write(bytes(222)) + + yield str(file_path_1), str(file_path_2) + + +def test_file_checksum_calculation(generate_test_files): + filepath1, filepath2 = generate_test_files + checksum = calculate_file_checksum(filepath1, ChecksumAlgorithm.SHA1) + assert checksum == "dd90903d2f566a3922979dd5e18378a075c7ed33" + checksum = calculate_file_checksum(filepath2, ChecksumAlgorithm.SHA1) + assert checksum == "140dc52658e2eeee3fdc4d471cce84fec7253fe3" + + +def test_verification_code_calculation_with_predefined_checksums(generate_test_files): + filepath1, filepath2 = generate_test_files + file1 = File( + filepath1, + "SPDXRef-hello", + [Checksum(ChecksumAlgorithm.SHA1, "20862a6d08391d07d09344029533ec644fac6b21")], + ) + file2 = File( + filepath2, + "SPDXRef-Makefile", + [Checksum(ChecksumAlgorithm.SHA1, "69a2e85696fff1865c3f0686d6c3824b59915c80")], + ) + verification_code = calculate_package_verification_code([file1, file2]) + + assert verification_code == PackageVerificationCode("c6cb0949d7cd7439fce8690262a0946374824639") + + +def test_verification_code_calculation_with_calculated_checksums(generate_test_files): + filepath1, filepath2 = generate_test_files + file1 = File( + filepath1, + "SPDXRef-hello", + [Checksum(ChecksumAlgorithm.MD4, "20862a6d08391d07d09344029533ec644fac6b21")], + ) + file2 = File( + filepath2, + "SPDXRef-Makefile", + [Checksum(ChecksumAlgorithm.MD4, "69a2e85696fff1865c3f0686d6c3824b59915c80")], + ) + verification_code = calculate_package_verification_code([file1, file2]) + + assert verification_code == PackageVerificationCode("6f29d813abb63ee52a47dbcb691ea2e70f956328") + + +def test_verification_code_calculation_with_wrong_file_location(): + unknown_file_name = "./unknown_file_name" + file1 = File( + unknown_file_name, + "SPDXRef-unknown", + [Checksum(ChecksumAlgorithm.MD4, "20862a6d08391d07d09344029533ec644fac6b21")], + ) + + with pytest.raises(FileNotFoundError) as err: + calculate_package_verification_code([file1]) + + assert unknown_file_name in str(err.value) diff --git a/tests/spdx/test_cli.py b/tests/spdx/test_cli.py new file mode 100644 index 000000000..0019cf3a3 --- /dev/null +++ b/tests/spdx/test_cli.py @@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os + +import pytest +from click.testing import CliRunner + +from spdx_tools.spdx.clitools.pyspdxtools import main + + +@pytest.mark.parametrize( + "options", + [ + ("--infile", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json")), + ("-i", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), "--novalidation"), + ( + "-i", + os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), + "--novalidation", + "--version", + "SPDX-2.3", + ), + ("-i", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), "-o", "-"), + ], +) +def test_cli_with_system_exit_code_0(options): + runner = CliRunner() + + result = runner.invoke(main, options) + + assert result.exit_code == 0 + + +@pytest.mark.parametrize( + "options", + [ + ( + "-i", + os.path.join( + os.path.dirname(__file__), + "data/invalid/spdx-trivy-vmware_log-intelligence-fluentd-sha256_086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a.json", # noqa: E501 + ), + ), + ("-i", "non_existent_file.spdx"), + ], +) +def test_cli_with_system_exit_code_1(options): + runner = CliRunner() + + result = runner.invoke(main, options) + + assert result.exit_code == 1 + + +@pytest.mark.parametrize( + "options", + [ + (), + ("-i", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), "--version"), + ("-i", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), "-o"), + ], +) +def test_cli_with_system_exit_code_2(options): + runner = CliRunner() + + result = runner.invoke(main, options) + + assert result.exit_code == 2 diff --git a/tests/spdx/test_datetime_conversions.py b/tests/spdx/test_datetime_conversions.py new file mode 100644 index 000000000..3967d593b --- /dev/null +++ b/tests/spdx/test_datetime_conversions.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime, timezone + +import pytest + +from spdx_tools.spdx.datetime_conversions import datetime_from_str, datetime_to_iso_string + +# The following is required as long as we support Python 3.8.x or +# older. Once Python 3.9 is the oldest version we support, we can +# rely solely on the section which imports and uses zoneinfo. + +try: + # Python 3.9 and later + from zoneinfo import ZoneInfo + + tz_nyc = ZoneInfo("America/New_York") +except ImportError: + # Python 3.8 and earlier + from datetime import timedelta + + tz_nyc = timezone(timedelta(hours=-4)) + + +def test_datetime_to_iso_string(): + assert datetime_to_iso_string(datetime(2022, 12, 13, 1, 2, 3)) == "2022-12-13T01:02:03Z" + + +def test_datetime_to_iso_string_with_microseconds(): + assert datetime_to_iso_string(datetime(2022, 12, 13, 1, 2, 3, 666666)) == "2022-12-13T01:02:03Z" + + +def test_utc_datetime_to_iso_string(): + dt = datetime(2023, 10, 4, 1, 2, 3, tzinfo=timezone.utc) + assert datetime_to_iso_string(dt) == "2023-10-04T01:02:03Z" + + +def test_local_datetime_to_iso_string(): + dt = datetime(2023, 10, 4, 1, 2, 3, tzinfo=tz_nyc) + assert datetime_to_iso_string(dt) == "2023-10-04T05:02:03Z" + + +def test_datetime_from_str(): + date_str = "2010-03-04T05:45:11Z" + + date = datetime_from_str(date_str) + + assert date == datetime(2010, 3, 4, 5, 45, 11) + + +@pytest.mark.parametrize( + "invalid_date_str, error_type, expected_message", + [ + (5, TypeError, "Could not convert str to datetime, invalid type: int"), + ("2010-02-03", ValueError, "time data '2010-02-03' does not match format '%Y-%m-%dT%H:%M:%SZ'"), + ], +) +def test_datetime_from_str_error(invalid_date_str, error_type, expected_message): + with pytest.raises(error_type, match=expected_message): + datetime_from_str(invalid_date_str) diff --git a/tests/spdx/test_document_utils.py b/tests/spdx/test_document_utils.py new file mode 100644 index 000000000..4e05de869 --- /dev/null +++ b/tests/spdx/test_document_utils.py @@ -0,0 +1,125 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.document_utils import ( + create_document_without_duplicates, + create_list_without_duplicates, + get_contained_spdx_element_ids, + get_contained_spdx_elements, + get_element_from_spdx_id, +) +from spdx_tools.spdx.model import FileType, SpdxNoAssertion, SpdxNone +from tests.spdx.fixtures import ( + actor_fixture, + checksum_fixture, + creation_info_fixture, + document_fixture, + external_document_ref_fixture, + external_package_ref_fixture, + extracted_licensing_info_fixture, + file_fixture, + package_fixture, + snippet_fixture, +) + + +@pytest.fixture +def variables(): + return document_fixture(), package_fixture(), file_fixture(), snippet_fixture() + + +def test_contained_element_ids(variables): + document, package, file, snippet = variables + element_ids = get_contained_spdx_element_ids(document) + TestCase().assertCountEqual(element_ids, [package.spdx_id, file.spdx_id, snippet.spdx_id]) + + +def test_get_element_from_spdx_id(variables): + document, package, file, snippet = variables + assert get_element_from_spdx_id(document, package.spdx_id) == package + assert get_element_from_spdx_id(document, file.spdx_id) == file + assert get_element_from_spdx_id(document, snippet.spdx_id) == snippet + assert get_element_from_spdx_id(document, "unknown_id") is None + + +def test_get_contained_spdx_elements(variables): + document, package, file, snippet = variables + contained_elements = get_contained_spdx_elements(document) + assert contained_elements[package.spdx_id] == package + assert contained_elements[file.spdx_id] == file + assert contained_elements[snippet.spdx_id] == snippet + + +def test_create_list_without_duplicates(): + list_with_duplicates = [1, 2, 3, 5, 1, 67, 9, 67] + + list_without_duplicates = create_list_without_duplicates(list_with_duplicates) + + assert list_without_duplicates == [1, 2, 3, 5, 67, 9] + + +def test_create_document_without_duplicates(): + document = document_fixture( + creation_info=creation_info_fixture( + creators=[actor_fixture(name="creatorName"), actor_fixture(name="creatorName")], + external_document_refs=[external_document_ref_fixture(), external_document_ref_fixture()], + ), + packages=[ + package_fixture( + checksums=[checksum_fixture(), checksum_fixture()], + license_info_from_files=[SpdxNoAssertion(), SpdxNoAssertion()], + external_references=[external_package_ref_fixture(), external_package_ref_fixture()], + attribution_texts=["duplicated text", "duplicated text"], + ) + ], + files=[ + file_fixture( + checksums=[checksum_fixture(), checksum_fixture()], + file_types=[FileType.TEXT, FileType.TEXT], + license_info_in_file=[SpdxNoAssertion(), SpdxNoAssertion()], + contributors=["duplicated contributor", "duplicated contributor"], + attribution_texts=["duplicated text", "duplicated text"], + ) + ], + snippets=[ + snippet_fixture( + license_info_in_snippet=[SpdxNone(), SpdxNone()], + attribution_texts=["duplicated text", "duplicated text"], + ) + ], + extracted_licensing_info=[ + extracted_licensing_info_fixture(cross_references=["duplicated reference", "duplicated reference"]) + ], + ) + expected_document = document_fixture( + creation_info=creation_info_fixture( + creators=[actor_fixture(name="creatorName")], external_document_refs=[external_document_ref_fixture()] + ), + packages=[ + package_fixture( + checksums=[checksum_fixture()], + license_info_from_files=[SpdxNoAssertion()], + external_references=[external_package_ref_fixture()], + attribution_texts=["duplicated text"], + ) + ], + files=[ + file_fixture( + checksums=[checksum_fixture()], + file_types=[FileType.TEXT], + license_info_in_file=[SpdxNoAssertion()], + contributors=["duplicated contributor"], + attribution_texts=["duplicated text"], + ) + ], + snippets=[snippet_fixture(license_info_in_snippet=[SpdxNone()], attribution_texts=["duplicated text"])], + extracted_licensing_info=[extracted_licensing_info_fixture(cross_references=["duplicated reference"])], + ) + + document_without_duplicates = create_document_without_duplicates(document) + + assert document_without_duplicates == expected_document diff --git a/tests/spdx/test_graph_generation.py b/tests/spdx/test_graph_generation.py new file mode 100644 index 000000000..f51d9590b --- /dev/null +++ b/tests/spdx/test_graph_generation.py @@ -0,0 +1,153 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from pathlib import Path +from typing import List +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.graph_generation import generate_relationship_graph_from_spdx +from spdx_tools.spdx.model import Document, Relationship, RelationshipType +from spdx_tools.spdx.parser.parse_anything import parse_file +from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture + +try: + import networkx # noqa: F401 +except ImportError: + pytest.skip("Skip this module as the tests need optional dependencies to run.", allow_module_level=True) + + +@pytest.mark.parametrize( + "file_name, nodes_count, edges_count, relationship_node_keys", + [ + ( + "SPDXJSONExample-v2.3.spdx.json", + 22, + 22, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ( + "SPDXJSONExample-v2.2.spdx.json", + 20, + 19, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ( + "SPDXRdfExample-v2.3.spdx.rdf.xml", + 22, + 22, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ( + "SPDXRdfExample-v2.2.spdx.rdf.xml", + 20, + 19, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ( + "SPDXTagExample-v2.3.spdx", + 22, + 22, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ], +) +def test_generate_graph_from_spdx( + file_name: str, + nodes_count: int, + edges_count: int, + relationship_node_keys: List[str], +) -> None: + document = parse_file(str(Path(__file__).resolve().parent.parent / "spdx" / "data" / file_name)) + graph = generate_relationship_graph_from_spdx(document) + + assert document.creation_info.spdx_id in graph.nodes() + assert graph.number_of_nodes() == nodes_count + assert graph.number_of_edges() == edges_count + assert "SPDXRef-DOCUMENT_DESCRIBES" in graph.nodes() + for relationship_node_key in relationship_node_keys: + assert relationship_node_key in graph.nodes() + + +def test_complete_connected_graph() -> None: + document = _create_minimal_document() + + graph = generate_relationship_graph_from_spdx(document) + + TestCase().assertCountEqual( + graph.nodes(), + [ + "SPDXRef-DOCUMENT", + "SPDXRef-Package-A", + "SPDXRef-Package-B", + "SPDXRef-File", + "SPDXRef-DOCUMENT_DESCRIBES", + "SPDXRef-Package-A_CONTAINS", + "SPDXRef-Package-B_CONTAINS", + ], + ) + TestCase().assertCountEqual( + graph.edges(), + [ + ("SPDXRef-DOCUMENT", "SPDXRef-DOCUMENT_DESCRIBES"), + ("SPDXRef-DOCUMENT_DESCRIBES", "SPDXRef-Package-A"), + ("SPDXRef-DOCUMENT_DESCRIBES", "SPDXRef-Package-B"), + ("SPDXRef-Package-A", "SPDXRef-Package-A_CONTAINS"), + ("SPDXRef-Package-A_CONTAINS", "SPDXRef-File"), + ("SPDXRef-Package-B", "SPDXRef-Package-B_CONTAINS"), + ("SPDXRef-Package-B_CONTAINS", "SPDXRef-File"), + ], + ) + + +def test_complete_unconnected_graph() -> None: + document = _create_minimal_document() + document.packages += [package_fixture(spdx_id="SPDXRef-Package-C", name="Package without connection to document")] + + graph = generate_relationship_graph_from_spdx(document) + + TestCase().assertCountEqual( + graph.nodes(), + [ + "SPDXRef-DOCUMENT", + "SPDXRef-Package-A", + "SPDXRef-Package-B", + "SPDXRef-File", + "SPDXRef-DOCUMENT_DESCRIBES", + "SPDXRef-Package-A_CONTAINS", + "SPDXRef-Package-B_CONTAINS", + "SPDXRef-Package-C", + ], + ) + TestCase().assertCountEqual( + graph.edges(), + [ + ("SPDXRef-DOCUMENT", "SPDXRef-DOCUMENT_DESCRIBES"), + ("SPDXRef-DOCUMENT_DESCRIBES", "SPDXRef-Package-A"), + ("SPDXRef-DOCUMENT_DESCRIBES", "SPDXRef-Package-B"), + ("SPDXRef-Package-A", "SPDXRef-Package-A_CONTAINS"), + ("SPDXRef-Package-A_CONTAINS", "SPDXRef-File"), + ("SPDXRef-Package-B", "SPDXRef-Package-B_CONTAINS"), + ("SPDXRef-Package-B_CONTAINS", "SPDXRef-File"), + ], + ) + + +def _create_minimal_document() -> Document: + packages = [ + package_fixture(spdx_id="SPDXRef-Package-A", name="Package-A"), + package_fixture(spdx_id="SPDXRef-Package-B", name="Package-B"), + ] + files = [ + file_fixture(spdx_id="SPDXRef-File", name="File"), + ] + relationships = [ + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package-A"), + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package-B"), + Relationship("SPDXRef-Package-A", RelationshipType.CONTAINS, "SPDXRef-File"), + Relationship("SPDXRef-Package-B", RelationshipType.CONTAINS, "SPDXRef-File"), + ] + document = document_fixture(packages=packages, files=files, relationships=relationships, snippets=[]) + + return document diff --git a/tests/spdx/validation/__init__.py b/tests/spdx/validation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/validation/test_actor_validator.py b/tests/spdx/validation/test_actor_validator.py new file mode 100644 index 000000000..0ab122473 --- /dev/null +++ b/tests/spdx/validation/test_actor_validator.py @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import ActorType +from spdx_tools.spdx.validation.actor_validator import validate_actor +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import actor_fixture + + +def test_valid_actor_person(): + actor = actor_fixture() + validation_messages: List[ValidationMessage] = validate_actor(actor, DOCUMENT_SPDX_ID) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "actor, expected_message", + [ + ( + actor_fixture(actor_type=ActorType.TOOL, email="mail@mail.com"), + "email must be None if actor_type is TOOL, but is: mail@mail.com", + ), + ], +) +def test_invalid_actor(actor, expected_message): + parent_id = DOCUMENT_SPDX_ID + validation_messages: List[ValidationMessage] = validate_actor(actor, parent_id) + + expected = ValidationMessage( + expected_message, + ValidationContext(parent_id=parent_id, element_type=SpdxElementType.ACTOR, full_element=actor), + ) + + assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_annotation_validator.py b/tests/spdx/validation/test_annotation_validator.py new file mode 100644 index 000000000..2462f9cda --- /dev/null +++ b/tests/spdx/validation/test_annotation_validator.py @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List + +import pytest + +from spdx_tools.spdx.model import Annotation, Document +from spdx_tools.spdx.validation.annotation_validator import validate_annotation +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import annotation_fixture, document_fixture, file_fixture + + +def test_valid_annotation(): + validation_messages: List[ValidationMessage] = validate_annotation(annotation_fixture(), document_fixture()) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "annotation_id, file_id, expected_message", + [ + ( + "SPDXRef-File", + "SPDXRef-hiddenFile", + 'did not find the referenced spdx_id "SPDXRef-File" in the SPDX document', + ) + ], +) +def test_invalid_annotation(annotation_id, file_id, expected_message): + annotation: Annotation = annotation_fixture(spdx_id=annotation_id) + document: Document = document_fixture(files=[file_fixture(spdx_id=file_id)]) + validation_messages: List[ValidationMessage] = validate_annotation(annotation, document) + + expected = ValidationMessage( + expected_message, ValidationContext(element_type=SpdxElementType.ANNOTATION, full_element=annotation) + ) + + assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_checksum_validator.py b/tests/spdx/validation/test_checksum_validator.py new file mode 100644 index 000000000..9340de5db --- /dev/null +++ b/tests/spdx/validation/test_checksum_validator.py @@ -0,0 +1,232 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List + +import pytest + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.validation.checksum_validator import validate_checksum +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import checksum_fixture + + +@pytest.mark.parametrize( + "checksum", + [ + checksum_fixture(), + Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), + Checksum(ChecksumAlgorithm.SHA224, "9c9f4e27d957a123cc32d86afe33ae53b1184192cccb23b0f257f588"), + Checksum(ChecksumAlgorithm.SHA256, "fbea580d286bbbbb41314430d58ba887716a74d7134119c5307cdc9f0c7a4299"), + Checksum( + ChecksumAlgorithm.SHA384, + "73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933", + ), + Checksum( + ChecksumAlgorithm.SHA512, + "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f" + "15af43e7cb5547f1a464053", + ), + Checksum(ChecksumAlgorithm.SHA3_256, "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce"), + Checksum( + ChecksumAlgorithm.SHA3_384, + "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", + ), + Checksum( + ChecksumAlgorithm.SHA3_512, + "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d11" + "1310266a5d46e2bc1ffbb36", + ), + Checksum(ChecksumAlgorithm.BLAKE2B_256, "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7"), + Checksum( + ChecksumAlgorithm.BLAKE2B_384, + "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", + ), + Checksum( + ChecksumAlgorithm.BLAKE2B_512, + "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8" + "c4af74dce531ca8ebd8824c", + ), + Checksum( + ChecksumAlgorithm.BLAKE3, + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874d" + "cec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006" + "857d3b9985174bf67239874dcec4cbbc9839496179feafed", + ), + Checksum(ChecksumAlgorithm.MD2, "af1eec2a1b18886c3f3cc244349d91d8"), + Checksum(ChecksumAlgorithm.MD4, "d4c41ce30a517d6ce9d79c8c17bb4b66"), + Checksum(ChecksumAlgorithm.MD5, "0d7f61beb7018b3924c6b8f96549fa39"), + Checksum( + ChecksumAlgorithm.MD6, + "af1eec2a1b18886c3f3cc244349d91d8d4c41ce30a517d6ce9d79c8c17bb4b660d7f61beb7018b3924c6b8f96549fa39", + ), + Checksum(ChecksumAlgorithm.ADLER32, "02ec0130"), + ], +) +def test_valid_checksum(checksum): + validation_messages: List[ValidationMessage] = validate_checksum(checksum, "parent_id", "SPDX-2.3") + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "checksum, expected_message", + [ + ( + Checksum(ChecksumAlgorithm.SHA1, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA224, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA224 must consist of 56 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA256, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA256 must consist of 64 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA384, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA384 must consist of 96 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA512, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA512 must consist of 128 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA3_256, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA3_256 must consist of 64 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA3_384, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA3_384 must consist of 96 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA3_512, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA3_512 must consist of 128 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.BLAKE2B_256, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.BLAKE2B_256 must consist of 64 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.BLAKE2B_384, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.BLAKE2B_384 must consist of 96 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.BLAKE2B_512, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.BLAKE2B_512 must consist of 128 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.BLAKE3, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.BLAKE3 must consist of at least 256 lowercase hexadecimal digits, but is: af1e" + "ec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.MD2, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), + "value of ChecksumAlgorithm.MD2 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364" + "f3ebbb42c484ff43d00791c (length: 40 digits)", + ), + ( + Checksum(ChecksumAlgorithm.MD4, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), + "value of ChecksumAlgorithm.MD4 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364" + "f3ebbb42c484ff43d00791c (length: 40 digits)", + ), + ( + Checksum(ChecksumAlgorithm.MD5, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), + "value of ChecksumAlgorithm.MD5 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364" + "f3ebbb42c484ff43d00791c (length: 40 digits)", + ), + ( + Checksum( + ChecksumAlgorithm.MD6, + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf672398" + "74dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967" + "a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582" + "b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b" + "5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc983949617" + "9feafed5", + ), + "value of ChecksumAlgorithm.MD6 must consist of between 0 and 512 lowercase hexadecimal digits, but is: " + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dc" + "ec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a1300685" + "7d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6a" + "c3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341" + "bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed5 " + "(length: 513 digits)", + ), + ( + Checksum(ChecksumAlgorithm.ADLER32, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.ADLER32 must consist of 8 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA1, "CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4"), + "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: " + "CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)", + ), + ], +) +def test_invalid_checksum(checksum, expected_message): + parent_id = "parent_id" + validation_messages: List[ValidationMessage] = validate_checksum(checksum, parent_id, "SPDX-2.3") + + expected = ValidationMessage( + expected_message, + ValidationContext(parent_id=parent_id, element_type=SpdxElementType.CHECKSUM, full_element=checksum), + ) + + assert validation_messages == [expected] + + +@pytest.mark.parametrize( + "checksum", + [ + Checksum(ChecksumAlgorithm.SHA3_256, "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce"), + Checksum( + ChecksumAlgorithm.SHA3_384, + "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", + ), + Checksum( + ChecksumAlgorithm.SHA3_512, + "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d1" + "11310266a5d46e2bc1ffbb36", + ), + Checksum(ChecksumAlgorithm.BLAKE2B_256, "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7"), + Checksum( + ChecksumAlgorithm.BLAKE2B_384, + "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", + ), + Checksum( + ChecksumAlgorithm.BLAKE2B_512, + "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e" + "8c4af74dce531ca8ebd8824c", + ), + Checksum( + ChecksumAlgorithm.BLAKE3, + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874" + "dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006" + "857d3b9985174bf67239874dcec4cbbc9839496179feafed", + ), + Checksum(ChecksumAlgorithm.ADLER32, "02ec0130"), + ], +) +def test_v2_3only_checksums(checksum): + parent_id = "parent_id" + validation_messages: List[ValidationMessage] = validate_checksum(checksum, parent_id, "SPDX-2.2") + + context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.CHECKSUM, full_element=checksum) + expected = ValidationMessage(f"{checksum.algorithm.name} is not supported in SPDX-2.2", context) + + assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_creation_info_validator.py b/tests/spdx/validation/test_creation_info_validator.py new file mode 100644 index 000000000..340993ebf --- /dev/null +++ b/tests/spdx/validation/test_creation_info_validator.py @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.validation.creation_info_validator import validate_creation_info +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import creation_info_fixture + + +def test_valid_creation_info(): + creation_info = creation_info_fixture() + validation_messages: List[ValidationMessage] = validate_creation_info(creation_info, "SPDX-2.3") + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "creation_info_input, spdx_id, expected_message", + [ + ( + creation_info_fixture(spdx_id="SPDXRef-doc"), + "SPDXRef-doc", + f"spdx_id must be {DOCUMENT_SPDX_ID}, but is: SPDXRef-doc", + ), + (creation_info_fixture(data_license="MIT"), DOCUMENT_SPDX_ID, 'data_license must be "CC0-1.0", but is: MIT'), + ( + creation_info_fixture(document_namespace="some_namespace"), + DOCUMENT_SPDX_ID, + "document_namespace must be a valid URI specified in RFC-3986 and must contain no fragment (#), " + "but is: some_namespace", + ), + ], +) +def test_invalid_creation_info(creation_info_input, expected_message, spdx_id): + validation_messages: List[ValidationMessage] = validate_creation_info(creation_info_input, "SPDX-2.3") + + expected = ValidationMessage(expected_message, ValidationContext(spdx_id, None, SpdxElementType.DOCUMENT)) + + assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py new file mode 100644 index 000000000..1b1897f52 --- /dev/null +++ b/tests/spdx/validation/test_document_validator.py @@ -0,0 +1,152 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os +from typing import List, Optional + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import CreationInfo, Document, Relationship, RelationshipType +from spdx_tools.spdx.parser.parse_anything import parse_file +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import creation_info_fixture, document_fixture, file_fixture, package_fixture, snippet_fixture + + +def test_valid_document(): + document = document_fixture() + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + + assert validation_messages == [] + + +def test_spdx_lite_validation(): + document = parse_file(os.path.join(os.path.dirname(__file__), "../data/SPDXLite.spdx")) + + assert validate_full_spdx_document(document) == [] + + +@pytest.mark.parametrize( + "creation_info, version_input, expected_message", + [ + (creation_info_fixture(spdx_version="SPDX-2.3"), "SPDX-2.3", None), + (creation_info_fixture(spdx_version="SPDX-2.3"), None, None), + ( + creation_info_fixture(spdx_version="SPDX-2.3"), + "SPDX-2.2", + "provided SPDX version SPDX-2.2 does not match the document's SPDX version SPDX-2.3", + ), + ( + creation_info_fixture(spdx_version="SPDX-2.3"), + "SPDX2.3", + "provided SPDX version SPDX2.3 does not match the document's SPDX version SPDX-2.3", + ), + ( + creation_info_fixture(spdx_version="SPDX2.3"), + "SPDX-2.3", + 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX2.3', + ), + ( + creation_info_fixture(spdx_version="SPDX2.3"), + None, + 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX2.3', + ), + ( + creation_info_fixture(spdx_version="SPDX2.3"), + "SPDX2.3", + 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX2.3', + ), + ( + creation_info_fixture(spdx_version="SPDX-2.1"), + "SPDX-2.1", + 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s ' + "spdx_version is: SPDX-2.1", + ), + ], +) +def test_spdx_version_handling(creation_info: CreationInfo, version_input: str, expected_message: Optional[str]): + document: Document = document_fixture(creation_info=creation_info) + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document, version_input) + + context = ValidationContext(spdx_id=creation_info.spdx_id, element_type=SpdxElementType.DOCUMENT) + expected: List[ValidationMessage] = [] + + if expected_message: + expected.append(ValidationMessage(expected_message, context)) + expected.append( + ValidationMessage( + "There are issues concerning the SPDX version of the document. " + "As subsequent validation relies on the correct version, " + "the validation process has been cancelled.", + context, + ) + ) + + assert validation_messages == expected + + +@pytest.mark.parametrize( + "relationships", + [ + [Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-File")], + [Relationship("SPDXRef-File", RelationshipType.DESCRIBED_BY, DOCUMENT_SPDX_ID)], + ], +) +def test_document_describes_at_least_one_element(relationships): + document = document_fixture(relationships=relationships) + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + + assert validation_messages == [] + + +def test_document_does_not_describe_an_element_with_only_one_package(): + document = document_fixture( + packages=[package_fixture()], + files=[], + snippets=[], + relationships=[], + annotations=[], + ) + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + + assert validation_messages == [] + + +def test_document_does_not_describe_an_element_with_multiple_elements(): + document = document_fixture( + relationships=[Relationship("SPDXRef-Package", RelationshipType.DESCRIBES, "SPDXRef-File")] + ) + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + + assert validation_messages == [ + ValidationMessage( + f'there must be at least one relationship "{DOCUMENT_SPDX_ID} DESCRIBES ..." or "... DESCRIBED_BY ' + f'{DOCUMENT_SPDX_ID}" when there is not only a single package present', + ValidationContext(spdx_id=DOCUMENT_SPDX_ID, element_type=SpdxElementType.DOCUMENT), + ) + ] + + +def test_duplicated_spdx_ids(): + document = document_fixture( + files=[ + file_fixture(spdx_id="SPDXRef-File"), + file_fixture(spdx_id="SPDXRef-2"), + file_fixture(spdx_id="SPDXRef-3"), + ], + packages=[package_fixture(spdx_id="SPDXRef-2"), package_fixture(spdx_id=DOCUMENT_SPDX_ID)], + snippets=[snippet_fixture(spdx_id="SPDXRef-2"), snippet_fixture(spdx_id="SPDXRef-3")], + ) + + context = ValidationContext(spdx_id=document.creation_info.spdx_id, element_type=SpdxElementType.DOCUMENT) + + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + + assert validation_messages == [ + ValidationMessage( + "every spdx_id must be unique within the document, but found the following duplicates: ['SPDXRef-2', " + f"'SPDXRef-3', '{DOCUMENT_SPDX_ID}']", + context, + ) + ] diff --git a/tests/spdx/validation/test_external_document_ref_validator.py b/tests/spdx/validation/test_external_document_ref_validator.py new file mode 100644 index 000000000..ce67b6d4d --- /dev/null +++ b/tests/spdx/validation/test_external_document_ref_validator.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List + +from spdx_tools.spdx.validation.external_document_ref_validator import validate_external_document_ref +from spdx_tools.spdx.validation.validation_message import ValidationMessage +from tests.spdx.fixtures import external_document_ref_fixture + + +def test_valid_external_document_ref(): + external_document_ref = external_document_ref_fixture() + validation_messages: List[ValidationMessage] = validate_external_document_ref( + external_document_ref, "parent_id", "SPDX-2.3" + ) + + assert validation_messages == [] diff --git a/tests/spdx/validation/test_external_package_ref_validator.py b/tests/spdx/validation/test_external_package_ref_validator.py new file mode 100644 index 000000000..eafa31941 --- /dev/null +++ b/tests/spdx/validation/test_external_package_ref_validator.py @@ -0,0 +1,303 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List + +import pytest + +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.validation.external_package_ref_validator import ( + BOWER_REGEX, + CPE22TYPE_REGEX, + CPE23TYPE_REGEX, + GITOID_REGEX, + MAVEN_CENTRAL_REGEX, + NPM_REGEX, + NUGET_REGEX, + PURL_REGEX, + SWH_REGEX, + validate_external_package_ref, +) +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +@pytest.mark.parametrize( + "category, reference_type, locator", + [ + (ExternalPackageRefCategory.SECURITY, "cpe22Type", "cpe:/o:canonical:ubuntu_linux:10.04:-:lts"), + (ExternalPackageRefCategory.SECURITY, "cpe23Type", "cpe:2.3:o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*"), + (ExternalPackageRefCategory.SECURITY, "advisory", "https://nvd.nist.gov/vuln/detail/CVE-2020-28498"), + (ExternalPackageRefCategory.SECURITY, "fix", "https://github.com/indutny/elliptic/commit/441b7428"), + ( + ExternalPackageRefCategory.SECURITY, + "url", + "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/" + "secp256k1_twist_attacks.md", + ), + (ExternalPackageRefCategory.SECURITY, "swid", "swid:2df9de35-0aff-4a86-ace6-f7dddd1ade4c"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "maven-central", "org.apache.tomcat:tomcat:9.0.0.M4"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "npm", "http-server@0.3.0"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "nuget", "Microsoft.AspNet.MVC/5.0.0"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "bower", "modernizr#2.6.2"), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:docker/debian@sha256:2f04d3d33b6027bb74ecc81397abe780649ec89f1a2af18d7022737d0482cefe", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:bitbucket/birkenfeld/pygments-main@244fd47e07d1014f0aed9c", + ), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:deb/debian/curl@7.50.3-1?arch=i386&distro=jessie"), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:docker/customer/dockerimage@sha256:244fd47e07d1004f0aed9c?repository_url=gcr.io", + ), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:gem/jruby-launcher@1.1.2?platform=java"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:gem/ruby-advisory-db-check@0.12.4"), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:golang/google.golang.org/genproto#googleapis/api/annotations", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?repository_url=repo.spring.io%2Frelease", + ), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:npm/%40angular/animation@12.3.1"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:nuget/EnterpriseLibrary.Common@6.0.1304"), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:rpm/fedora/curl@7.50.3-1.fc25?arch=i386&distro=fedora-25", + ), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2"), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:dir:d198bc9d7a6bcf6db04f476d29314f157507d505"), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:rev:309cf2674ee7a0749978cf8265ab91a60aea0f7d"), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:rel:22ece559cc7cc2364edc5e5593d63ae8bd229f9f"), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:snp:c7c108084bc0bf3d81436bf980b46e98bd338453"), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "gitoid", + "gitoid:blob:sha1:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "gitoid", + "gitoid:blob:sha256:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c", + ), + (ExternalPackageRefCategory.OTHER, "some idstring", "#//string-withOUT!Spaces\\?"), + ], +) +def test_valid_external_package_ref(category, reference_type, locator): + external_package_ref = ExternalPackageRef(category, reference_type, locator, "externalPackageRef comment") + validation_messages: List[ValidationMessage] = validate_external_package_ref( + external_package_ref, "parent_id", "SPDX-2.3" + ) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "category, reference_type, locator, expected_message", + [ + ( + ExternalPackageRefCategory.SECURITY, + "cpe22Typo", + "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", + "externalPackageRef type in category SECURITY must be one of ['cpe22Type', 'cpe23Type', 'advisory', 'fix'" + ", 'url', 'swid'], but is: cpe22Typo", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "nugat", + "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", + "externalPackageRef type in category PACKAGE_MANAGER must be one of ['maven-central', 'npm', 'nuget'," + " 'bower', 'purl'], but is: nugat", + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "git-oid", + "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", + "externalPackageRef type in category PERSISTENT_ID must be one of ['swh', 'gitoid'], but is: git-oid", + ), + ], +) +def test_invalid_external_package_ref_types(category, reference_type, locator, expected_message): + external_package_ref = ExternalPackageRef(category, reference_type, locator, "externalPackageRef comment") + parent_id = "SPDXRef-Package" + validation_messages: List[ValidationMessage] = validate_external_package_ref( + external_package_ref, parent_id, "SPDX-2.3" + ) + + expected = ValidationMessage( + expected_message, + ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, full_element=external_package_ref + ), + ) + + assert validation_messages == [expected] + + +@pytest.mark.parametrize( + "category, reference_type, locator, expected_message", + [ + ( + ExternalPackageRefCategory.SECURITY, + "cpe22Type", + "cpe:o:canonical:ubuntu_linux:10.04:-:lts", + f'externalPackageRef locator of type "cpe22Type" must conform with the regex {CPE22TYPE_REGEX}, but is: ' + f"cpe:o:canonical:ubuntu_linux:10.04:-:lts", + ), + ( + ExternalPackageRefCategory.SECURITY, + "cpe23Type", + "cpe:2.3:/o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*", + f'externalPackageRef locator of type "cpe23Type" must conform with the regex {CPE23TYPE_REGEX}, but is: ' + f"cpe:2.3:/o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*", + ), + ( + ExternalPackageRefCategory.SECURITY, + "advisory", + "http://locatorurl", + 'externalPackageRef locator of type "advisory" must be a valid URL, but is: http://locatorurl', + ), + ( + ExternalPackageRefCategory.SECURITY, + "fix", + "http://fixurl", + 'externalPackageRef locator of type "fix" must be a valid URL, but is: http://fixurl', + ), + ( + ExternalPackageRefCategory.SECURITY, + "url", + "http://url", + 'externalPackageRef locator of type "url" must be a valid URL, but is: http://url', + ), + ( + ExternalPackageRefCategory.SECURITY, + "swid", + "2df9de35-0aff-4a86-ace6-f7dddd1ade4c", + 'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, but is: ' + "2df9de35-0aff-4a86-ace6-f7dddd1ade4c", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "maven-central", + "org.apache.tomcat:tomcat:tomcat:9.0.0.M4", + f'externalPackageRef locator of type "maven-central" must conform with the regex {MAVEN_CENTRAL_REGEX}, ' + f"but is: org.apache.tomcat:tomcat:tomcat:9.0.0.M4", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "npm", + "http-server:0.3.0", + f'externalPackageRef locator of type "npm" must conform with the regex {NPM_REGEX}, ' + f"but is: http-server:0.3.0", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "nuget", + "Microsoft.AspNet.MVC@5.0.0", + f'externalPackageRef locator of type "nuget" must conform with the regex {NUGET_REGEX}, ' + f"but is: Microsoft.AspNet.MVC@5.0.0", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "bower", + "modernizr:2.6.2", + f'externalPackageRef locator of type "bower" must conform with the regex {BOWER_REGEX}, ' + f"but is: modernizr:2.6.2", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:npm@12.3.1", + f'externalPackageRef locator of type "purl" must conform with the regex {PURL_REGEX}, ' + f"but is: pkg:npm@12.3.1", + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "swh", + "swh:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", + f'externalPackageRef locator of type "swh" must conform with the regex {SWH_REGEX}, ' + f"but is: swh:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "gitoid", + "gitoid:blob:sha1:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c", + f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX}, ' + f"but is: gitoid:blob:sha1:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c", + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "gitoid", + "gitoid:blob:sha256:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", + f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX},' + f" but is: gitoid:blob:sha256:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", + ), + ( + ExternalPackageRefCategory.OTHER, + "id string", + "locator string", + "externalPackageRef locator in category OTHER must contain no spaces, but is: locator string", + ), + ], +) +def test_invalid_external_package_ref_locators(category, reference_type, locator, expected_message): + external_package_ref = ExternalPackageRef(category, reference_type, locator, "externalPackageRef comment") + parent_id = "SPDXRef-Package" + validation_messages: List[ValidationMessage] = validate_external_package_ref( + external_package_ref, parent_id, "SPDX-2.3" + ) + + expected = ValidationMessage( + expected_message, + ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, full_element=external_package_ref + ), + ) + + assert validation_messages == [expected] + + +@pytest.mark.parametrize( + "category, reference_type, locator", + [ + (ExternalPackageRefCategory.SECURITY, "advisory", "https://nvd.nist.gov/vuln/detail/CVE-2020-28498"), + (ExternalPackageRefCategory.SECURITY, "fix", "https://github.com/indutny/elliptic/commit/441b7428"), + ( + ExternalPackageRefCategory.SECURITY, + "url", + "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/" + "secp256k1_twist_attacks.md", + ), + (ExternalPackageRefCategory.SECURITY, "swid", "swid:2df9de35-0aff-4a86-ace6-f7dddd1ade4c"), + ], +) +def test_v2_3only_external_package_ref_types(category, reference_type, locator): + external_package_ref = ExternalPackageRef(category, reference_type, locator, "externalPackageRef comment") + parent_id = "SPDXRef-Package" + validation_messages: List[ValidationMessage] = validate_external_package_ref( + external_package_ref, parent_id, "SPDX-2.2" + ) + + expected = ValidationMessage( + f'externalPackageRef type "{reference_type}" is not supported in SPDX-2.2', + ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, full_element=external_package_ref + ), + ) + + assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_extracted_licensing_info_validator.py b/tests/spdx/validation/test_extracted_licensing_info_validator.py new file mode 100644 index 000000000..911bea71c --- /dev/null +++ b/tests/spdx/validation/test_extracted_licensing_info_validator.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List + +import pytest + +from spdx_tools.spdx.validation.extracted_licensing_info_validator import validate_extracted_licensing_info +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import extracted_licensing_info_fixture + + +def test_valid_extracted_licensing_info(): + extracted_licensing_info = extracted_licensing_info_fixture() + validation_messages: List[ValidationMessage] = validate_extracted_licensing_info(extracted_licensing_info) + + assert validation_messages == [] + + +# TODO: tests for licenses not on the SPDX License list (i.e. they must provide id, name and cross-references) +@pytest.mark.parametrize( + "extracted_licensing_info, expected_message", + [ + ( + extracted_licensing_info_fixture(extracted_text=None), + "extracted_text must be provided if there is a license_id assigned", + ), + ( + extracted_licensing_info_fixture(cross_references=["invalid_url"]), + "cross_reference must be a valid URL, but is: invalid_url", + ), + ], +) +def test_invalid_extracted_licensing_info(extracted_licensing_info, expected_message): + validation_messages: List[ValidationMessage] = validate_extracted_licensing_info(extracted_licensing_info) + + expected = ValidationMessage( + expected_message, + ValidationContext( + element_type=SpdxElementType.EXTRACTED_LICENSING_INFO, full_element=extracted_licensing_info + ), + ) + + assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_file_validator.py b/tests/spdx/validation/test_file_validator.py new file mode 100644 index 000000000..73f107a9f --- /dev/null +++ b/tests/spdx/validation/test_file_validator.py @@ -0,0 +1,67 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.validation.file_validator import validate_file, validate_file_within_document +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import document_fixture, file_fixture + + +def test_valid_file(): + file = file_fixture() + validation_messages: List[ValidationMessage] = validate_file_within_document(file, "SPDX-2.3", document_fixture()) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "file_input, spdx_id, expected_message", + [ + ( + file_fixture(name="/invalid/file/name"), + file_fixture().spdx_id, + 'file name must not be an absolute path starting with "/", but is: /invalid/file/name', + ), + ( + file_fixture(checksums=[Checksum(ChecksumAlgorithm.MD2, "d4c41ce30a517d6ce9d79c8c17bb4b66")]), + file_fixture().spdx_id, + "checksums must contain a SHA1 algorithm checksum, but only contains: []", + ), + ], +) +def test_invalid_file(file_input, spdx_id, expected_message): + validation_messages: List[ValidationMessage] = validate_file_within_document( + file_input, "SPDX-2.3", document_fixture() + ) + + expected = ValidationMessage( + expected_message, + ValidationContext( + spdx_id=spdx_id, + parent_id=document_fixture().creation_info.spdx_id, + element_type=SpdxElementType.FILE, + full_element=file_input, + ), + ) + + assert validation_messages == [expected] + + +def test_v2_2mandatory_fields(): + file = file_fixture(license_concluded=None, license_info_in_file=[], copyright_text=None) + + assert validate_file(file, "SPDX-2.3") == [] + + validation_messages: List[ValidationMessage] = validate_file(file, "SPDX-2.2") + + context = ValidationContext(spdx_id=file.spdx_id, element_type=SpdxElementType.FILE, full_element=file) + mandatory_fields = ["license_concluded", "license_info_in_file", "copyright_text"] + expected = [ValidationMessage(f"{field} is mandatory in SPDX-2.2", context) for field in mandatory_fields] + + TestCase().assertCountEqual(validation_messages, expected) diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py new file mode 100644 index 000000000..e965f4803 --- /dev/null +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -0,0 +1,175 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List +from unittest import TestCase + +import pytest +from license_expression import LicenseExpression + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.validation.license_expression_validator import ( + validate_license_expression, + validate_license_expressions, +) +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import document_fixture, external_document_ref_fixture, extracted_licensing_info_fixture + +FIXTURE_LICENSE_ID = extracted_licensing_info_fixture().license_id +EXTERNAL_DOCUMENT_ID = external_document_ref_fixture().document_ref_id + + +@pytest.mark.parametrize( + "expression_string", + [ + "MIT", + FIXTURE_LICENSE_ID, + f"GPL-2.0-only with GPL-CC-1.0 and {FIXTURE_LICENSE_ID} with 389-exception or Beerware", + f"{EXTERNAL_DOCUMENT_ID}:LicenseRef-007", + ], +) +def test_valid_license_expression(expression_string): + document: Document = document_fixture() + license_expression: LicenseExpression = spdx_licensing.parse(expression_string) + validation_messages: List[ValidationMessage] = validate_license_expression( + license_expression, document, parent_id="SPDXRef-File" + ) + + assert validation_messages == [] + + +@pytest.mark.parametrize("expression", [SpdxNone(), SpdxNoAssertion()]) +def test_none_and_no_assertion(expression): + document: Document = document_fixture() + validation_messages: List[ValidationMessage] = validate_license_expression( + expression, document, parent_id="SPDXRef-File" + ) + assert validation_messages == [] + + +@pytest.mark.parametrize( + "expression_list", + [ + [SpdxNone()], + [SpdxNoAssertion()], + [spdx_licensing.parse("MIT and GPL-3.0-only"), spdx_licensing.parse(FIXTURE_LICENSE_ID)], + [SpdxNone(), spdx_licensing.parse("MIT"), SpdxNoAssertion()], + ], +) +def test_valid_license_expressions(expression_list): + document: Document = document_fixture() + validation_messages: List[ValidationMessage] = validate_license_expressions( + expression_list, document, parent_id="SPDXRef-File" + ) + assert validation_messages == [] + + +@pytest.mark.parametrize( + "expression_string, unknown_symbols", + [ + (f"{FIXTURE_LICENSE_ID} or LicenseRef-22", ["LicenseRef-22"]), + ("nope with 389-exception and _.- or LicenseRef-10", ["nope", "_.-", "LicenseRef-10"]), + ], +) +def test_invalid_license_expression_with_unknown_symbols(expression_string, unknown_symbols): + document: Document = document_fixture() + license_expression: LicenseExpression = spdx_licensing.parse(expression_string) + parent_id = "SPDXRef-File" + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression + ) + + validation_messages: List[ValidationMessage] = validate_license_expression(license_expression, document, parent_id) + expected_messages = [ + ValidationMessage( + f"Unrecognized license reference: {symbol}. license_expression must only use IDs from the license list or " + f"extracted licensing info, but is: {license_expression}", + context, + ) + for symbol in unknown_symbols + ] + + TestCase().assertCountEqual(validation_messages, expected_messages) + + +@pytest.mark.parametrize( + "expression_string, expected_message", + [ + ( + "MIT with MIT", + 'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at ' + "position: 9. for license_expression: MIT WITH MIT", + ), + ( + f"GPL-2.0-or-later and {FIXTURE_LICENSE_ID} with {FIXTURE_LICENSE_ID}", + f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: ' + f'"{FIXTURE_LICENSE_ID}" at position: 39. for license_expression: GPL-2.0-or-later AND ' + f"{FIXTURE_LICENSE_ID} WITH {FIXTURE_LICENSE_ID}", + ), + ( + f"GPL-2.0-or-later with MIT and {FIXTURE_LICENSE_ID} with GPL-2.0-or-later", + f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at ' + f"position: 22. for license_expression: GPL-2.0-or-later WITH MIT AND {FIXTURE_LICENSE_ID} " + f"WITH GPL-2.0-or-later", + ), + ( + "389-exception with 389-exception", + 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: ' + '"389-exception". for license_expression: 389-exception WITH 389-exception', + ), + ( + "389-exception with MIT", + 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: ' + '"389-exception". for license_expression: 389-exception WITH MIT', + ), + ], +) +def test_invalid_license_expression_with_invalid_exceptions(expression_string, expected_message): + document: Document = document_fixture() + license_expression: LicenseExpression = spdx_licensing.parse(expression_string) + parent_id = "SPDXRef-File" + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression + ) + + validation_messages: List[ValidationMessage] = validate_license_expression(license_expression, document, parent_id) + expected_messages = [ValidationMessage(expected_message, context)] + + assert validation_messages == expected_messages + + +@pytest.mark.parametrize( + "expression_string, expected_message", + [ + ( + f"{EXTERNAL_DOCUMENT_ID}:LicenseRef-007:4", + f"Too many colons in license reference: {EXTERNAL_DOCUMENT_ID}:LicenseRef-007:4. " + "A license reference must only contain a single colon to " + "separate an external document reference from the license reference.", + ), + ( + f"{EXTERNAL_DOCUMENT_ID}:unknown_license", + 'A license reference must start with "LicenseRef-", but is: unknown_license ' + f"in external license reference {EXTERNAL_DOCUMENT_ID}:unknown_license.", + ), + ( + "DocumentRef-unknown:LicenseRef-1", + 'Did not find the external document reference "DocumentRef-unknown" in the SPDX document. ' + "From the external license reference DocumentRef-unknown:LicenseRef-1.", + ), + ], +) +def test_invalid_license_expression_with_external_reference(expression_string, expected_message): + document: Document = document_fixture() + license_expression: LicenseExpression = spdx_licensing.parse(expression_string) + parent_id = "SPDXRef-File" + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression + ) + + validation_messages: List[ValidationMessage] = validate_license_expression(license_expression, document, parent_id) + expected_messages = [ValidationMessage(expected_message, context)] + + assert validation_messages == expected_messages diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py new file mode 100644 index 000000000..d0516fff2 --- /dev/null +++ b/tests/spdx/validation/test_package_validator.py @@ -0,0 +1,156 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List +from unittest import TestCase + +import pytest + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.validation.package_validator import validate_package, validate_package_within_document +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture, package_verification_code_fixture + + +def test_valid_package(): + package = package_fixture() + validation_messages: List[ValidationMessage] = validate_package_within_document( + package, "SPDX-2.3", document_fixture() + ) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "package_input, expected_message", + [ + ( + package_fixture( + files_analyzed=False, verification_code=package_verification_code_fixture(), license_info_from_files=[] + ), + f"verification_code must be None if files_analyzed is False, but is: " + f"{package_verification_code_fixture()}", + ), + ( + package_fixture(files_analyzed=False, license_info_from_files=[SpdxNone()], verification_code=None), + "license_info_from_files must be None if files_analyzed is False, but is: [NONE]", + ), + ( + package_fixture(files_analyzed=False, license_info_from_files=[SpdxNoAssertion()], verification_code=None), + "license_info_from_files must be None if files_analyzed is False, but is: [NOASSERTION]", + ), + ( + package_fixture( + files_analyzed=False, + license_info_from_files=[spdx_licensing.parse("some_license")], + verification_code=None, + ), + "license_info_from_files must be None if files_analyzed is False, but is: [LicenseSymbol('some_license', " + "is_exception=False)]", + ), + ], +) +def test_invalid_package(package_input, expected_message): + validation_messages: List[ValidationMessage] = validate_package_within_document( + package_input, "SPDX-2.3", document_fixture(relationships=[]) + ) + + expected = ValidationMessage( + expected_message, + ValidationContext( + spdx_id=package_input.spdx_id, + parent_id=DOCUMENT_SPDX_ID, + element_type=SpdxElementType.PACKAGE, + full_element=package_input, + ), + ) + + assert validation_messages == [expected] + + +@pytest.mark.parametrize( + "relationships", + [ + [Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "DocumentRef-external:SPDXRef-File")], + [Relationship("DocumentRef-external:SPDXRef-File", RelationshipType.CONTAINED_BY, "SPDXRef-Package")], + ], +) +def test_valid_package_with_contains(relationships): + document = document_fixture( + relationships=relationships, + files=[file_fixture(spdx_id="SPDXRef-File1"), file_fixture(spdx_id="SPDXRef-File2")], + ) + package = package_fixture(files_analyzed=False, verification_code=None, license_info_from_files=[]) + + validation_messages: List[ValidationMessage] = validate_package_within_document(package, "SPDX-2.3", document) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "relationships", + [ + [Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File1")], + [Relationship("SPDXRef-File2", RelationshipType.CONTAINED_BY, "SPDXRef-Package")], + [ + Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File2"), + Relationship("SPDXRef-File1", RelationshipType.CONTAINED_BY, "SPDXRef-Package"), + ], + ], +) +def test_invalid_package_with_contains(relationships): + document = document_fixture( + relationships=relationships, + files=[file_fixture(spdx_id="SPDXRef-File1"), file_fixture(spdx_id="SPDXRef-File2")], + ) + package = package_fixture(files_analyzed=False, verification_code=None, license_info_from_files=[]) + context = ValidationContext( + spdx_id=package.spdx_id, + parent_id=document.creation_info.spdx_id, + element_type=SpdxElementType.PACKAGE, + full_element=package, + ) + + validation_messages: List[ValidationMessage] = validate_package_within_document(package, "SPDX-2.3", document) + + assert validation_messages == [ + ValidationMessage( + f"package must contain no elements if files_analyzed is False, but found {relationships}", context + ) + ] + + +def test_v2_3only_fields(): + package = package_fixture() + validation_messages: List[ValidationMessage] = validate_package(package, "SPDX-2.2") + + context = ValidationContext(spdx_id=package.spdx_id, element_type=SpdxElementType.PACKAGE, full_element=package) + unsupported_fields = ["primary_package_purpose", "built_date", "release_date", "valid_until_date"] + expected = [ValidationMessage(f"{field} is not supported in SPDX-2.2", context) for field in unsupported_fields] + + TestCase().assertCountEqual(validation_messages, expected) + + +def test_v2_2mandatory_fields(): + package = package_fixture( + license_concluded=None, + license_declared=None, + copyright_text=None, + primary_package_purpose=None, + built_date=None, + release_date=None, + valid_until_date=None, + ) + + assert validate_package(package, "SPDX-2.3") == [] + + validation_messages: List[ValidationMessage] = validate_package(package, "SPDX-2.2") + + context = ValidationContext(spdx_id=package.spdx_id, element_type=SpdxElementType.PACKAGE, full_element=package) + mandatory_fields = ["license_concluded", "license_declared", "copyright_text"] + expected = [ValidationMessage(f"{field} is mandatory in SPDX-2.2", context) for field in mandatory_fields] + + TestCase().assertCountEqual(validation_messages, expected) diff --git a/tests/spdx/validation/test_package_verification_code_validator.py b/tests/spdx/validation/test_package_verification_code_validator.py new file mode 100644 index 000000000..020bd8dd3 --- /dev/null +++ b/tests/spdx/validation/test_package_verification_code_validator.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.model import PackageVerificationCode +from spdx_tools.spdx.validation.package_verification_code_validator import validate_verification_code +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage + + +def test_valid_package_verification_code(): + code = PackageVerificationCode("71c4025dd9897b364f3ebbb42c484ff43d00791c", ["./excluded_file", "another.file"]) + validation_messages = validate_verification_code(code, "SPDXRef-Package") + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "code, expected_message", + [ + ( + PackageVerificationCode("71c4025dd9897b364f3ebbb42c484ff43d00791cab", []), + "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: " + "71c4025dd9897b364f3ebbb42c484ff43d00791cab (length: 42 digits)", + ), + ( + PackageVerificationCode("CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4", []), + "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: " + "CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)", + ), + ( + PackageVerificationCode("71c4025dd9897b364f3ebbb42c484ff43d00791c", ["/invalid/excluded/file"]), + 'file name must not be an absolute path starting with "/", but is: /invalid/excluded/file', + ), + ], +) +def test_invalid_package_verification_code(code, expected_message): + parent_id = "SPDXRef-Package" + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.PACKAGE_VERIFICATION_CODE, full_element=code + ) + validation_messages = validate_verification_code(code, parent_id) + + assert validation_messages == [ValidationMessage(expected_message, context)] diff --git a/tests/spdx/validation/test_relationship_validator.py b/tests/spdx/validation/test_relationship_validator.py new file mode 100644 index 000000000..28cae9d7d --- /dev/null +++ b/tests/spdx/validation/test_relationship_validator.py @@ -0,0 +1,76 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import Document, Relationship, RelationshipType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.validation.relationship_validator import validate_relationship +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import document_fixture, relationship_fixture + + +@pytest.mark.parametrize("related_spdx_element", ["SPDXRef-Package", SpdxNoAssertion(), SpdxNone()]) +def test_valid_relationship(related_spdx_element): + relationship = Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, related_spdx_element, comment="comment") + validation_messages: List[ValidationMessage] = validate_relationship(relationship, "SPDX-2.3", document_fixture()) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "spdx_element_id, related_spdx_element_id, expected_message", + [ + ( + "SPDXRef-unknownFile", + "SPDXRef-File", + 'did not find the referenced spdx_id "SPDXRef-unknownFile" in the SPDX document', + ), + ( + "SPDXRef-File", + "SPDXRef-unknownFile", + 'did not find the referenced spdx_id "SPDXRef-unknownFile" in the SPDX document', + ), + ], +) +def test_unknown_spdx_id(spdx_element_id, related_spdx_element_id, expected_message): + relationship: Relationship = relationship_fixture( + spdx_element_id=spdx_element_id, related_spdx_element_id=related_spdx_element_id + ) + validation_messages: List[ValidationMessage] = validate_relationship(relationship, "SPDX-2.3", document_fixture()) + + expected = ValidationMessage( + expected_message, ValidationContext(element_type=SpdxElementType.RELATIONSHIP, full_element=relationship) + ) + + assert validation_messages == [expected] + + +@pytest.mark.parametrize( + "relationship, expected_message", + [ + ( + Relationship(DOCUMENT_SPDX_ID, RelationshipType.SPECIFICATION_FOR, "SPDXRef-Package"), + "RelationshipType.SPECIFICATION_FOR is not supported in SPDX-2.2", + ), + ( + Relationship(DOCUMENT_SPDX_ID, RelationshipType.REQUIREMENT_DESCRIPTION_FOR, "SPDXRef-Package"), + "RelationshipType.REQUIREMENT_DESCRIPTION_FOR is not supported in SPDX-2.2", + ), + ], +) +def test_v2_3_only_types(relationship, expected_message): + document: Document = document_fixture() + + validation_message: List[ValidationMessage] = validate_relationship(relationship, "SPDX-2.2", document) + + expected = [ + ValidationMessage( + expected_message, ValidationContext(element_type=SpdxElementType.RELATIONSHIP, full_element=relationship) + ) + ] + + assert validation_message == expected diff --git a/tests/spdx/validation/test_snippet_validator.py b/tests/spdx/validation/test_snippet_validator.py new file mode 100644 index 000000000..8b8d2af4b --- /dev/null +++ b/tests/spdx/validation/test_snippet_validator.py @@ -0,0 +1,74 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import List +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.validation.snippet_validator import validate_snippet, validate_snippet_within_document +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import document_fixture, snippet_fixture + + +def test_valid_snippet(): + snippet = snippet_fixture() + validation_messages: List[ValidationMessage] = validate_snippet_within_document( + snippet, "SPDX-2.3", document_fixture() + ) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "snippet_input, expected_message", + [ + ( + snippet_fixture(byte_range=(-12, 45)), + "byte_range values must be greater than or equal to 1, but is: (-12, 45)", + ), + ( + snippet_fixture(byte_range=(45, 23)), + "the first value of byte_range must be less than or equal to the second, but is: (45, 23)", + ), + ( + snippet_fixture(line_range=(-12, 45)), + "line_range values must be greater than or equal to 1, but is: (-12, 45)", + ), + ( + snippet_fixture(line_range=(45, 23)), + "the first value of line_range must be less than or equal to the second, but is: (45, 23)", + ), + ], +) +def test_invalid_ranges(snippet_input, expected_message): + validation_messages: List[ValidationMessage] = validate_snippet_within_document( + snippet_input, "SPDX-2.3", document_fixture() + ) + + expected = ValidationMessage( + expected_message, + ValidationContext( + spdx_id=snippet_input.spdx_id, + parent_id=document_fixture().creation_info.spdx_id, + element_type=SpdxElementType.SNIPPET, + full_element=snippet_input, + ), + ) + + assert validation_messages == [expected] + + +def test_v2_2mandatory_fields(): + snippet = snippet_fixture(license_concluded=None, copyright_text=None) + + assert validate_snippet(snippet, "SPDX-2.3") == [] + + validation_messages: List[ValidationMessage] = validate_snippet(snippet, "SPDX-2.2") + + context = ValidationContext(spdx_id=snippet.spdx_id, element_type=SpdxElementType.SNIPPET, full_element=snippet) + mandatory_fields = ["license_concluded", "copyright_text"] + expected = [ValidationMessage(f"{field} is mandatory in SPDX-2.2", context) for field in mandatory_fields] + + TestCase().assertCountEqual(validation_messages, expected) diff --git a/tests/spdx/validation/test_spdx_id_validators.py b/tests/spdx/validation/test_spdx_id_validators.py new file mode 100644 index 000000000..8cc2d3b11 --- /dev/null +++ b/tests/spdx/validation/test_spdx_id_validators.py @@ -0,0 +1,172 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.validation.spdx_id_validators import ( + get_list_of_all_spdx_ids, + is_external_doc_ref_present_in_document, + is_spdx_id_present_in_document, + is_valid_external_doc_ref_id, + is_valid_internal_spdx_id, + validate_spdx_id, +) +from tests.spdx.fixtures import ( + creation_info_fixture, + document_fixture, + external_document_ref_fixture, + file_fixture, + package_fixture, + snippet_fixture, +) + +DOCUMENT = document_fixture( + files=[file_fixture(spdx_id="SPDXRef-File1"), file_fixture(spdx_id="SPDXRef-File2")], + packages=[package_fixture(spdx_id="SPDXRef-Package1"), package_fixture(spdx_id="SPDXRef-Package2")], + snippets=[snippet_fixture(spdx_id="SPDXRef-Snippet1"), snippet_fixture(spdx_id="SPDXRef-Snippet2")], + creation_info=creation_info_fixture( + external_document_refs=[ + external_document_ref_fixture(document_ref_id="DocumentRef-external"), + external_document_ref_fixture(document_ref_id="DocumentRef-1.2-ext"), + ] + ), +) + + +@pytest.mark.parametrize("spdx_id", [DOCUMENT_SPDX_ID, "SPDXRef-File1", "SPDXRef-1.3-3.7"]) +def test_valid_internal_spdx_ids(spdx_id): + assert is_valid_internal_spdx_id(spdx_id) + + +@pytest.mark.parametrize( + "spdx_id", ["spdxId", "spdxRef-DOCUMENT", "SPDXRef.File", "SPDXRef#Snippet", "SPDXRef-1.3_3.7"] +) +def test_invalid_internal_spdx_ids(spdx_id): + assert not is_valid_internal_spdx_id(spdx_id) + + +@pytest.mark.parametrize("doc_ref_id", ["DocumentRef-external", "DocumentRef-...+", "DocumentRef-v0.4.2-alpha"]) +def test_valid_external_doc_ref_ids(doc_ref_id): + assert is_valid_external_doc_ref_id(doc_ref_id) + + +@pytest.mark.parametrize( + "doc_ref_id", ["external-ref", "Documentref-external", "DocumentRef-...#", "DocumentRef-v0_4_2-alpha"] +) +def test_invalid_external_doc_ref_ids(doc_ref_id): + assert not is_valid_external_doc_ref_id(doc_ref_id) + + +def test_is_spdx_id_present_in_document(): + assert is_spdx_id_present_in_document("SPDXRef-File1", DOCUMENT) + assert is_spdx_id_present_in_document("SPDXRef-Package2", DOCUMENT) + assert is_spdx_id_present_in_document("SPDXRef-Snippet1", DOCUMENT) + assert is_spdx_id_present_in_document(DOCUMENT_SPDX_ID, DOCUMENT) + assert not is_spdx_id_present_in_document("SPDXRef-file2", DOCUMENT) + + +def test_is_external_doc_ref_present_in_document(): + assert is_external_doc_ref_present_in_document("DocumentRef-1.2-ext", DOCUMENT) + assert not is_external_doc_ref_present_in_document("DocumentRef-External1", DOCUMENT) + + +def test_list_of_all_spdx_ids(): + TestCase().assertCountEqual( + get_list_of_all_spdx_ids(DOCUMENT), + [ + DOCUMENT_SPDX_ID, + "SPDXRef-File1", + "SPDXRef-File2", + "SPDXRef-Package1", + "SPDXRef-Package2", + "SPDXRef-Snippet1", + "SPDXRef-Snippet2", + ], + ) + + +@pytest.mark.parametrize("spdx_id", ["DocumentRef-external:SPDXRef-File", "SPDXRef-Package"]) +def test_valid_spdx_id(spdx_id): + validation_messages = validate_spdx_id(spdx_id, DOCUMENT) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "spdx_id, expected_messages", + [ + ( + "DocumentRef-external:extern:SPDXRef-File", + [ + "spdx_id must not contain more than one colon in order to separate the external document reference id" + " from the internal SPDX id, but is: DocumentRef-external:extern:SPDXRef-File" + ], + ), + ( + "DocumentRef external:SPDXRef-File", + [ + 'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" ' + 'and must begin with "DocumentRef-", but is: DocumentRef external', + 'did not find the external document reference "DocumentRef external" in the SPDX document', + ], + ), + ( + "DocRef-ext:SPDXRef-File_2", + [ + 'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" ' + 'and must begin with "DocumentRef-", but is: DocRef-ext', + 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin ' + 'with "SPDXRef-", but is: SPDXRef-File_2', + 'did not find the external document reference "DocRef-ext" in the SPDX document', + ], + ), + ( + "DocumentRef-external:SPDXRef-File_2", + [ + 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin ' + 'with "SPDXRef-", but is: SPDXRef-File_2' + ], + ), + ( + "SPDXRef-42+", + [ + 'spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: ' + "SPDXRef-42+" + ], + ), + ], +) +def test_invalid_spdx_id(spdx_id, expected_messages): + validation_messages = validate_spdx_id(spdx_id, DOCUMENT) + + TestCase().assertCountEqual(validation_messages, expected_messages) + + +@pytest.mark.parametrize( + "spdx_id", + ["DocumentRef-external:SPDXRef-File", DOCUMENT_SPDX_ID, "SPDXRef-File1", "SPDXRef-Package1", "SPDXRef-Snippet1"], +) +def test_valid_spdx_id_with_check_document(spdx_id): + validation_messages = validate_spdx_id(spdx_id, DOCUMENT, check_document=True) + assert validation_messages == [] + + +def test_invalid_spdx_id_with_check_document(): + validation_messages = validate_spdx_id("SPDXRef-Filet", DOCUMENT, check_document=True) + assert validation_messages == ['did not find the referenced spdx_id "SPDXRef-Filet" in the SPDX document'] + + +@pytest.mark.parametrize("spdx_id", ["DocumentRef-external:SPDXRef-File", "SPDXRef-File1"]) +def test_valid_spdx_id_with_check_files(spdx_id): + validation_messages = validate_spdx_id(spdx_id, DOCUMENT, check_files=True) + assert validation_messages == [] + + +def test_invalid_spdx_id_with_check_files(): + validation_messages = validate_spdx_id("SPDXRef-Package1", DOCUMENT, check_files=True) + assert validation_messages == [ + 'did not find the referenced spdx_id "SPDXRef-Package1" in the SPDX document\'s files' + ] diff --git a/tests/spdx/validation/test_uri_validators.py b/tests/spdx/validation/test_uri_validators.py new file mode 100644 index 000000000..2d374ee8e --- /dev/null +++ b/tests/spdx/validation/test_uri_validators.py @@ -0,0 +1,137 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx.validation.uri_validators import validate_download_location, validate_uri, validate_url + + +@pytest.mark.parametrize( + "input_value", + [ + "https://some.url", + "https://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82...", + "http://some.url", + "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + ], +) +def test_valid_url(input_value): + assert validate_url(input_value) == [] + # URLs are also valid download locations: + assert validate_download_location(input_value) == [] + + +# TODO: more negative examples: https://github.com/spdx/tools-python/issues/377 +@pytest.mark.parametrize("input_value", [":::::", "http://testurl"]) +def test_invalid_url(input_value): + assert validate_url(input_value) == [f"must be a valid URL, but is: {input_value}"] + + +@pytest.mark.parametrize( + "input_value", + [ + "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "git://git.myproject.org/MyProject", + "git+https://git.myproject.org/MyProject.git", + "git+http://git.myproject.org/MyProject", + "git+ssh://git.myproject.org/MyProject.git", + "git+ssh://git@git.myproject.org/MyProject.git", + "git+git://git.myproject.org/MyProject", + "git+git@git.myproject.org:MyProject", + "git://git.myproject.org/MyProject#src/somefile.c", + "git+https://git.myproject.org/MyProject#src/Class.java", + "git://git.myproject.org/MyProject.git@master", + "git+https://git.myproject.org/MyProject.git@v1.0", + "git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709", + "git+https://git.myproject.org/MyProject.git@master#/src/MyClass.cpp", + "git+https://git.myproject.org/MyProject@da39a3ee5e6b4b0d3255bfef95601890afd80709#lib/variable.rb", + "hg+http://hg.myproject.org/MyProject", + "hg+https://hg.myproject.org/MyProject", + "hg+ssh://hg.myproject.org/MyProject", + "hg+https://hg.myproject.org/MyProject#src/somefile.c", + "hg+https://hg.myproject.org/MyProject#src/Class.java", + "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b", + "hg+https://hg.myproject.org/MyProject@2019", + "hg+https://hg.myproject.org/MyProject@v1.0", + "hg+https://hg.myproject.org/MyProject@special_feature", + "hg+https://hg.myproject.org/MyProject@master#/src/MyClass.cpp", + "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b#lib/variable.rb", + "svn://svn.myproject.org/svn/MyProject", + "svn+svn://svn.myproject.org/svn/MyProject", + "svn+http://svn.myproject.org/svn/MyProject/trunk", + "svn+https://svn.myproject.org/svn/MyProject/trunk", + "svn+https://svn.myproject.org/MyProject#src/somefile.c", + "svn+https://svn.myproject.org/MyProject#src/Class.java", + "svn+https://svn.myproject.org/MyProject/trunk#src/somefile.c", + "svn+https://svn.myproject.org/MyProject/trunk/src/somefile.c", + "svn+https://svn.myproject.org/svn/MyProject/trunk@2019", + "svn+https://svn.myproject.org/MyProject@123#/src/MyClass.cpp", + "svn+https://svn.myproject.org/MyProject/trunk@1234#lib/variable/variable.rb", + "bzr+https://bzr.myproject.org/MyProject/trunk", + "bzr+http://bzr.myproject.org/MyProject/trunk", + "bzr+sftp://myproject.org/MyProject/trunk", + "bzr+ssh://myproject.org/MyProject/trunk", + "bzr+ftp://myproject.org/MyProject/trunk", + "bzr+lp:MyProject", + "bzr+https://bzr.myproject.org/MyProject/trunk#src/somefile.c", + "bzr+https://bzr.myproject.org/MyProject/trunk#src/Class.java", + "bzr+https://bzr.myproject.org/MyProject/trunk@2019", + "bzr+http://bzr.myproject.org/MyProject/trunk@v1.0", + "bzr+https://bzr.myproject.org/MyProject/trunk@2019#src/somefile.c", + ], +) +def test_valid_package_download_location(input_value): + assert validate_download_location(input_value) == [] + + +# TODO: more negative examples: https://github.com/spdx/tools-python/issues/377 +@pytest.mark.parametrize( + "input_value", + [ + ":::::", + ], +) +def test_invalid_package_download_location(input_value): + assert validate_download_location(input_value) == [ + f"must be a valid URL or download location according to the specification, but is: {input_value}" + ] + + +@pytest.mark.parametrize( + "input_value", + [ + "https://some.uri", + "http:////some", + "https://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82...", + "h://someweirdtest^?", + "https://some.uri that goes on!?", + ], +) +def test_valid_uri(input_value): + message = validate_uri(input_value) + + assert message == [] + + +@pytest.mark.parametrize( + "input_value", ["/invalid/uri", "http//uri", "http://some#uri", "some/uri", "some weird test"] +) +def test_invalid_uri(input_value): + message = validate_uri(input_value) + + assert message == [ + f"must be a valid URI specified in RFC-3986 and must contain no fragment (#), but is: {input_value}" + ] + + +@pytest.mark.parametrize("input_value", ["://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82..."]) +@pytest.mark.skip( + "validate_uri() seems to invalidate URIs without scheme, so it does not run into this case. But I'm not sure yet " + "if this covers all scheme-less examples." + "https://github.com/spdx/tools-python/issues/377" +) +def test_uri_without_scheme(input_value): + message = validate_uri(input_value) + + assert message == [f"must have a URI scheme, but is: {input_value}"] diff --git a/tests/spdx/writer/__init__.py b/tests/spdx/writer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/writer/json/__init__.py b/tests/spdx/writer/json/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/writer/json/expected_results/__init__.py b/tests/spdx/writer/json/expected_results/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/writer/json/expected_results/expected.json b/tests/spdx/writer/json/expected_results/expected.json new file mode 100644 index 000000000..264cf0410 --- /dev/null +++ b/tests/spdx/writer/json/expected_results/expected.json @@ -0,0 +1,166 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "comment": "documentComment", + "creationInfo": { + "comment": "creatorComment", + "created": "2022-12-01T00:00:00Z", + "creators": [ + "Person: creatorName (some@mail.com)" + ], + "licenseListVersion": "3.19" + }, + "dataLicense": "CC0-1.0", + "documentNamespace": "https://some.namespace", + "externalDocumentRefs": [ + { + "checksum": { + "algorithm": "SHA1", + "checksumValue": "71c4025dd9897b364f3ebbb42c484ff43d00791c" + }, + "externalDocumentId": "DocumentRef-external", + "spdxDocument": "https://namespace.com" + } + ], + "files": [ + { + "SPDXID": "SPDXRef-File", + "annotations": [ + { + "annotationDate": "2022-12-24T00:00:00Z", + "annotationType": "REVIEW", + "annotator": "Person: annotatorName (some@mail.com)", + "comment": "annotationComment" + } + ], + "attributionTexts": [ + "fileAttributionText" + ], + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "71c4025dd9897b364f3ebbb42c484ff43d00791c" + } + ], + "comment": "fileComment", + "copyrightText": "copyrightText", + "fileContributors": [ + "fileContributor" + ], + "fileName": "./fileName.py", + "fileTypes": [ + "TEXT" + ], + "licenseComments": "licenseComment", + "licenseConcluded": "MIT AND GPL-2.0-only", + "licenseInfoInFiles": ["MIT", "GPL-2.0-only", "NOASSERTION"], + "noticeText": "fileNotice" + } + ], + "hasExtractedLicensingInfos": [ + { + "comment": "licenseComment", + "extractedText": "extractedText", + "licenseId": "LicenseRef-1", + "name": "licenseName", + "seeAlsos": [ + "https://see.also" + ] + } + ], + "name": "documentName", + "packages": [ + { + "SPDXID": "SPDXRef-Package", + "attributionTexts": [ + "packageAttributionText" + ], + "builtDate": "2022-11-02T00:00:00Z", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "71c4025dd9897b364f3ebbb42c484ff43d00791c" + } + ], + "comment": "packageComment", + "copyrightText": "packageCopyrightText", + "description": "packageDescription", + "downloadLocation": "https://download.com", + "externalRefs": [ + { + "comment": "externalPackageRefComment", + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "org.apache.tomcat:tomcat:9.0.0.M4", + "referenceType": "maven-central" + } + ], + "filesAnalyzed": true, + "homepage": "https://homepage.com", + "licenseComments": "packageLicenseComment", + "licenseConcluded": "MIT AND GPL-2.0-only", + "licenseDeclared": "MIT AND GPL-2.0-only", + "licenseInfoFromFiles": ["MIT", "GPL-2.0-only", "NOASSERTION"], + "name": "packageName", + "originator": "Person: originatorName (some@mail.com)", + "packageFileName": "./packageFileName", + "packageVerificationCode": { + "packageVerificationCodeExcludedFiles": [ + "./exclude.py" + ], + "packageVerificationCodeValue": "85ed0817af83a24ad8da68c2b5094de69833983c" + }, + "primaryPackagePurpose": "SOURCE", + "releaseDate": "2022-11-01T00:00:00Z", + "sourceInfo": "sourceInfo", + "summary": "packageSummary", + "supplier": "Person: supplierName (some@mail.com)", + "validUntilDate": "2022-11-03T00:00:00Z", + "versionInfo": "12.2" + } + ], + "relationships": [ + { + "comment": "relationshipComment", + "relatedSpdxElement": "SPDXRef-File", + "relationshipType": "DESCRIBES", + "spdxElementId": "SPDXRef-DOCUMENT" + } + ], + "snippets": [ + { + "SPDXID": "SPDXRef-Snippet", + "attributionTexts": [ + "snippetAttributionText" + ], + "comment": "snippetComment", + "copyrightText": "licenseCopyrightText", + "licenseComments": "snippetLicenseComment", + "licenseConcluded": "MIT AND GPL-2.0-only", + "licenseInfoInSnippets": ["MIT", "GPL-2.0-only", "NONE"], + "name": "snippetName", + "ranges": [ + { + "endPointer": { + "offset": 2, + "reference": "SPDXRef-File" + }, + "startPointer": { + "offset": 1, + "reference": "SPDXRef-File" + } + }, + { + "endPointer": { + "lineNumber": 4, + "reference": "SPDXRef-File" + }, + "startPointer": { + "lineNumber": 3, + "reference": "SPDXRef-File" + } + } + ], + "snippetFromFile": "SPDXRef-File" + } + ], + "spdxVersion": "SPDX-2.3" +} diff --git a/tests/spdx/writer/json/test_json_writer.py b/tests/spdx/writer/json/test_json_writer.py new file mode 100644 index 000000000..3f03844f8 --- /dev/null +++ b/tests/spdx/writer/json/test_json_writer.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import json +import os + +import pytest + +from spdx_tools.spdx.writer.json.json_writer import write_document_to_file +from tests.spdx.fixtures import document_fixture + + +@pytest.fixture +def temporary_file_path() -> str: + temporary_file_path = "temp_test_json_writer_output.json" + yield temporary_file_path + os.remove(temporary_file_path) + + +def test_write_json(temporary_file_path: str): + document = document_fixture() + write_document_to_file(document, temporary_file_path, validate=True) + + with open(temporary_file_path, encoding="utf-8") as written_file: + written_json = json.load(written_file) + + with open( + os.path.join(os.path.dirname(__file__), "expected_results", "expected.json"), encoding="utf-8" + ) as expected_file: + expected_json = json.load(expected_file) + + assert written_json == expected_json + + +def test_document_is_validated(): + document = document_fixture() + document.creation_info.spdx_id = "InvalidId" + + with pytest.raises(ValueError) as error: + write_document_to_file(document, "dummy_path") + assert "Document is not valid" in error.value.args[0] + + +def test_document_validation_can_be_overridden(temporary_file_path: str): + document = document_fixture() + document.creation_info.spdx_id = "InvalidId" + + write_document_to_file(document, temporary_file_path, validate=False) diff --git a/tests/spdx/writer/rdf/__init__.py b/tests/spdx/writer/rdf/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/writer/rdf/test_annotation_writer.py b/tests/spdx/writer/rdf/test_annotation_writer.py new file mode 100644 index 000000000..62f8b13a1 --- /dev/null +++ b/tests/spdx/writer/rdf/test_annotation_writer.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDF, RDFS, Graph, Literal, URIRef + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.annotation_writer import add_annotation_to_graph +from tests.spdx.fixtures import annotation_fixture + + +def test_add_annotation_to_graph(): + graph = Graph() + annotation = annotation_fixture() + + add_annotation_to_graph(annotation, graph, "docNamespace", {}) + + assert (URIRef("docNamespace#SPDXRef-File"), SPDX_NAMESPACE.annotation, None) in graph + assert (None, RDF.type, SPDX_NAMESPACE.Annotation) in graph + assert (None, SPDX_NAMESPACE.annotationType, SPDX_NAMESPACE.annotationType_review) in graph + assert (None, SPDX_NAMESPACE.annotationDate, Literal(datetime_to_iso_string(annotation.annotation_date))) in graph + assert (None, SPDX_NAMESPACE.annotator, Literal(annotation.annotator.to_serialized_string())) in graph + assert (None, RDFS.comment, Literal(annotation.annotation_comment)) in graph diff --git a/tests/spdx/writer/rdf/test_checksum_writer.py b/tests/spdx/writer/rdf/test_checksum_writer.py new file mode 100644 index 000000000..bbfa7358a --- /dev/null +++ b/tests/spdx/writer/rdf/test_checksum_writer.py @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest +from rdflib import RDF, Graph, Literal, URIRef + +from spdx_tools.spdx.model import ChecksumAlgorithm +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph, algorithm_to_rdf_string +from tests.spdx.fixtures import checksum_fixture + + +def test_add_checksum_to_graph(): + graph = Graph() + checksum = checksum_fixture() + + add_checksum_to_graph(checksum, graph, URIRef("parentNode")) + + assert (URIRef("parentNode"), SPDX_NAMESPACE.checksum, None) in graph + assert (None, RDF.type, SPDX_NAMESPACE.Checksum) in graph + assert (None, SPDX_NAMESPACE.algorithm, SPDX_NAMESPACE.checksumAlgorithm_sha1) in graph + assert (None, SPDX_NAMESPACE.checksumValue, Literal(checksum.value)) in graph + + +@pytest.mark.parametrize( + "algorithm,expected", + [ + (ChecksumAlgorithm.SHA1, SPDX_NAMESPACE.checksumAlgorithm_sha1), + (ChecksumAlgorithm.SHA224, SPDX_NAMESPACE.checksumAlgorithm_sha224), + (ChecksumAlgorithm.SHA256, SPDX_NAMESPACE.checksumAlgorithm_sha256), + (ChecksumAlgorithm.SHA384, SPDX_NAMESPACE.checksumAlgorithm_sha384), + (ChecksumAlgorithm.SHA512, SPDX_NAMESPACE.checksumAlgorithm_sha512), + (ChecksumAlgorithm.SHA3_256, SPDX_NAMESPACE.checksumAlgorithm_sha3_256), + (ChecksumAlgorithm.SHA3_384, SPDX_NAMESPACE.checksumAlgorithm_sha3_384), + (ChecksumAlgorithm.SHA3_512, SPDX_NAMESPACE.checksumAlgorithm_sha3_512), + (ChecksumAlgorithm.BLAKE2B_256, SPDX_NAMESPACE.checksumAlgorithm_blake2b256), + (ChecksumAlgorithm.BLAKE2B_384, SPDX_NAMESPACE.checksumAlgorithm_blake2b384), + (ChecksumAlgorithm.BLAKE2B_512, SPDX_NAMESPACE.checksumAlgorithm_blake2b512), + (ChecksumAlgorithm.BLAKE3, SPDX_NAMESPACE.checksumAlgorithm_blake3), + (ChecksumAlgorithm.MD2, SPDX_NAMESPACE.checksumAlgorithm_md2), + (ChecksumAlgorithm.MD4, SPDX_NAMESPACE.checksumAlgorithm_md4), + (ChecksumAlgorithm.MD5, SPDX_NAMESPACE.checksumAlgorithm_md5), + (ChecksumAlgorithm.MD6, SPDX_NAMESPACE.checksumAlgorithm_md6), + (ChecksumAlgorithm.ADLER32, SPDX_NAMESPACE.checksumAlgorithm_adler32), + ], +) +def test_algorithm_to_rdf_string(algorithm, expected): + rdf_element = algorithm_to_rdf_string(algorithm) + + assert rdf_element == expected diff --git a/tests/spdx/writer/rdf/test_creation_info_writer.py b/tests/spdx/writer/rdf/test_creation_info_writer.py new file mode 100644 index 000000000..4a0656e70 --- /dev/null +++ b/tests/spdx/writer/rdf/test_creation_info_writer.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDF, RDFS, Graph, Literal, URIRef + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.creation_info_writer import add_creation_info_to_graph +from tests.spdx.fixtures import creation_info_fixture + + +def test_add_creation_info_to_graph(): + graph = Graph() + creation_info = creation_info_fixture() + + add_creation_info_to_graph(creation_info, graph) + + assert (None, RDF.type, SPDX_NAMESPACE.SpdxDocument) in graph + assert (URIRef(f"{creation_info.document_namespace}#{creation_info.spdx_id}"), None, None) in graph + assert (None, SPDX_NAMESPACE.dataLicense, LICENSE_NAMESPACE[creation_info.data_license]) in graph + assert (None, SPDX_NAMESPACE.name, Literal(creation_info.name)) in graph + assert (None, SPDX_NAMESPACE.specVersion, Literal(creation_info.spdx_version)) in graph + assert (None, SPDX_NAMESPACE.creationInfo, None) in graph + + assert (None, RDF.type, SPDX_NAMESPACE.CreationInfo) in graph + assert (None, SPDX_NAMESPACE.created, Literal(datetime_to_iso_string(creation_info.created))) in graph + assert (None, RDFS.comment, Literal(creation_info.creator_comment)) in graph + assert (None, SPDX_NAMESPACE.licenseListVersion, Literal(creation_info.license_list_version)) in graph + assert (None, SPDX_NAMESPACE.creator, Literal(creation_info.creators[0].to_serialized_string())) in graph diff --git a/tests/spdx/writer/rdf/test_external_document_ref_writer.py b/tests/spdx/writer/rdf/test_external_document_ref_writer.py new file mode 100644 index 000000000..9197b39d9 --- /dev/null +++ b/tests/spdx/writer/rdf/test_external_document_ref_writer.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDF, Graph, URIRef + +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph +from tests.spdx.fixtures import external_document_ref_fixture + + +def test_add_external_document_ref_to_graph(): + graph = Graph() + external_document_ref = external_document_ref_fixture() + + add_external_document_ref_to_graph(external_document_ref, graph, URIRef("docNode"), "docNamespace") + + assert ( + URIRef("docNode"), + SPDX_NAMESPACE.externalDocumentRef, + URIRef("docNamespace#DocumentRef-external"), + ) in graph + assert (None, RDF.type, SPDX_NAMESPACE.ExternalDocumentRef) in graph + assert (None, SPDX_NAMESPACE.checksum, None) in graph + assert (None, RDF.type, SPDX_NAMESPACE.Checksum) in graph + assert (None, SPDX_NAMESPACE.spdxDocument, URIRef(external_document_ref.document_uri)) in graph diff --git a/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py new file mode 100644 index 000000000..b8fa1f871 --- /dev/null +++ b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDF, RDFS, Graph, Literal, URIRef + +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.extracted_licensing_info_writer import add_extracted_licensing_info_to_graph +from tests.spdx.fixtures import extracted_licensing_info_fixture + + +def test_add_extracted_licensing_info_to_graph(): + graph = Graph() + extracted_licensing_info = extracted_licensing_info_fixture() + + add_extracted_licensing_info_to_graph(extracted_licensing_info, graph, URIRef("docNode"), "docNamespace") + + assert (URIRef("docNode"), SPDX_NAMESPACE.hasExtractedLicensingInfo, None) in graph + assert (URIRef("docNamespace#LicenseRef-1"), RDF.type, SPDX_NAMESPACE.ExtractedLicensingInfo) in graph + assert (None, SPDX_NAMESPACE.licenseId, Literal(extracted_licensing_info.license_id)) in graph + assert (None, SPDX_NAMESPACE.extractedText, Literal(extracted_licensing_info.extracted_text)) in graph + assert (None, RDFS.seeAlso, Literal(extracted_licensing_info.cross_references[0])) in graph + assert (None, SPDX_NAMESPACE.name, Literal(extracted_licensing_info.license_name)) in graph + assert (None, RDFS.comment, Literal(extracted_licensing_info.comment)) in graph diff --git a/tests/spdx/writer/rdf/test_file_writer.py b/tests/spdx/writer/rdf/test_file_writer.py new file mode 100644 index 000000000..bcba0fd4e --- /dev/null +++ b/tests/spdx/writer/rdf/test_file_writer.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDF, RDFS, Graph, Literal, URIRef + +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.file_writer import add_file_to_graph +from tests.spdx.fixtures import file_fixture + + +def test_add_file_to_graph(): + graph = Graph() + file = file_fixture() + + add_file_to_graph(file, graph, "docNamespace", {}) + + assert (URIRef("docNamespace#SPDXRef-File"), RDF.type, SPDX_NAMESPACE.File) in graph + assert (None, SPDX_NAMESPACE.fileName, Literal(file.name)) in graph + assert (None, SPDX_NAMESPACE.fileType, SPDX_NAMESPACE.fileType_text) in graph + assert (None, SPDX_NAMESPACE.licenseComments, Literal(file.license_comment)) in graph + assert (None, SPDX_NAMESPACE.licenseConcluded, None) in graph + assert (None, SPDX_NAMESPACE.licenseInfoInFile, LICENSE_NAMESPACE.MIT) in graph + assert (None, SPDX_NAMESPACE.licenseInfoInFile, LICENSE_NAMESPACE["GPL-2.0-only"]) in graph + assert (None, SPDX_NAMESPACE.licenseInfoInFile, SPDX_NAMESPACE.noassertion) in graph + assert (None, SPDX_NAMESPACE.copyrightText, Literal(file.copyright_text)) in graph + assert (None, RDFS.comment, Literal(file.comment)) in graph + assert (None, SPDX_NAMESPACE.noticeText, Literal(file.notice)) in graph + assert (None, SPDX_NAMESPACE.fileContributor, Literal(file.contributors[0])) in graph + assert (None, SPDX_NAMESPACE.checksum, None) in graph + assert (None, SPDX_NAMESPACE.attributionText, Literal(file.attribution_texts[0])) in graph diff --git a/tests/spdx/writer/rdf/test_license_expression_writer.py b/tests/spdx/writer/rdf/test_license_expression_writer.py new file mode 100644 index 000000000..78fbec616 --- /dev/null +++ b/tests/spdx/writer/rdf/test_license_expression_writer.py @@ -0,0 +1,62 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest +from rdflib import RDF, Graph, Literal, URIRef + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_to_graph + + +def test_add_conjunctive_license_set_to_graph(): + graph = Graph() + license_expression = spdx_licensing.parse("MIT AND GPL-2.0") + + add_license_expression_to_graph( + license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, "https://namespace" + ) + + assert (URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, None) in graph + assert (None, RDF.type, SPDX_NAMESPACE.ConjunctiveLicenseSet) in graph + assert (None, SPDX_NAMESPACE.member, URIRef("http://spdx.org/licenses/MIT")) in graph + assert (None, SPDX_NAMESPACE.member, URIRef("http://spdx.org/licenses/GPL-2.0-only")) in graph + + +def test_add_disjunctive_license_set_to_graph(): + graph = Graph() + license_expression = spdx_licensing.parse("MIT OR GPL-2.0") + + add_license_expression_to_graph( + license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, "https://namespace" + ) + + assert (URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, None) in graph + assert (None, RDF.type, SPDX_NAMESPACE.DisjunctiveLicenseSet) in graph + assert (None, SPDX_NAMESPACE.member, URIRef("http://spdx.org/licenses/MIT")) in graph + assert (None, SPDX_NAMESPACE.member, URIRef("http://spdx.org/licenses/GPL-2.0-only")) in graph + + +@pytest.mark.parametrize( + "license_with_exception," "expected_triple", + [ + ( + "MIT WITH openvpn-openssl-exception", + (URIRef("http://spdx.org/licenses/openvpn-openssl-exception"), RDF.type, SPDX_NAMESPACE.LicenseException), + ), + ("MIT WITH unknown-exception", (None, SPDX_NAMESPACE.licenseExceptionId, Literal("unknown-exception"))), + ], +) +def test_license_exception_to_graph(license_with_exception, expected_triple): + graph = Graph() + license_expression = spdx_licensing.parse(license_with_exception) + + add_license_expression_to_graph( + license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, "https://namespace" + ) + + assert (URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, None) in graph + assert (None, RDF.type, SPDX_NAMESPACE.WithExceptionOperator) in graph + assert (None, SPDX_NAMESPACE.member, URIRef("http://spdx.org/licenses/MIT")) in graph + assert (None, SPDX_NAMESPACE.licenseException, None) in graph + assert expected_triple in graph diff --git a/tests/spdx/writer/rdf/test_package_writer.py b/tests/spdx/writer/rdf/test_package_writer.py new file mode 100644 index 000000000..2c0d5abbd --- /dev/null +++ b/tests/spdx/writer/rdf/test_package_writer.py @@ -0,0 +1,98 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest +from rdflib import DOAP, RDF, RDFS, XSD, Graph, Literal, URIRef + +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model import ExternalPackageRefCategory +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.package_writer import ( + add_external_package_ref_to_graph, + add_package_to_graph, + add_package_verification_code_to_graph, +) +from tests.spdx.fixtures import external_package_ref_fixture, package_fixture, package_verification_code_fixture + + +def test_add_package_to_graph(): + graph = Graph() + package = package_fixture() + + add_package_to_graph(package, graph, "docNamespace", {}) + + assert (URIRef("docNamespace#SPDXRef-Package"), RDF.type, SPDX_NAMESPACE.Package) in graph + assert (None, SPDX_NAMESPACE.name, Literal(package.name)) in graph + assert (None, SPDX_NAMESPACE.versionInfo, Literal(package.version)) in graph + assert (None, SPDX_NAMESPACE.packageFileName, Literal(package.file_name)) in graph + assert (None, SPDX_NAMESPACE.supplier, Literal(package.supplier.to_serialized_string())) in graph + assert (None, SPDX_NAMESPACE.originator, Literal(package.originator.to_serialized_string())) in graph + assert (None, SPDX_NAMESPACE.downloadLocation, Literal(package.download_location)) in graph + assert (None, SPDX_NAMESPACE.filesAnalyzed, Literal(package.files_analyzed, datatype=XSD.boolean)) in graph + assert (URIRef("docNamespace#SPDXRef-Package"), SPDX_NAMESPACE.packageVerificationCode, None) in graph + assert (URIRef("docNamespace#SPDXRef-Package"), SPDX_NAMESPACE.checksum, None) in graph + assert (None, DOAP.homepage, Literal(package.homepage)) in graph + assert (None, SPDX_NAMESPACE.sourceInfo, Literal(package.source_info)) in graph + assert (None, SPDX_NAMESPACE.licenseConcluded, None) in graph + assert (None, SPDX_NAMESPACE.licenseInfoFromFiles, LICENSE_NAMESPACE.MIT) in graph + assert (None, SPDX_NAMESPACE.licenseInfoFromFiles, LICENSE_NAMESPACE["GPL-2.0-only"]) in graph + assert (None, SPDX_NAMESPACE.licenseInfoFromFiles, SPDX_NAMESPACE.noassertion) in graph + assert (None, SPDX_NAMESPACE.licenseDeclared, None) in graph + assert (None, SPDX_NAMESPACE.licenseComments, Literal(package.license_comment)) in graph + assert (None, SPDX_NAMESPACE.copyrightText, Literal(package.copyright_text)) in graph + assert (None, SPDX_NAMESPACE.summary, Literal(package.summary)) in graph + assert (None, SPDX_NAMESPACE.description, Literal(package.description)) in graph + assert (None, RDFS.comment, Literal(package.comment)) in graph + assert (URIRef("docNamespace#SPDXRef-Package"), SPDX_NAMESPACE.externalRef, None) in graph + assert (None, SPDX_NAMESPACE.attributionText, Literal(package.attribution_texts[0])) in graph + assert (None, SPDX_NAMESPACE.primaryPackagePurpose, SPDX_NAMESPACE.purpose_source) in graph + assert (None, SPDX_NAMESPACE.releaseDate, Literal(datetime_to_iso_string(package.release_date))) in graph + assert (None, SPDX_NAMESPACE.builtDate, Literal(datetime_to_iso_string(package.built_date))) in graph + assert (None, SPDX_NAMESPACE.validUntilDate, Literal(datetime_to_iso_string(package.valid_until_date))) in graph + + +def test_add_package_verification_code_to_graph(): + graph = Graph() + verification_code = package_verification_code_fixture() + + add_package_verification_code_to_graph(verification_code, graph, URIRef("docNamespace")) + + assert (None, RDF.type, SPDX_NAMESPACE.PackageVerificationCode) in graph + assert ( + None, + SPDX_NAMESPACE.packageVerificationCodeValue, + Literal("85ed0817af83a24ad8da68c2b5094de69833983c"), + ) in graph + assert (None, SPDX_NAMESPACE.packageVerificationCodeExcludedFile, Literal("./exclude.py")) in graph + + +@pytest.mark.parametrize( + "external_reference,ref_type,category", + [ + ( + external_package_ref_fixture(), + URIRef("http://spdx.org/rdf/references/maven-central"), + SPDX_NAMESPACE.referenceCategory_packageManager, + ), + ( + external_package_ref_fixture( + locator="acmecorp/acmenator/4.1.3-alpha", + category=ExternalPackageRefCategory.OTHER, + reference_type="LocationRef-acmeforge", + comment="This is the external ref for Acme", + ), + URIRef("https://some.namespace#LocationRef-acmeforge"), + SPDX_NAMESPACE.referenceCategory_other, + ), + ], +) +def test_external_package_ref_to_graph(external_reference, ref_type, category): + graph = Graph() + doc_namespace = "https://some.namespace" + add_external_package_ref_to_graph(external_reference, graph, URIRef("docNamespace"), doc_namespace) + + assert (None, RDF.type, SPDX_NAMESPACE.ExternalRef) in graph + assert (None, SPDX_NAMESPACE.referenceCategory, category) in graph + assert (None, SPDX_NAMESPACE.referenceType, ref_type) in graph + assert (None, SPDX_NAMESPACE.referenceLocator, Literal(external_reference.locator)) in graph + assert (None, RDFS.comment, Literal(external_reference.comment)) in graph diff --git a/tests/spdx/writer/rdf/test_rdf_writer.py b/tests/spdx/writer/rdf/test_rdf_writer.py new file mode 100644 index 000000000..da6ae01bf --- /dev/null +++ b/tests/spdx/writer/rdf/test_rdf_writer.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os + +import pytest + +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.writer.rdf.rdf_writer import write_document_to_file +from tests.spdx.fixtures import document_fixture + + +@pytest.fixture +def temporary_file_path() -> str: + temporary_file_path = "temp_test_rdf_writer_output.rdf.xml" + yield temporary_file_path + os.remove(temporary_file_path) + + +def test_write_document_to_file(temporary_file_path: str): + document: Document = document_fixture() + + write_document_to_file(document, temporary_file_path, False) diff --git a/tests/spdx/writer/rdf/test_relationship_writer.py b/tests/spdx/writer/rdf/test_relationship_writer.py new file mode 100644 index 000000000..3019d9ec5 --- /dev/null +++ b/tests/spdx/writer/rdf/test_relationship_writer.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from rdflib import RDFS, Graph, Literal, URIRef + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.relationship_writer import add_relationship_to_graph +from tests.spdx.fixtures import relationship_fixture + + +def test_add_relationship_to_graph(): + relationship = relationship_fixture() + graph = Graph() + add_relationship_to_graph(relationship, graph, "docNamespace", {}) + + assert (URIRef(f"docNamespace#{DOCUMENT_SPDX_ID}"), SPDX_NAMESPACE.relationship, None) in graph + assert (None, SPDX_NAMESPACE.relationshipType, SPDX_NAMESPACE.relationshipType_describes) in graph + assert (None, SPDX_NAMESPACE.relatedSpdxElement, URIRef("docNamespace#SPDXRef-File")) in graph + assert (None, RDFS.comment, Literal(relationship.comment)) in graph diff --git a/tests/spdx/writer/rdf/test_snippet_writer.py b/tests/spdx/writer/rdf/test_snippet_writer.py new file mode 100644 index 000000000..6bc121396 --- /dev/null +++ b/tests/spdx/writer/rdf/test_snippet_writer.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest +from rdflib import RDF, RDFS, Graph, Literal, URIRef + +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.snippet_writer import add_range_to_graph, add_snippet_to_graph +from tests.spdx.fixtures import snippet_fixture + + +def test_add_snippet_to_graph(): + graph = Graph() + snippet = snippet_fixture() + + add_snippet_to_graph(snippet, graph, "docNamespace", {}) + + assert (URIRef("docNamespace#SPDXRef-Snippet"), RDF.type, SPDX_NAMESPACE.Snippet) in graph + assert (None, SPDX_NAMESPACE.snippetFromFile, URIRef(f"docNamespace#{snippet.file_spdx_id}")) in graph + assert (None, SPDX_NAMESPACE.licenseConcluded, None) in graph + assert (None, SPDX_NAMESPACE.licenseInfoInSnippet, LICENSE_NAMESPACE.MIT) in graph + assert (None, SPDX_NAMESPACE.licenseInfoInSnippet, LICENSE_NAMESPACE["GPL-2.0-only"]) in graph + assert (None, SPDX_NAMESPACE.licenseInfoInSnippet, SPDX_NAMESPACE.none) in graph + assert (None, SPDX_NAMESPACE.licenseComments, Literal(snippet.license_comment)) in graph + assert (None, SPDX_NAMESPACE.copyrightText, Literal(snippet.copyright_text)) in graph + assert (None, SPDX_NAMESPACE.name, Literal(snippet.name)) in graph + assert (None, SPDX_NAMESPACE.attributionText, Literal(snippet.attribution_texts[0])) in graph + assert (None, RDFS.comment, Literal(snippet.comment)) in graph + + +@pytest.mark.parametrize( + "range,pointer,predicate", + [ + ((5, 190), POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ((1, 3), POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + ], +) +def test_add_ranges_to_graph(range, pointer, predicate): + graph = Graph() + add_range_to_graph(range, graph, URIRef("snippetNode"), URIRef("docNamespace#SPDXRef-File"), pointer) + + assert (URIRef("snippetNode"), SPDX_NAMESPACE.range, None) in graph + assert (None, POINTER_NAMESPACE.startPointer, None) in graph + assert (None, POINTER_NAMESPACE.endPointer, None) in graph + assert (None, POINTER_NAMESPACE.reference, URIRef("docNamespace#SPDXRef-File")) in graph + assert (None, predicate, Literal(range[0])) in graph + assert (None, predicate, Literal(range[1])) in graph diff --git a/tests/spdx/writer/rdf/test_writer_utils.py b/tests/spdx/writer/rdf/test_writer_utils.py new file mode 100644 index 000000000..150dd8405 --- /dev/null +++ b/tests/spdx/writer/rdf/test_writer_utils.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id + + +@pytest.mark.parametrize( + "spdx_id,namespace,external_namespaces,expected", + [ + ("SPDXRef-File", "docNamespace", {}, "docNamespace#SPDXRef-File"), + ( + "externalDoc:SPDXRef-File", + "docNamespace", + {"externalDoc": "externalNamespace"}, + "externalNamespace#SPDXRef-File", + ), + ("externalDoc#A-Ref", "", {}, "externalDoc#A-Ref"), + ("externalDoc:A-Ref", "", {}, "externalDoc:A-Ref"), + ], +) +def test_add_namespace_to_spdx_id(spdx_id, namespace, expected, external_namespaces): + extended_spdx_id = add_namespace_to_spdx_id(spdx_id, namespace, external_namespaces) + + assert extended_spdx_id == expected diff --git a/tests/spdx/writer/tagvalue/__init__.py b/tests/spdx/writer/tagvalue/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/writer/tagvalue/expected_results/expected_tag_value.spdx b/tests/spdx/writer/tagvalue/expected_results/expected_tag_value.spdx new file mode 100644 index 000000000..ae6eb22c4 --- /dev/null +++ b/tests/spdx/writer/tagvalue/expected_results/expected_tag_value.spdx @@ -0,0 +1,54 @@ +## Document Information +SPDXVersion: spdxVersion +DataLicense: dataLicense +SPDXID: documentId +DocumentName: documentName +DocumentNamespace: documentNamespace +DocumentComment: comment + +## External Document References +ExternalDocumentRef: docRefId externalDocumentUri SHA1: externalRefSha1 + +## Creation Information +LicenseListVersion: spdxVersion +Creator: Tool: tools-python (tools-python@github.com) +Created: 2022-12-01T00:00:00Z + +## File Information +FileName: fileName +SPDXID: fileId +FileChecksum: SHA1: fileSha1 + +## Snippet Information +SnippetSPDXID: snippetId +SnippetFromFileSPDXID: fileId +SnippetByteRange: 1:2 + +## Package Information +PackageName: packageName +SPDXID: packageId +PackageDownloadLocation: NONE +FilesAnalyzed: True + +## License Information +LicenseID: licenseId +ExtractedText: licenseText + +## Relationships +Relationship: documentId DESCRIBES packageId +Relationship: documentId DESCRIBES fileId +RelationshipComment: relationshipComment +Relationship: relationshipOriginId AMENDS relationShipTargetId + +## Annotations +Annotator: Person: reviewerName +AnnotationDate: 2022-12-02T00:00:00Z +AnnotationType: REVIEW +SPDXREF: documentId +AnnotationComment: reviewComment + +Annotator: Tool: toolName +AnnotationDate: 2022-12-03T00:00:00Z +AnnotationType: OTHER +SPDXREF: fileId +AnnotationComment: otherComment diff --git a/tests/spdx/writer/tagvalue/test_annotation_writer.py b/tests/spdx/writer/tagvalue/test_annotation_writer.py new file mode 100644 index 000000000..974f01ec4 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_annotation_writer.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx_tools.spdx.writer.tagvalue.annotation_writer import write_annotation +from tests.spdx.fixtures import annotation_fixture + + +def test_annotation_writer(): + annotation = annotation_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_annotation(annotation, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call(f"Annotator: Person: {annotation.annotator.name} ({annotation.annotator.email})\n"), + call("AnnotationDate: 2022-12-24T00:00:00Z\n"), + call(f"AnnotationType: {annotation.annotation_type.name}\n"), + call(f"SPDXREF: {annotation.spdx_id}\n"), + call(f"AnnotationComment: {annotation.annotation_comment}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_checksum_writer.py b/tests/spdx/writer/tagvalue/test_checksum_writer.py new file mode 100644 index 000000000..ddc2474e0 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_checksum_writer.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.model import ChecksumAlgorithm +from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value +from tests.spdx.fixtures import checksum_fixture + + +@pytest.mark.parametrize( + "checksum, expected_string", + [ + (checksum_fixture(), "SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c"), + (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_256, value="fdsef"), "SHA3-256: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_384, value="fdsef"), "SHA3-384: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_512, value="fdsef"), "SHA3-512: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_256, value="fdsef"), "BLAKE2b-256: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_384, value="fdsef"), "BLAKE2b-384: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_512, value="fdsef"), "BLAKE2b-512: fdsef"), + ], +) +def test_checksum_writer(checksum, expected_string): + checksum_string = write_checksum_to_tag_value(checksum) + + assert checksum_string == expected_string diff --git a/tests/spdx/writer/tagvalue/test_creation_info_writer.py b/tests/spdx/writer/tagvalue/test_creation_info_writer.py new file mode 100644 index 000000000..133364c37 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_creation_info_writer.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2023 SPDX Contributors +# +# SPDX-License-Identifier: Apache-2.0 +import datetime +from unittest.mock import MagicMock, call, mock_open, patch + +import pytest + +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model import CreationInfo +from spdx_tools.spdx.writer.tagvalue.creation_info_writer import write_creation_info +from tests.spdx.fixtures import actor_fixture, creation_info_fixture + + +@pytest.mark.parametrize( + "creation_info, expected_calls", + [ + ( + creation_info_fixture(), + [ + call("SPDXVersion: SPDX-2.3\n"), + call("DataLicense: CC0-1.0\n"), + call(f"SPDXID: {DOCUMENT_SPDX_ID}\n"), + call("DocumentName: documentName\n"), + call("DocumentNamespace: https://some.namespace\n"), + call("DocumentComment: documentComment\n"), + call("\n## External Document References\n"), + call( + "ExternalDocumentRef: DocumentRef-external https://namespace.com " + "SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n" + ), + call("\n"), + call("## Creation Information\n"), + call("LicenseListVersion: 3.19\n"), + call("Creator: Person: creatorName (some@mail.com)\n"), + call("Created: 2022-12-01T00:00:00Z\n"), + call("CreatorComment: creatorComment\n"), + ], + ), + ( + CreationInfo( + spdx_version="SPDX-2.3", + spdx_id=DOCUMENT_SPDX_ID, + creators=[actor_fixture()], + name="Test document", + document_namespace="https://namespace.com", + created=datetime.datetime(2022, 3, 10), + ), + [ + call("SPDXVersion: SPDX-2.3\n"), + call("DataLicense: CC0-1.0\n"), + call(f"SPDXID: {DOCUMENT_SPDX_ID}\n"), + call("DocumentName: Test document\n"), + call("DocumentNamespace: https://namespace.com\n"), + call("\n"), + call("## Creation Information\n"), + call("Creator: Person: actorName (some@mail.com)\n"), + call("Created: 2022-03-10T00:00:00Z\n"), + ], + ), + ], +) +def test_creation_info_writer(creation_info, expected_calls): + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_creation_info(creation_info, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls(expected_calls) diff --git a/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py b/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py new file mode 100644 index 000000000..a0c70440a --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx_tools.spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info +from tests.spdx.fixtures import extracted_licensing_info_fixture + + +def test_extracted_licensing_info_writer(): + extracted_licensing_info = extracted_licensing_info_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_extracted_licensing_info(extracted_licensing_info, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call(f"LicenseID: {extracted_licensing_info.license_id}\n"), + call(f"ExtractedText: {extracted_licensing_info.extracted_text}\n"), + call(f"LicenseName: {extracted_licensing_info.license_name}\n"), + call(f"LicenseCrossReference: {extracted_licensing_info.cross_references[0]}\n"), + call(f"LicenseComment: {extracted_licensing_info.comment}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_file_writer.py b/tests/spdx/writer/tagvalue/test_file_writer.py new file mode 100644 index 000000000..c25998089 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_file_writer.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx_tools.spdx.writer.tagvalue.file_writer import write_file +from tests.spdx.fixtures import file_fixture + + +def test_file_writer(): + spdx_file = file_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_file(spdx_file, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## File Information\n"), + call(f"FileName: {spdx_file.name}\n"), + call(f"SPDXID: {spdx_file.spdx_id}\n"), + call(f"FileType: {spdx_file.file_types[0].name}\n"), + call("FileChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call(f"LicenseConcluded: {spdx_file.license_concluded}\n"), + call(f"LicenseInfoInFile: {spdx_file.license_info_in_file[0]}\n"), + call(f"LicenseInfoInFile: {spdx_file.license_info_in_file[1]}\n"), + call(f"LicenseInfoInFile: {spdx_file.license_info_in_file[2]}\n"), + call(f"LicenseComments: {spdx_file.license_comment}\n"), + call(f"FileCopyrightText: {spdx_file.copyright_text}\n"), + call(f"FileComment: {spdx_file.comment}\n"), + call(f"FileNotice: {spdx_file.notice}\n"), + call(f"FileContributor: {spdx_file.contributors[0]}\n"), + call(f"FileAttributionText: {spdx_file.attribution_texts[0]}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_package_writer.py b/tests/spdx/writer/tagvalue/test_package_writer.py new file mode 100644 index 000000000..994931ead --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_package_writer.py @@ -0,0 +1,56 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx_tools.spdx.writer.tagvalue.package_writer import write_package +from tests.spdx.fixtures import package_fixture + + +def test_package_writer(): + package = package_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_package(package, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## Package Information\n"), + call(f"PackageName: {package.name}\n"), + call(f"SPDXID: {package.spdx_id}\n"), + call(f"PackageVersion: {package.version}\n"), + call(f"PackageFileName: {package.file_name}\n"), + call(f"PackageSupplier: Person: {package.supplier.name} ({package.supplier.email})\n"), + call(f"PackageOriginator: Person: {package.originator.name} ({package.originator.email})\n"), + call(f"PackageDownloadLocation: {package.download_location}\n"), + call("FilesAnalyzed: true\n"), + call(f"PackageVerificationCode: {package.verification_code.value} (excludes: ./exclude.py)\n"), + call("PackageChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call(f"PackageHomePage: {package.homepage}\n"), + call(f"PackageSourceInfo: {package.source_info}\n"), + call(f"PackageLicenseConcluded: {package.license_concluded}\n"), + call(f"PackageLicenseInfoFromFiles: {package.license_info_from_files[0]}\n"), + call(f"PackageLicenseInfoFromFiles: {package.license_info_from_files[1]}\n"), + call(f"PackageLicenseInfoFromFiles: {package.license_info_from_files[2]}\n"), + call(f"PackageLicenseDeclared: {package.license_declared}\n"), + call(f"PackageLicenseComments: {package.license_comment}\n"), + call(f"PackageCopyrightText: {package.copyright_text}\n"), + call(f"PackageSummary: {package.summary}\n"), + call(f"PackageDescription: {package.description}\n"), + call(f"PackageComment: {package.comment}\n"), + call( + f"ExternalRef: PACKAGE-MANAGER {package.external_references[0].reference_type} " + f"{package.external_references[0].locator}\n" + ), + call(f"ExternalRefComment: {package.external_references[0].comment}\n"), + call(f"PackageAttributionText: {package.attribution_texts[0]}\n"), + call(f"PrimaryPackagePurpose: {package.primary_package_purpose.name}\n"), + call("ReleaseDate: 2022-11-01T00:00:00Z\n"), + call("BuiltDate: 2022-11-02T00:00:00Z\n"), + call("ValidUntilDate: 2022-11-03T00:00:00Z\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_relationship_writer.py b/tests/spdx/writer/tagvalue/test_relationship_writer.py new file mode 100644 index 000000000..9b207c33b --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_relationship_writer.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +import pytest + +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.writer.tagvalue.relationship_writer import write_relationship +from tests.spdx.fixtures import relationship_fixture + + +@pytest.mark.parametrize( + "relationship, expected_calls", + [ + ( + relationship_fixture(), + [ + call("Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-File\n"), + call("RelationshipComment: relationshipComment\n"), + ], + ), + ( + relationship_fixture(related_spdx_element_id=SpdxNoAssertion(), comment=None), + [call("Relationship: SPDXRef-DOCUMENT DESCRIBES NOASSERTION\n")], + ), + ( + relationship_fixture( + spdx_element_id="DocumentRef-External:SPDXRef-DOCUMENT", + related_spdx_element_id=SpdxNone(), + comment=None, + ), + [call("Relationship: DocumentRef-External:SPDXRef-DOCUMENT DESCRIBES NONE\n")], + ), + ], +) +def test_relationship_writer(relationship, expected_calls): + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_relationship(relationship, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls(expected_calls) diff --git a/tests/spdx/writer/tagvalue/test_snippet_writer.py b/tests/spdx/writer/tagvalue/test_snippet_writer.py new file mode 100644 index 000000000..4015908c1 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_snippet_writer.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx_tools.spdx.writer.tagvalue.snippet_writer import write_snippet +from tests.spdx.fixtures import snippet_fixture + + +def test_snippet_writer(): + snippet = snippet_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_snippet(snippet, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## Snippet Information\n"), + call(f"SnippetSPDXID: {snippet.spdx_id}\n"), + call(f"SnippetFromFileSPDXID: {snippet.file_spdx_id}\n"), + call("SnippetByteRange: 1:2\n"), + call("SnippetLineRange: 3:4\n"), + call(f"SnippetLicenseConcluded: {snippet.license_concluded}\n"), + call(f"LicenseInfoInSnippet: {snippet.license_info_in_snippet[0]}\n"), + call(f"LicenseInfoInSnippet: {snippet.license_info_in_snippet[1]}\n"), + call(f"LicenseInfoInSnippet: {snippet.license_info_in_snippet[2]}\n"), + call(f"SnippetLicenseComments: {snippet.license_comment}\n"), + call(f"SnippetCopyrightText: {snippet.copyright_text}\n"), + call(f"SnippetComment: {snippet.comment}\n"), + call(f"SnippetName: {snippet.name}\n"), + call(f"SnippetAttributionText: {snippet.attribution_texts[0]}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py new file mode 100644 index 000000000..487ee0dca --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py @@ -0,0 +1,221 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import os +from datetime import datetime +from unittest.mock import MagicMock, call, mock_open, patch + +import pytest + +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, + CreationInfo, + Document, + File, + Package, + Relationship, + RelationshipType, + Snippet, +) +from spdx_tools.spdx.parser.tagvalue import tagvalue_parser +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer import write_document, write_document_to_file +from tests.spdx.fixtures import checksum_fixture, document_fixture + + +@pytest.fixture +def temporary_file_path() -> str: + temporary_file_path = "temp_test_tag_value_writer_output.spdx" + yield temporary_file_path + os.remove(temporary_file_path) + + +def test_write_tag_value(temporary_file_path: str): + document = document_fixture() + + write_document_to_file(document, temporary_file_path, False) + + parsed_document = tagvalue_parser.parse_from_file(temporary_file_path) + + assert parsed_document == document + + +def test_correct_order_of_elements(): + packages = [ + Package(name="Test Package A", spdx_id="SPDXRef-Package-A", download_location=""), + Package(name="Test Package B", spdx_id="SPDXRef-Package-B", download_location=""), + ] + files = [ + File(name="Test File A", spdx_id="SPDXRef-File-A", checksums=[checksum_fixture()]), + File(name="Test File B", spdx_id="SPDXRef-File-B", checksums=[checksum_fixture()]), + ] + snippets = [ + Snippet(spdx_id="SPDXRef-Snippet-A", file_spdx_id="DocumentRef-External:SPDXRef-File", byte_range=(1, 2)), + Snippet(spdx_id="SPDXRef-Snippet-B", file_spdx_id="SPDXRef-File-A", byte_range=(1, 2)), + Snippet(spdx_id="SPDXRef-Snippet-C", file_spdx_id="SPDXRef-File-B", byte_range=(3, 4)), + ] + relationships = [Relationship("SPDXRef-Package-A", RelationshipType.CONTAINS, "SPDXRef-File-B")] + document = document_fixture( + files=files, + packages=packages, + snippets=snippets, + relationships=relationships, + annotations=[], + extracted_licensing_info=[], + ) + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_document(document, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## Document Information\n"), + call("SPDXVersion: SPDX-2.3\n"), + call("DataLicense: CC0-1.0\n"), + call("SPDXID: SPDXRef-DOCUMENT\n"), + call("DocumentName: documentName\n"), + call("DocumentNamespace: https://some.namespace\n"), + call("DocumentComment: documentComment\n"), + call("\n## External Document References\n"), + call( + "ExternalDocumentRef: DocumentRef-external https://namespace.com " + "SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n" + ), + call("\n"), + call("## Creation Information\n"), + call("LicenseListVersion: 3.19\n"), + call("Creator: Person: creatorName (some@mail.com)\n"), + call("Created: 2022-12-01T00:00:00Z\n"), + call("CreatorComment: creatorComment\n"), + call("\n"), + call("## Snippet Information\n"), + call("SnippetSPDXID: SPDXRef-Snippet-A\n"), + call("SnippetFromFileSPDXID: DocumentRef-External:SPDXRef-File\n"), + call("SnippetByteRange: 1:2\n"), + call("\n"), + call("## File Information\n"), + call("FileName: Test File A\n"), + call("SPDXID: SPDXRef-File-A\n"), + call("FileChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call("\n"), + call("## Snippet Information\n"), + call("SnippetSPDXID: SPDXRef-Snippet-B\n"), + call("SnippetFromFileSPDXID: SPDXRef-File-A\n"), + call("SnippetByteRange: 1:2\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Test Package A\n"), + call("SPDXID: SPDXRef-Package-A\n"), + call("PackageDownloadLocation: \n"), + call("FilesAnalyzed: true\n"), + call("\n"), + call("## File Information\n"), + call("FileName: Test File B\n"), + call("SPDXID: SPDXRef-File-B\n"), + call("FileChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call("\n"), + call("## Snippet Information\n"), + call("SnippetSPDXID: SPDXRef-Snippet-C\n"), + call("SnippetFromFileSPDXID: SPDXRef-File-B\n"), + call("SnippetByteRange: 3:4\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Test Package B\n"), + call("SPDXID: SPDXRef-Package-B\n"), + call("PackageDownloadLocation: \n"), + call("FilesAnalyzed: true\n"), + call("\n"), + call("\n"), + ] + ) + + +def test_same_file_in_multiple_packages(): + creation_info = CreationInfo( + spdx_version="SPDX-2.3", + spdx_id="SPDXRef-DOCUMENT", + data_license="CC0-1.0", + name="SPDX Lite Document", + document_namespace="https://test.namespace.com", + creators=[Actor(ActorType.PERSON, "John Doe")], + created=datetime(2023, 3, 14, 8, 49), + ) + package_a = Package( + name="Example package A", + spdx_id="SPDXRef-Package-A", + download_location="https://download.com", + ) + package_b = Package( + name="Example package B", + spdx_id="SPDXRef-Package-B", + download_location="https://download.com", + ) + file = File( + name="Example file", + spdx_id="SPDXRef-File", + checksums=[Checksum(ChecksumAlgorithm.SHA1, "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12")], + ) + + relationships = [ + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package-A"), + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package-B"), + Relationship("SPDXRef-Package-A", RelationshipType.CONTAINS, "SPDXRef-File"), + Relationship("SPDXRef-Package-B", RelationshipType.CONTAINS, "SPDXRef-File"), + ] + document = Document( + creation_info=creation_info, + packages=[package_a, package_b], + files=[file], + relationships=relationships, + ) + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_document(document, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## Document Information\n"), + call("SPDXVersion: SPDX-2.3\n"), + call("DataLicense: CC0-1.0\n"), + call("SPDXID: SPDXRef-DOCUMENT\n"), + call("DocumentName: SPDX Lite Document\n"), + call("DocumentNamespace: https://test.namespace.com\n"), + call("\n"), + call("## Creation Information\n"), + call("Creator: Person: John Doe\n"), + call("Created: 2023-03-14T08:49:00Z\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Example package A\n"), + call("SPDXID: SPDXRef-Package-A\n"), + call("PackageDownloadLocation: https://download.com\n"), + call("FilesAnalyzed: true\n"), + call("\n"), + call("## File Information\n"), + call("FileName: Example file\n"), + call("SPDXID: SPDXRef-File\n"), + call("FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Example package B\n"), + call("SPDXID: SPDXRef-Package-B\n"), + call("PackageDownloadLocation: https://download.com\n"), + call("FilesAnalyzed: true\n"), + call("\n"), + call("## Relationships\n"), + call("Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package-A\n"), + call("Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package-B\n"), + call("Relationship: SPDXRef-Package-B CONTAINS SPDXRef-File\n"), + call("\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py new file mode 100644 index 000000000..4949b434b --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py @@ -0,0 +1,74 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +import pytest + +from spdx_tools.spdx.model import ActorType, RelationshipType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships, write_actor +from tests.spdx.fixtures import actor_fixture, file_fixture, package_fixture, relationship_fixture + + +def test_scan_relationships(): + first_package_spdx_id = "SPDXRef-Package1" + second_package_spdx_id = "SPDXRef-Package2" + packages = [package_fixture(spdx_id=first_package_spdx_id), package_fixture(spdx_id=second_package_spdx_id)] + file_spdx_id = "SPDXRef-File" + files = [file_fixture(spdx_id=file_spdx_id)] + no_assertion_relationship = relationship_fixture( + spdx_element_id=second_package_spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=SpdxNoAssertion(), + comment=None, + ) + none_relationship = relationship_fixture( + spdx_element_id=second_package_spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=SpdxNone(), + comment=None, + ) + relationships = [ + relationship_fixture( + spdx_element_id=first_package_spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=file_spdx_id, + comment=None, + ), + relationship_fixture( + spdx_element_id=second_package_spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=file_spdx_id, + comment=None, + ), + no_assertion_relationship, + none_relationship, + ] + + relationships_to_write, contained_files_by_package_id = scan_relationships(relationships, packages, files) + + assert relationships_to_write == [no_assertion_relationship, none_relationship] + assert contained_files_by_package_id == {first_package_spdx_id: files, second_package_spdx_id: files} + + +@pytest.mark.parametrize( + "element_to_write, expected_calls", + [ + (actor_fixture(), [call("ActorTest: Person: actorName (some@mail.com)\n")]), + ( + actor_fixture(actor_type=ActorType.ORGANIZATION, name="organizationName"), + [call("ActorTest: Organization: organizationName (some@mail.com)\n")], + ), + (actor_fixture(actor_type=ActorType.TOOL, name="toolName", email=None), [call("ActorTest: Tool: toolName\n")]), + (SpdxNoAssertion(), [call("ActorTest: NOASSERTION\n")]), + ], +) +def test_write_actor(element_to_write, expected_calls): + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_actor("ActorTest", element_to_write, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls(expected_calls) diff --git a/tests/spdx3/__init__.py b/tests/spdx3/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/bump/__init__.py b/tests/spdx3/bump/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py new file mode 100644 index 000000000..e6606134e --- /dev/null +++ b/tests/spdx3/bump/test_actor_bump.py @@ -0,0 +1,84 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +import pytest +from semantic_version import Version + +from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor +from spdx_tools.spdx3.model import ( + CreationInfo, + ExternalIdentifier, + ExternalIdentifierType, + Organization, + Person, + ProfileIdentifierType, + Tool, +) +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.actor import Actor, ActorType + + +@pytest.mark.parametrize( + "actor_type, actor_name, actor_mail, element_type, new_spdx_id", + [ + (ActorType.PERSON, "person name", "person@mail.com", Person, "SPDXRef-Actor-personname-person@mail.com"), + ( + ActorType.ORGANIZATION, + "organization name", + "organization@mail.com", + Organization, + "SPDXRef-Actor-organizationname-organization@mail.com", + ), + (ActorType.TOOL, "tool name", None, Tool, "SPDXRef-Actor-toolname"), + ], +) +def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_id): + payload = Payload() + document_namespace = "https://doc.namespace" + creation_info = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [ProfileIdentifierType.CORE]) + actor = Actor(actor_type, actor_name, actor_mail) + + agent_or_tool_id = bump_actor(actor, payload, document_namespace, creation_info) + agent_or_tool = payload.get_element(agent_or_tool_id) + + assert isinstance(agent_or_tool, element_type) + assert agent_or_tool.spdx_id == f"{document_namespace}#{new_spdx_id}" + assert agent_or_tool.name == actor_name + if actor_mail: + assert len(agent_or_tool.external_identifier) == 1 + assert agent_or_tool.external_identifier[0] == ExternalIdentifier(ExternalIdentifierType.EMAIL, actor_mail) + else: + assert len(agent_or_tool.external_identifier) == 0 + + +def test_bump_actor_that_already_exists(): + creation_info_old = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [ProfileIdentifierType.CORE]) + creation_info_new = CreationInfo(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [ProfileIdentifierType.CORE]) + + name = "some name" + document_namespace = "https://doc.namespace" + payload = Payload( + { + "https://doc.namespace#SPDXRef-Actor-somename-some@mail.com": Person( + "https://doc.namespace#SPDXRef-Actor-somename-some@mail.com", creation_info_old, name + ) + } + ) + + actor = Actor(ActorType.PERSON, name, "some@mail.com") + agent_spdx_id = bump_actor(actor, payload, document_namespace, creation_info_new) + + # assert that there is only one Person in the payload + assert ( + len( + [ + payload.get_element(person_id) + for person_id in payload.get_full_map() + if isinstance(payload.get_element(person_id), Person) + ] + ) + == 1 + ) + assert payload.get_element(agent_spdx_id).creation_info == creation_info_old diff --git a/tests/spdx3/bump/test_bump_utils.py b/tests/spdx3/bump/test_bump_utils.py new file mode 100644 index 000000000..258ab19f9 --- /dev/null +++ b/tests/spdx3/bump/test_bump_utils.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone + + +@pytest.mark.parametrize( + "input_argument,expected_value,expected_stdout", + [ + (SpdxNone(), None, "test_field: Missing conversion for SpdxNone.\n"), + (SpdxNoAssertion(), None, ""), + ("test_string", "test_string", ""), + ], +) +def test_handle_no_assertion_or_none(input_argument, expected_value, expected_stdout, capsys): + value = handle_no_assertion_or_none(input_argument, "test_field") + + captured = capsys.readouterr() + + assert value == expected_value + assert captured.out == expected_stdout diff --git a/tests/spdx3/bump/test_checksum_bump.py b/tests/spdx3/bump/test_checksum_bump.py new file mode 100644 index 000000000..671653535 --- /dev/null +++ b/tests/spdx3/bump/test_checksum_bump.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum, convert_checksum_algorithm_to_hash_algorithm +from spdx_tools.spdx3.model import HashAlgorithm +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from tests.spdx.fixtures import checksum_fixture + + +def test_bump_checksum(): + checksum = checksum_fixture() + hash = bump_checksum(checksum) + + assert hash.algorithm == HashAlgorithm.SHA1 + assert hash.hash_value == "71c4025dd9897b364f3ebbb42c484ff43d00791c" + + +@pytest.mark.parametrize( + "checksum_algorithm,expected_hash_algorithm", + [ + (ChecksumAlgorithm.SHA1, HashAlgorithm.SHA1), + (ChecksumAlgorithm.SHA224, HashAlgorithm.SHA224), + (ChecksumAlgorithm.SHA256, HashAlgorithm.SHA256), + (ChecksumAlgorithm.SHA384, HashAlgorithm.SHA384), + (ChecksumAlgorithm.SHA512, HashAlgorithm.SHA512), + (ChecksumAlgorithm.SHA3_256, HashAlgorithm.SHA3_256), + (ChecksumAlgorithm.SHA3_384, HashAlgorithm.SHA3_384), + (ChecksumAlgorithm.SHA3_512, HashAlgorithm.SHA3_512), + (ChecksumAlgorithm.BLAKE2B_256, HashAlgorithm.BLAKE2B256), + (ChecksumAlgorithm.BLAKE2B_384, HashAlgorithm.BLAKE2B384), + (ChecksumAlgorithm.BLAKE2B_512, HashAlgorithm.BLAKE2B512), + (ChecksumAlgorithm.BLAKE3, HashAlgorithm.BLAKE3), + (ChecksumAlgorithm.MD2, HashAlgorithm.MD2), + (ChecksumAlgorithm.MD4, HashAlgorithm.MD4), + (ChecksumAlgorithm.MD5, HashAlgorithm.MD5), + (ChecksumAlgorithm.MD6, HashAlgorithm.MD6), + (ChecksumAlgorithm.ADLER32, HashAlgorithm.OTHER), + ], +) +def test_bump_checksum_algorithm(checksum_algorithm, expected_hash_algorithm): + hash_algorithm = convert_checksum_algorithm_to_hash_algorithm(checksum_algorithm) + + assert hash_algorithm == expected_hash_algorithm diff --git a/tests/spdx3/bump/test_external_document_ref_bump.py b/tests/spdx3/bump/test_external_document_ref_bump.py new file mode 100644 index 000000000..296a080c6 --- /dev/null +++ b/tests/spdx3/bump/test_external_document_ref_bump.py @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.creation_info import bump_creation_info +from spdx_tools.spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import ExternalDocumentRef +from tests.spdx.fixtures import checksum_fixture, creation_info_fixture, external_document_ref_fixture + + +def test_bump_external_document_ref(): + checksum = checksum_fixture() + external_document_ref = ExternalDocumentRef("DocumentRef-external", "https://external.uri", checksum) + namespace_map, imports = bump_external_document_ref(external_document_ref) + + assert namespace_map.prefix == "DocumentRef-external" + assert namespace_map.namespace == "https://external.uri#" + + assert imports.external_id == "DocumentRef-external:SPDXRef-DOCUMENT" + assert imports.verified_using == [bump_checksum(checksum)] + + +def test_bump_multiple_external_document_refs(): + payload = Payload() + creation_info = creation_info_fixture( + external_document_refs=[ + external_document_ref_fixture("DocumentRef-external1", "https://external.uri1"), + external_document_ref_fixture("DocumentRef-external2", "https://external.uri2"), + ] + ) + spdx_document = bump_creation_info(creation_info, payload) + + assert len(spdx_document.imports) == 2 + assert len(spdx_document.namespaces) == 2 diff --git a/tests/spdx3/bump/test_external_element_bump.py b/tests/spdx3/bump/test_external_element_bump.py new file mode 100644 index 000000000..887fa5f44 --- /dev/null +++ b/tests/spdx3/bump/test_external_element_bump.py @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from unittest import TestCase + +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx_tools.spdx3.model import ExternalMap +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import ExternalDocumentRef +from spdx_tools.spdx.model.document import Document as Spdx2_Document +from tests.spdx.fixtures import ( + checksum_fixture, + creation_info_fixture, + document_fixture, + file_fixture, + package_fixture, + snippet_fixture, +) + + +def test_bump_external_elements(): + external_doc_uri = "https://external-document.uri" + external_doc_id = "DocumentRef-external" + + full_external_doc_id = external_doc_id + ":SPDXRef-DOCUMENT" + package_id = external_doc_id + ":SPDXRef-Package" + file_id = external_doc_id + ":SPDXRef-File" + snippet_id = external_doc_id + ":SPDXRef-Snippet" + document_namespace = document_fixture().creation_info.document_namespace + + spdx2_document: Spdx2_Document = document_fixture( + creation_info=creation_info_fixture( + external_document_refs=[ExternalDocumentRef(external_doc_id, external_doc_uri, checksum_fixture())] + ), + packages=[package_fixture(spdx_id=package_id)], + files=[file_fixture(spdx_id=file_id)], + snippets=[snippet_fixture(spdx_id=snippet_id)], + ) + payload: Payload = bump_spdx_document(spdx2_document) + + expected_imports = [ + ExternalMap(external_id=package_id, defining_document=full_external_doc_id), + ExternalMap(external_id=file_id, defining_document=full_external_doc_id), + ExternalMap(external_id=snippet_id, defining_document=full_external_doc_id), + ExternalMap(external_id=full_external_doc_id, verified_using=[bump_checksum(checksum_fixture())]), + ] + spdx_document = payload.get_element(f"{document_namespace}#SPDXRef-DOCUMENT") + + assert f"{external_doc_uri}#SPDXRef-Package" in payload.get_full_map() + assert f"{external_doc_uri}#SPDXRef-File" in payload.get_full_map() + assert f"{external_doc_uri}#SPDXRef-Snippet" in payload.get_full_map() + + TestCase().assertCountEqual(spdx_document.imports, expected_imports) diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py new file mode 100644 index 000000000..06e93db42 --- /dev/null +++ b/tests/spdx3/bump/test_file_bump.py @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from spdx_tools.spdx3.bump_from_spdx2.file import bump_file +from spdx_tools.spdx3.model import Hash, HashAlgorithm +from spdx_tools.spdx3.model.software import File +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.file import File as Spdx2_File +from tests.spdx.fixtures import file_fixture + + +def test_bump_file(): + payload = Payload() + document_namespace = "https://doc.namespace" + spdx2_file: Spdx2_File = file_fixture() + integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") + expected_new_file_id = f"{document_namespace}#{spdx2_file.spdx_id}" + + bump_file(spdx2_file, payload, document_namespace, [], []) + file = payload.get_element(expected_new_file_id) + + assert isinstance(file, File) + assert file.spdx_id == expected_new_file_id + assert file.verified_using == [integrity_method] + assert file.copyright_text == spdx2_file.copyright_text + assert file.attribution_text == spdx2_file.attribution_texts[0] diff --git a/tests/spdx3/bump/test_license_expression_bump.py b/tests/spdx3/bump/test_license_expression_bump.py new file mode 100644 index 000000000..0f63299cf --- /dev/null +++ b/tests/spdx3/bump/test_license_expression_bump.py @@ -0,0 +1,108 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest +from license_expression import LicenseExpression + +from spdx_tools.common.spdx_licensing import spdx_licensing +from spdx_tools.spdx3.bump_from_spdx2.license_expression import ( + bump_license_expression, + bump_license_expression_or_none_or_no_assertion, +) +from spdx_tools.spdx3.model.licensing import ( + ConjunctiveLicenseSet, + CustomLicense, + CustomLicenseAddition, + DisjunctiveLicenseSet, + ListedLicense, + ListedLicenseException, + NoAssertionLicense, + NoneLicense, + WithAdditionOperator, +) +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from tests.spdx.fixtures import extracted_licensing_info_fixture + + +@pytest.mark.parametrize( + "element, expected_class", + [ + (SpdxNoAssertion(), NoAssertionLicense), + (SpdxNone(), NoneLicense), + (spdx_licensing.parse("MIT"), ListedLicense), + ], +) +def test_license_expression_or_none_or_no_assertion(element, expected_class): + license_info = bump_license_expression_or_none_or_no_assertion(element, []) + + assert isinstance(license_info, expected_class) + + +@pytest.mark.parametrize( + "license_expression, extracted_licensing_info, expected_element", + [ + (spdx_licensing.parse("MIT"), [], ListedLicense("MIT", "MIT", "blank")), + (spdx_licensing.parse("LGPL-2.0"), [], ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank")), + ( + spdx_licensing.parse("LicenseRef-1"), + [extracted_licensing_info_fixture()], + CustomLicense("LicenseRef-1", "licenseName", "extractedText"), + ), + ( + spdx_licensing.parse("MIT AND LGPL-2.0"), + [], + ConjunctiveLicenseSet( + [ListedLicense("MIT", "MIT", "blank"), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank")] + ), + ), + ( + spdx_licensing.parse("LicenseRef-1 OR LGPL-2.0"), + [extracted_licensing_info_fixture()], + DisjunctiveLicenseSet( + [ + CustomLicense("LicenseRef-1", "licenseName", "extractedText"), + ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank"), + ] + ), + ), + ( + spdx_licensing.parse("LGPL-2.0 WITH 389-exception"), + [], + WithAdditionOperator( + ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank"), + ListedLicenseException("389-exception", "", ""), + ), + ), + ( + spdx_licensing.parse("LicenseRef-1 WITH custom-exception"), + [ + extracted_licensing_info_fixture(), + extracted_licensing_info_fixture("custom-exception", "This is a custom exception", "exceptionName"), + ], + WithAdditionOperator( + CustomLicense("LicenseRef-1", "licenseName", "extractedText"), + CustomLicenseAddition("custom-exception", "exceptionName", "This is a custom exception"), + ), + ), + ( + spdx_licensing.parse("MIT AND LicenseRef-1 WITH custom-exception"), + [ + extracted_licensing_info_fixture(), + extracted_licensing_info_fixture("custom-exception", "This is a custom exception", "exceptionName"), + ], + ConjunctiveLicenseSet( + [ + ListedLicense("MIT", "MIT", "blank"), + WithAdditionOperator( + CustomLicense("LicenseRef-1", "licenseName", "extractedText"), + CustomLicenseAddition("custom-exception", "exceptionName", "This is a custom exception"), + ), + ] + ), + ), + ], +) +def test_license_expression_bump(license_expression: LicenseExpression, extracted_licensing_info, expected_element): + license_info = bump_license_expression(license_expression, extracted_licensing_info) + + assert license_info == expected_element diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py new file mode 100644 index 000000000..efef7933d --- /dev/null +++ b/tests/spdx3/bump/test_package_bump.py @@ -0,0 +1,131 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + +import pytest + +from spdx_tools.spdx3.bump_from_spdx2.package import bump_package +from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType, ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model.software import Package +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import SpdxNoAssertion +from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.model.package import Package as Spdx2_Package +from tests.spdx.fixtures import actor_fixture, package_fixture + + +@pytest.mark.parametrize( + "originator, expected_originator, supplier, expected_supplier", + [ + ( + actor_fixture(name="originatorName"), + ["https://doc.namespace#SPDXRef-Actor-originatorName-some@mail.com"], + actor_fixture(name="supplierName"), + ["https://doc.namespace#SPDXRef-Actor-supplierName-some@mail.com"], + ), + (None, [], None, []), + (SpdxNoAssertion(), [], SpdxNoAssertion(), []), + ], +) +def test_bump_package(originator, expected_originator, supplier, expected_supplier): + payload = Payload() + document_namespace = "https://doc.namespace" + spdx2_package: Spdx2_Package = package_fixture( + originator=originator, + supplier=supplier, + external_references=[ + ExternalPackageRef( + ExternalPackageRefCategory.SECURITY, "advisory", "advisory_locator", "advisory_comment" + ), + ExternalPackageRef(ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh_locator", "swh_comment"), + ], + ) + expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" + + bump_package(spdx2_package, payload, document_namespace, [], []) + package = payload.get_element(expected_new_package_id) + + assert isinstance(package, Package) + assert package.spdx_id == expected_new_package_id + assert package.package_version == spdx2_package.version + assert package.external_reference == [ + ExternalReference(ExternalReferenceType.SECURITY_ADVISORY, ["advisory_locator"], None, "advisory_comment") + ] + assert package.external_identifier == [ + ExternalIdentifier(ExternalIdentifierType.SWHID, "swh_locator", "swh_comment") + ] + assert package.download_location == spdx2_package.download_location + assert package.package_version == spdx2_package.version + assert package.originated_by == expected_originator + assert package.supplied_by == expected_supplier + assert package.homepage == spdx2_package.homepage + assert package.source_info == spdx2_package.source_info + assert package.built_time == spdx2_package.built_date + assert package.release_time == spdx2_package.release_date + assert package.valid_until_time == spdx2_package.valid_until_date + assert package.copyright_text == spdx2_package.copyright_text + assert package.attribution_text == spdx2_package.attribution_texts[0] + + +def test_bump_of_single_purl_without_comment(): + payload = Payload() + document_namespace = "https://doc.namespace" + spdx2_package: Spdx2_Package = package_fixture( + external_references=[ + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator", None), + ] + ) + expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" + + bump_package(spdx2_package, payload, document_namespace, [], []) + package = payload.get_element(expected_new_package_id) + + assert package.package_url == "purl_locator" + assert package.external_reference == [] + assert package.external_identifier == [] + + +def test_bump_of_single_purl_with_comment(): + payload = Payload() + document_namespace = "https://doc.namespace" + spdx2_package: Spdx2_Package = package_fixture( + external_references=[ + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator", "purl_comment"), + ] + ) + expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" + + bump_package(spdx2_package, payload, document_namespace, [], []) + package = payload.get_element(expected_new_package_id) + + assert package.package_url is None + assert package.external_reference == [] + assert package.external_identifier == [ + ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator", "purl_comment") + ] + + +def test_bump_of_multiple_purls(): + payload = Payload() + document_namespace = "https://doc.namespace" + spdx2_package: Spdx2_Package = package_fixture( + external_references=[ + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator", "comment"), + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator2", None), + ] + ) + expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" + + bump_package(spdx2_package, payload, document_namespace, [], []) + package = payload.get_element(expected_new_package_id) + + assert package.package_url is None + assert package.external_reference == [] + TestCase().assertCountEqual( + package.external_identifier, + [ + ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator", "comment"), + ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator2", None), + ], + ) diff --git a/tests/spdx3/bump/test_relationship_bump.py b/tests/spdx3/bump/test_relationship_bump.py new file mode 100644 index 000000000..cd2910268 --- /dev/null +++ b/tests/spdx3/bump/test_relationship_bump.py @@ -0,0 +1,99 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.bump_from_spdx2.relationship import bump_relationship, bump_relationships +from spdx_tools.spdx3.model import Relationship, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import RelationshipType as Spdx2_RelationshipType +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from tests.spdx.fixtures import relationship_fixture + + +def test_relationship_bump(): + spdx2_relationship = relationship_fixture() + document_namespace = "https://doc.namespace" + relationship = bump_relationship(spdx2_relationship, document_namespace, 1) + + assert relationship == Relationship( + f"{document_namespace}#SPDXRef-Relationship-1", + f"{document_namespace}#{spdx2_relationship.spdx_element_id}", + RelationshipType.DESCRIBES, + [f"{document_namespace}#{spdx2_relationship.related_spdx_element_id}"], + comment=spdx2_relationship.comment, + ) + + +def test_relationships_bump(): + relationships = [ + relationship_fixture(comment=None), + relationship_fixture(related_spdx_element_id="SPDXRef-Package", comment=None), + ] + payload = Payload() + document_namespace = "https://doc.namespace" + bump_relationships(relationships, payload, document_namespace) + + assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-1") == Relationship( + f"{document_namespace}#SPDXRef-Relationship-1", + f"{document_namespace}#{relationships[0].spdx_element_id}", + RelationshipType.DESCRIBES, + [ + f"{document_namespace}#{relationships[0].related_spdx_element_id}", + f"{document_namespace}#{relationships[1].related_spdx_element_id}", + ], + ) + + +def test_relationships_bump_with_setting_completeness(): + relationships = [ + relationship_fixture(related_spdx_element_id=SpdxNoAssertion()), + relationship_fixture(related_spdx_element_id="SPDXRef-Package"), + relationship_fixture( + relationship_type=Spdx2_RelationshipType.SPECIFICATION_FOR, + related_spdx_element_id=SpdxNone(), + comment=None, + ), + ] + payload = Payload() + document_namespace = "https://doc.namespace" + bump_relationships(relationships, payload, document_namespace) + + assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-0") == Relationship( + f"{document_namespace}#SPDXRef-Relationship-0", + f"{document_namespace}#{relationships[0].spdx_element_id}", + RelationshipType.DESCRIBES, + [], + comment=relationships[0].comment, + completeness=RelationshipCompleteness.NOASSERTION, + ) + assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-1") == Relationship( + f"{document_namespace}#SPDXRef-Relationship-1", + f"{document_namespace}#{relationships[1].spdx_element_id}", + RelationshipType.DESCRIBES, + [f"{document_namespace}#{relationships[1].related_spdx_element_id}"], + comment=relationships[1].comment, + ) + assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-2") == Relationship( + f"{document_namespace}#SPDXRef-Relationship-2", + f"{document_namespace}#{relationships[2].spdx_element_id}", + RelationshipType.SPECIFICATION_FOR, + [], + completeness=RelationshipCompleteness.COMPLETE, + ) + + +def test_undefined_relationship_bump(capsys): + relationships = [ + relationship_fixture( + related_spdx_element_id=SpdxNoAssertion(), relationship_type=Spdx2_RelationshipType.CONTAINED_BY + ), + relationship_fixture(relationship_type=Spdx2_RelationshipType.OPTIONAL_COMPONENT_OF), + ] + payload = Payload() + document_namespace = "https://doc.namespace" + bump_relationships(relationships, payload, document_namespace) + + captured = capsys.readouterr() + assert ( + captured.err == "Swapped Relationship to NoAssertion/None not converted: missing conversion rule \n" + "OPTIONAL_COMPONENT_OF not converted: missing conversion rule \n" + ) diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py new file mode 100644 index 000000000..1ded094b6 --- /dev/null +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet +from spdx_tools.spdx3.model.software import Snippet +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet +from tests.spdx.fixtures import snippet_fixture + + +def test_bump_snippet(): + payload = Payload() + document_namespace = "https://doc.namespace" + spdx2_snippet: Spdx2_Snippet = snippet_fixture() + expected_new_snippet_id = f"{document_namespace}#{spdx2_snippet.spdx_id}" + + bump_snippet(spdx2_snippet, payload, document_namespace, [], []) + snippet = payload.get_element(expected_new_snippet_id) + + assert isinstance(snippet, Snippet) + assert snippet.spdx_id == expected_new_snippet_id + assert snippet.copyright_text == spdx2_snippet.copyright_text + assert snippet.attribution_text == spdx2_snippet.attribution_texts[0] diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py new file mode 100644 index 000000000..14a165381 --- /dev/null +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import sys + +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.console.payload_writer import write_payload +from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.model.document import Document as Spdx2_Document +from tests.spdx.fixtures import actor_fixture, annotation_fixture, creation_info_fixture, document_fixture + + +def test_bump_spdx_document(): + spdx2_document: Spdx2_Document = document_fixture() + spdx2_document.creation_info.creators.append(actor_fixture(ActorType.TOOL, "tool_name", None)) + document_namespace = document_fixture().creation_info.document_namespace + + payload: Payload = bump_spdx_document(spdx2_document) + + write_payload(payload, sys.stdout) + + assert f"{document_namespace}#SPDXRef-Package" in payload.get_full_map() + assert len(payload.get_full_map()) == 11 + + # this is more of a temporary test to make sure the dates don't get messed up again + assert ( + payload.get_element("#".join([document_namespace, "SPDXRef-DOCUMENT"])).creation_info.created + == creation_info_fixture().created + ) + assert ( + payload.get_element("#".join([document_namespace, "SPDXRef-Annotation-0"])).creation_info.created + == annotation_fixture().annotation_date + ) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py new file mode 100644 index 000000000..9d7e5fd24 --- /dev/null +++ b/tests/spdx3/fixtures.py @@ -0,0 +1,557 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import Any, Dict, Type + +from semantic_version import Version + +from spdx_tools.spdx3.model import ( + Agent, + Annotation, + AnnotationType, + Bom, + Bundle, + CreationInfo, + ExternalIdentifier, + ExternalIdentifierType, + ExternalMap, + ExternalReference, + ExternalReferenceType, + Hash, + HashAlgorithm, + LifecycleScopedRelationship, + LifecycleScopeType, + NamespaceMap, + Organization, + Person, + ProfileIdentifierType, + Relationship, + RelationshipCompleteness, + RelationshipType, + SoftwareAgent, + SpdxDocument, + Tool, +) +from spdx_tools.spdx3.model.ai.ai_package import AIPackage, SafetyRiskAssessmentType +from spdx_tools.spdx3.model.build import Build +from spdx_tools.spdx3.model.dataset.dataset import ( + ConfidentialityLevelType, + Dataset, + DatasetAvailabilityType, + DatasetType, +) +from spdx_tools.spdx3.model.licensing import ( + CustomLicense, + CustomLicenseAddition, + ListedLicense, + ListedLicenseException, +) +from spdx_tools.spdx3.model.positive_integer_range import PositiveIntegerRange +from spdx_tools.spdx3.model.security import ( + CvssV2VulnAssessmentRelationship, + CvssV3VulnAssessmentRelationship, + EpssVulnAssessmentRelationship, + ExploitCatalogType, + ExploitCatalogVulnAssessmentRelationship, + SsvcDecisionType, + SsvcVulnAssessmentRelationship, + VexAffectedVulnAssessmentRelationship, + VexFixedVulnAssessmentRelationship, + VexJustificationType, + VexNotAffectedVulnAssessmentRelationship, + VexUnderInvestigationVulnAssessmentRelationship, + Vulnerability, +) +from spdx_tools.spdx3.model.software import ( + DependencyConditionalityType, + File, + Package, + Sbom, + SBOMType, + Snippet, + SoftwareDependencyLinkType, + SoftwareDependencyRelationship, + SoftwarePurpose, +) + +"""Utility methods to create data model instances. All properties have valid defaults, so they don't need to be +specified unless relevant for the test.""" + + +def creation_info_fixture( + spec_version=Version("3.0.0"), + created=datetime(2022, 12, 1), + created_by=None, + created_using=None, + profile=None, + data_license="CC0-1.0", + comment="creationInfoComment", +) -> CreationInfo: + created_by = ["https://spdx.test/tools-python/creation_info_created_by"] if created_by is None else created_by + created_using = ( + ["https://spdx.test/tools-python/creation_info_created_using"] if created_using is None else created_using + ) + profile = ( + [ProfileIdentifierType.CORE, ProfileIdentifierType.SOFTWARE, ProfileIdentifierType.LICENSING] + if profile is None + else profile + ) + return CreationInfo( + spec_version=spec_version, + created=created, + created_by=created_by, + profile=profile, + data_license=data_license, + created_using=created_using, + comment=comment, + ) + + +def external_identifier_fixture( + external_identifier_type=ExternalIdentifierType.OTHER, + identifier="externalIdentifierIdentifier", + comment="externalIdentifierComment", + identifier_locator=None, + issuing_authority="https://spdx.test/tools-python/external_identifier_issuing_authority", +) -> ExternalIdentifier: + identifier_locator = ( + ["https://spdx.test/tools-python/external_identifier_identifier_locator"] + if identifier_locator is None + else identifier_locator + ) + return ExternalIdentifier( + external_identifier_type=external_identifier_type, + identifier=identifier, + comment=comment, + identifier_locator=identifier_locator, + issuing_authority=issuing_authority, + ) + + +def external_reference_fixture( + external_reference_type=ExternalReferenceType.OTHER, + locator=None, + content_type="externalReferenceContentType", + comment="externalReferenceComment", +) -> ExternalReference: + locator = ["org.apache.tomcat:tomcat:9.0.0.M4"] if locator is None else locator + return ExternalReference( + external_reference_type=external_reference_type, locator=locator, content_type=content_type, comment=comment + ) + + +def hash_fixture( + algorithm=HashAlgorithm.SHA1, + hash_value="71c4025dd9897b364f3ebbb42c484ff43d00791c", + comment="hashComment", +) -> Hash: + return Hash(algorithm=algorithm, hash_value=hash_value, comment=comment) + + +def external_map_fixture( + external_id="https://spdx.test/tools-python/external_map_external_id", + verified_using=None, + location_hint="https://spdx.test/tools-python/external_map_location_hint", + defining_document="https://spdx.test/tools-python/defining_document", +) -> ExternalMap: + verified_using = [hash_fixture()] if verified_using is None else verified_using + return ExternalMap( + external_id=external_id, + verified_using=verified_using, + location_hint=location_hint, + defining_document=defining_document, + ) + + +def namespace_map_fixture( + prefix="namespaceMapPrefix", namespace="https://spdx.test/tools-python/namespace_map_namespace" +) -> NamespaceMap: + return NamespaceMap(prefix=prefix, namespace=namespace) + + +def listed_license_fixture( + license_id="https://spdx.test/tools-python/license_id", + license_name="license name", + license_text="license text", + license_comment="license comment", + see_also=None, + is_osi_approved=True, + is_fsf_libre=True, + standard_license_header="license header", + standard_license_template="license template", + is_deprecated_license_id=True, + obsoleted_by="https://spdx.test/tools-python/obsoleted_by_license_id", + list_version_added="2.1", + deprecated_version="2.2", +): + see_also = ["https://see.also/license"] if see_also is None else see_also + return ListedLicense( + license_id=license_id, + license_name=license_name, + license_text=license_text, + license_comment=license_comment, + see_also=see_also, + is_osi_approved=is_osi_approved, + is_fsf_libre=is_fsf_libre, + standard_license_header=standard_license_header, + standard_license_template=standard_license_template, + is_deprecated_license_id=is_deprecated_license_id, + obsoleted_by=obsoleted_by, + list_version_added=list_version_added, + deprecated_version=deprecated_version, + ) + + +ELEMENT_DICT = { + "spdx_id": "https://spdx.test/tools-python/element_fixture", + "creation_info": creation_info_fixture(), + "name": "elementName", + "summary": "elementSummary", + "description": "elementDescription", + "comment": "elementComment", + "verified_using": [hash_fixture()], + "external_reference": [external_reference_fixture()], + "external_identifier": [external_identifier_fixture()], + "extension": "extensionPlaceholder", +} + +RELATIONSHIP_DICT = { + "from_element": "https://spdx.test/tools-python/relationship_from_element", + "relationship_type": RelationshipType.OTHER, + "to": ["https://spdx.test/tools-python/relationship_to"], + "completeness": RelationshipCompleteness.COMPLETE, + "start_time": datetime(2020, 1, 1), + "end_time": datetime(2023, 1, 1), +} + +LIFECYCLE_SCOPED_RELATIONSHIP_DICT = {"scope": LifecycleScopeType.DESIGN} + +ANNOTATION_DICT = { + "annotation_type": AnnotationType.OTHER, + "subject": "https://spdx.test/tools-python/annotation_subject", + "content_type": ["annotationContent"], + "statement": "annotationStatement", +} + +ELEMENT_COLLECTION_DICT = { + "element": ["https://spdx.test/tools-python/collection_element"], + "root_element": ["https://spdx.test/tools-python/collection_root_element"], + "namespaces": [namespace_map_fixture()], + "imports": [external_map_fixture()], +} + +BUNDLE_DICT = { + "context": "bundleContext", +} + +SBOM_DICT = { + "sbom_type": [SBOMType.BUILD], +} + +LICENSE_DICT = { + "license_id": "https://spdx.test/tools-python/license_id", + "license_name": "license name", + "license_text": "license text", + "license_comment": "license comment", + "see_also": ["https://see.also/license"], + "is_osi_approved": True, + "is_fsf_libre": True, + "standard_license_header": "license header", + "standard_license_template": "license template", + "is_deprecated_license_id": True, + "obsoleted_by": "https://spdx.test/tools-python/obsoleted_by_license_id", +} + +LISTED_LICENSE_DICT = { + "list_version_added": "2.1", + "deprecated_version": "2.2", +} + +LICENSE_ADDITION_DICT = { + "addition_id": "https://spdx.test/tools-python/addition_id", + "addition_name": "addition name", + "addition_text": "addition text", + "addition_comment": "addition comment", + "see_also": ["https://see.also/addition"], + "standard_addition_template": "addition template", + "is_deprecated_addition_id": True, + "obsoleted_by": "https://spdx.test/tools-python/obsoleted_by_addition_id", +} + +LISTED_LICENSE_EXCEPTION_DICT = { + "list_version_added": "2.1", + "deprecated_version": "2.2", +} + +VULNERABILITY_DICT = { + "published_time": datetime(2010, 1, 1), + "modified_time": datetime(2011, 1, 1), + "withdrawn_time": datetime(2012, 1, 1), +} + +VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "assessed_element": "https://spdx.test/tools-python/assessed_element", + "published_time": datetime(2004, 1, 1), + "supplied_by": "https://spdx.test/tools-python/supplied_by", + "modified_time": datetime(2005, 1, 1), + "withdrawn_time": datetime(2006, 1, 1), +} + +CVSS_V2_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "score": "4.3", + "severity": "low", + "vector": "(AV:N/AC:M/Au:N/C:P/I:N/A:N)", + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, +} + +CVSS_V3_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "score": "6.8", + "severity": "medium", + "vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N", + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, +} + +EPSS_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "probability": 80, + "severity": "high", + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, +} + +SSVC_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "decision_type": SsvcDecisionType.ACT, + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, +} + +EXPLOIT_CATALOG_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "catalog_type": ExploitCatalogType.KEV, + "exploited": True, + "locator": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, +} + +VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "vex_version": "v4.2", + "status_notes": "some status notes", +} + +VEX_AFFECTED_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "action_statement": "Upgrade to version 1.4 of ACME application.", + "action_statement_time": [datetime(2015, 10, 15)], + "relationship_type": RelationshipType.AFFECTS, +} + +VEX_NOT_AFFECTED_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "justification_type": VexJustificationType.COMPONENT_NOT_PRESENT, + "impact_statement": "Not using this vulnerable part of this library.", + "impact_statement_time": datetime(2015, 10, 15), + "relationship_type": RelationshipType.DOES_NOT_AFFECT, +} + +VEX_UNDER_INVESTIGATION_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "relationship_type": RelationshipType.UNDER_INVESTIGATION_FOR, +} + +VEX_FIXED_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "relationship_type": RelationshipType.FIXED_IN, +} + +AIPACKAGE_DICT = { + "energy_consumption": "energyConsumption", + "standard_compliance": ["standardCompliance"], + "limitation": "aIPackageLimitation", + "type_of_model": ["typeOfModel"], + "information_about_training": "informationAboutTraining", + "information_about_application": "informationAboutApplication", + "hyperparameter": {"aIPackageHypParaKey": "aIPackageHypParaValue"}, + "model_data_preprocessing": ["aImodelDataPreprocessing"], + "model_explainability": ["aImodelExplainability"], + "sensitive_personal_information": True, + "metric_decision_threshold": {"metricDecisionThresholdKey": "metricDecisionThresholdValue"}, + "metric": {"aIMetricKey": "aIMetricValue"}, + "domain": ["aIDomain"], + "autonomy_type": True, + "safety_risk_assessment": SafetyRiskAssessmentType.LOW, +} + +ARTIFACT_DICT = { + "originated_by": ["https://spdx.test/tools-python/originatedBy"], + "supplied_by": ["https://spdx.test/tools-python/suppliedBy"], + "built_time": datetime(2004, 1, 1), + "release_time": datetime(2005, 1, 1), + "valid_until_time": datetime(2006, 1, 1), + "standard": ["https://spdx.test/tools-python/standard"], +} + +SOFTWARE_ARTIFACT_DICT = { + "content_identifier": "https://spdx.test/tools-python/contentIdentifier", + "primary_purpose": SoftwarePurpose.SOURCE, + "additional_purpose": [SoftwarePurpose.OTHER], + "concluded_license": listed_license_fixture(), + "declared_license": listed_license_fixture(), + "copyright_text": "copyrightText", + "attribution_text": "attributionText", +} + +FILE_DICT = {"content_type": "fileContentType"} + +PACKAGE_DICT = { + "package_version": "packageVersion", + "download_location": "https://spdx.test/tools-python/downloadPackage", + "package_url": "https://spdx.test/tools-python/package", + "homepage": "https://spdx.test/tools-python/homepage", + "source_info": "sourceInfo", +} + +SNIPPET_DICT = {"byte_range": PositiveIntegerRange(1024, 2048), "line_range": PositiveIntegerRange(1, 4)} + +SOFTWARE_DEPENDENCY_RELATIONSHIP_DICT = { + "software_linkage": SoftwareDependencyLinkType.OTHER, + "conditionality": DependencyConditionalityType.OTHER, +} + +DATASET_DICT = { + "dataset_type": [DatasetType.OTHER], + "data_collection_process": "DatasetDataCollectionProcess", + "intended_use": "DatasetIntendedUse", + "dataset_size": 10, + "dataset_noise": "DatasetNoise", + "data_preprocessing": ["DataPreprocessing"], + "sensor": {"SensorKey": "SensorValue"}, + "known_bias": ["DatasetKnownBias"], + "sensitive_personal_information": True, + "anonymization_method_used": ["DatasetAnonymizationMethodUsed"], + "confidentiality_level": ConfidentialityLevelType.CLEAR, + "dataset_update_mechanism": "DatasetUpdateMechanism", + "dataset_availability": DatasetAvailabilityType.QUERY, +} + +BUILD_DICT = { + "build_type": "BuildType", + "build_id": "BuildId", + "config_source_entrypoint": ["ConfigSourceEntrypoint"], + "config_source_uri": ["ConfigSourceURI"], + "config_source_digest": [hash_fixture()], + "parameters": {"parameter": "value"}, + "build_start_time": datetime(2015, 4, 4), + "build_end_time": datetime(2015, 4, 5), + "environment": {"environment_param": "environment_value"}, +} + +FIXTURE_DICTS = { + Agent: [ELEMENT_DICT], + Person: [ELEMENT_DICT], + Organization: [ELEMENT_DICT], + SoftwareAgent: [ELEMENT_DICT], + Tool: [ELEMENT_DICT], + Relationship: [ELEMENT_DICT, RELATIONSHIP_DICT], + LifecycleScopedRelationship: [ELEMENT_DICT, RELATIONSHIP_DICT, LIFECYCLE_SCOPED_RELATIONSHIP_DICT], + Annotation: [ELEMENT_DICT, ANNOTATION_DICT], + Bundle: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], + SpdxDocument: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], + Bom: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], + Sbom: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT, SBOM_DICT], + ListedLicense: [LICENSE_DICT, LISTED_LICENSE_DICT], + CustomLicense: [LICENSE_DICT], + ListedLicenseException: [LICENSE_ADDITION_DICT, LISTED_LICENSE_EXCEPTION_DICT], + CustomLicenseAddition: [LICENSE_ADDITION_DICT], + CvssV2VulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + CVSS_V2_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + CvssV3VulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + CVSS_V3_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + EpssVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + EPSS_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + ExploitCatalogVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + EXPLOIT_CATALOG_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + SsvcVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + SSVC_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + VexAffectedVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_AFFECTED_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + VexFixedVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_FIXED_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + VexNotAffectedVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_NOT_AFFECTED_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + VexUnderInvestigationVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_UNDER_INVESTIGATION_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + Vulnerability: [ELEMENT_DICT, VULNERABILITY_DICT], + AIPackage: [AIPACKAGE_DICT, PACKAGE_DICT, ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT], + File: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, FILE_DICT], + Package: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, PACKAGE_DICT], + Snippet: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, SNIPPET_DICT], + SoftwareDependencyRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + LIFECYCLE_SCOPED_RELATIONSHIP_DICT, + SOFTWARE_DEPENDENCY_RELATIONSHIP_DICT, + ], + Dataset: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, PACKAGE_DICT, DATASET_DICT], + Build: [ELEMENT_DICT, BUILD_DICT], +} + + +def fixture_factory(clazz: Type[Any], **kwargs) -> Any: + fixture_dict = get_fixture_dict(clazz) + + for key in kwargs.keys(): + if key not in fixture_dict.keys(): + raise ValueError(f"Provided property name {key} is not part of {clazz.__name__}.") + else: + fixture_dict[key] = kwargs[key] + + return clazz(**fixture_dict) + + +def get_fixture_dict(clazz: Type[Any]) -> Dict[str, Any]: + fixture_dict = {} + if clazz not in FIXTURE_DICTS.keys(): + raise ValueError( + f"{clazz.__name__} is not part of the FIXTURE_DICTS. " + f"If it is a non-abstract subclass of Element, it was probably forgotten to add." + ) + for property_dict in FIXTURE_DICTS[clazz]: + fixture_dict.update(property_dict) + + if "spdx_id" in fixture_dict.keys(): + fixture_dict["spdx_id"] = f"https://spdx.test/tools-python/{clazz.__name__}_fixture" + + return fixture_dict diff --git a/tests/spdx3/model/__init__.py b/tests/spdx3/model/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/model/licensing/__init__.py b/tests/spdx3/model/licensing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/model/licensing/test_conjunctive_license_set.py b/tests/spdx3/model/licensing/test_conjunctive_license_set.py new file mode 100644 index 000000000..8a676041c --- /dev/null +++ b/tests/spdx3/model/licensing/test_conjunctive_license_set.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model.licensing import ConjunctiveLicenseSet, ListedLicense +from tests.spdx3.fixtures import fixture_factory + + +def test_valid_initialization(): + lic = fixture_factory(ListedLicense) + conjunctive_license_set = ConjunctiveLicenseSet([lic, lic]) + + assert conjunctive_license_set.member == [lic, lic] + + +def test_invalid_initialization(): + lic = fixture_factory(ListedLicense) + with pytest.raises(TypeError) as err: + ConjunctiveLicenseSet(lic) + + assert len(err.value.args[0]) == 1 + assert err.value.args[0][0].startswith("SetterError ConjunctiveLicenseSet:") diff --git a/tests/spdx3/model/licensing/test_disjunctive_license_set.py b/tests/spdx3/model/licensing/test_disjunctive_license_set.py new file mode 100644 index 000000000..f18bd6424 --- /dev/null +++ b/tests/spdx3/model/licensing/test_disjunctive_license_set.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model.licensing import DisjunctiveLicenseSet, ListedLicense +from tests.spdx3.fixtures import fixture_factory + + +def test_valid_initialization(): + lic = fixture_factory(ListedLicense) + disjunctive_license_set = DisjunctiveLicenseSet([lic, lic]) + + assert disjunctive_license_set.member == [lic, lic] + + +def test_invalid_initialization(): + lic = fixture_factory(ListedLicense) + with pytest.raises(TypeError) as err: + DisjunctiveLicenseSet(lic) + + assert len(err.value.args[0]) == 1 + assert err.value.args[0][0].startswith("SetterError DisjunctiveLicenseSet:") diff --git a/tests/spdx3/model/licensing/test_or_later_operator.py b/tests/spdx3/model/licensing/test_or_later_operator.py new file mode 100644 index 000000000..219307fa0 --- /dev/null +++ b/tests/spdx3/model/licensing/test_or_later_operator.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model.licensing import ListedLicense, OrLaterOperator +from tests.spdx3.fixtures import fixture_factory + + +def test_valid_initialization(): + lic = fixture_factory(ListedLicense) + or_later_operator = OrLaterOperator(lic) + + assert or_later_operator.subject_license == lic + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + OrLaterOperator("License") + + assert len(err.value.args[0]) == 1 + assert err.value.args[0][0].startswith("SetterError OrLaterOperator:") diff --git a/tests/spdx3/model/licensing/test_with_addition_operator.py b/tests/spdx3/model/licensing/test_with_addition_operator.py new file mode 100644 index 000000000..388aca27f --- /dev/null +++ b/tests/spdx3/model/licensing/test_with_addition_operator.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model.licensing import ListedLicense, ListedLicenseException, WithAdditionOperator +from tests.spdx3.fixtures import fixture_factory + + +def test_valid_initialization(): + lic = fixture_factory(ListedLicense) + lic_addition = fixture_factory(ListedLicenseException) + with_addition_operator = WithAdditionOperator(lic, lic_addition) + + assert with_addition_operator.subject_license == lic + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + WithAdditionOperator("License", "LicenseAddition") + + assert len(err.value.args[0]) == 2 + for arg in err.value.args[0]: + assert arg.startswith("SetterError WithAdditionOperator:") diff --git a/tests/spdx3/model/model_test_utils.py b/tests/spdx3/model/model_test_utils.py new file mode 100644 index 000000000..174d8ce40 --- /dev/null +++ b/tests/spdx3/model/model_test_utils.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import Any, List, Type + + +def get_property_names(clazz: Type[Any]) -> List[str]: + return [ + attribute + for attribute in dir(clazz) + if not attribute.startswith("_") and not callable(getattr(clazz, attribute)) + ] + + +class InvalidTypeClass: + pass diff --git a/tests/spdx3/model/test_abstract_classes.py b/tests/spdx3/model/test_abstract_classes.py new file mode 100644 index 000000000..b6217e2e5 --- /dev/null +++ b/tests/spdx3/model/test_abstract_classes.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model import Artifact, Element, ElementCollection, IntegrityMethod + + +@pytest.mark.parametrize("abstract_class", [Element, Artifact, ElementCollection, IntegrityMethod]) +def test_initialization_throws_error(abstract_class): + with pytest.raises(TypeError) as err: + abstract_class() + + assert f"Can't instantiate abstract class {abstract_class.__name__}" in err.value.args[0] diff --git a/tests/spdx3/model/test_creation_info.py b/tests/spdx3/model/test_creation_info.py new file mode 100644 index 000000000..03b2fad58 --- /dev/null +++ b/tests/spdx3/model/test_creation_info.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +import pytest +from semantic_version import Version + +from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifierType +from tests.spdx3.fixtures import creation_info_fixture +from tests.spdx3.model.model_test_utils import get_property_names + + +def test_correct_initialization(): + creation_info = creation_info_fixture() + + for property_name in get_property_names(CreationInfo): + assert getattr(creation_info, property_name) is not None + + assert creation_info.spec_version == Version("3.0.0") + assert creation_info.created == datetime(2022, 12, 1) + assert creation_info.created_by == ["https://spdx.test/tools-python/creation_info_created_by"] + assert creation_info.created_using == ["https://spdx.test/tools-python/creation_info_created_using"] + assert creation_info.profile == [ + ProfileIdentifierType.CORE, + ProfileIdentifierType.SOFTWARE, + ProfileIdentifierType.LICENSING, + ] + assert creation_info.data_license == "CC0-1.0" + assert creation_info.comment == "creationInfoComment" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + CreationInfo("2.3", "2012-01-01", [], "core", 3, [], []) + + assert len(err.value.args[0]) == 5 + for error in err.value.args[0]: + assert error.startswith("SetterError CreationInfo:") + + +def test_incomplete_initialization(): + with pytest.raises(TypeError) as err: + CreationInfo("2.3") + + assert ( + "__init__() missing 3 required positional arguments: 'created', 'created_by', and 'profile'" + in err.value.args[0] + ) diff --git a/tests/spdx3/model/test_element_and_licensing_subclasses.py b/tests/spdx3/model/test_element_and_licensing_subclasses.py new file mode 100644 index 000000000..0df9aa69f --- /dev/null +++ b/tests/spdx3/model/test_element_and_licensing_subclasses.py @@ -0,0 +1,107 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model import ( + Agent, + Annotation, + Bom, + Bundle, + LifecycleScopedRelationship, + Organization, + Person, + Relationship, + SoftwareAgent, + SpdxDocument, +) +from spdx_tools.spdx3.model.ai import AIPackage +from spdx_tools.spdx3.model.build import Build +from spdx_tools.spdx3.model.dataset import Dataset +from spdx_tools.spdx3.model.licensing import ( + CustomLicense, + CustomLicenseAddition, + ListedLicense, + ListedLicenseException, +) +from spdx_tools.spdx3.model.security import ( + CvssV2VulnAssessmentRelationship, + CvssV3VulnAssessmentRelationship, + EpssVulnAssessmentRelationship, + ExploitCatalogVulnAssessmentRelationship, + SsvcVulnAssessmentRelationship, + VexAffectedVulnAssessmentRelationship, + VexFixedVulnAssessmentRelationship, + VexNotAffectedVulnAssessmentRelationship, + VexUnderInvestigationVulnAssessmentRelationship, + Vulnerability, +) +from spdx_tools.spdx3.model.software import File, Package, Sbom, Snippet, SoftwareDependencyRelationship +from tests.spdx3.fixtures import fixture_factory, get_fixture_dict +from tests.spdx3.model.model_test_utils import InvalidTypeClass, get_property_names + +CLASS_LIST = [ + Agent, + Person, + Organization, + SoftwareAgent, + Annotation, + Relationship, + LifecycleScopedRelationship, + Bundle, + Bom, + SpdxDocument, + ListedLicense, + CustomLicense, + ListedLicenseException, + CustomLicenseAddition, + CvssV2VulnAssessmentRelationship, + CvssV3VulnAssessmentRelationship, + EpssVulnAssessmentRelationship, + ExploitCatalogVulnAssessmentRelationship, + SsvcVulnAssessmentRelationship, + VexAffectedVulnAssessmentRelationship, + VexFixedVulnAssessmentRelationship, + VexNotAffectedVulnAssessmentRelationship, + VexUnderInvestigationVulnAssessmentRelationship, + Vulnerability, + File, + Package, + Snippet, + Sbom, + SoftwareDependencyRelationship, + Dataset, + AIPackage, + Build, +] + + +@pytest.mark.parametrize( + "clazz", + CLASS_LIST, +) +def test_correct_initialization(clazz): + clazz_instance = fixture_factory(clazz) + fixture_dict = get_fixture_dict(clazz) + + for property_name in get_property_names(clazz): + assert getattr(clazz_instance, property_name) is not None + assert getattr(clazz_instance, property_name) == fixture_dict[property_name] + + +@pytest.mark.parametrize( + "clazz", + CLASS_LIST, +) +def test_invalid_initialization(clazz): + property_names = get_property_names(clazz) + false_properties_dict = {} + for property_name in property_names: + false_properties_dict[property_name] = InvalidTypeClass() + + with pytest.raises(TypeError) as err: + fixture_factory(clazz, **false_properties_dict) + + assert len(err.value.args[0]) == len(property_names) + for error in err.value.args[0]: + assert error.startswith(f"SetterError {clazz.__name__}") diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py new file mode 100644 index 000000000..c006dfda5 --- /dev/null +++ b/tests/spdx3/model/test_external_identifier.py @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType +from tests.spdx3.fixtures import external_identifier_fixture +from tests.spdx3.model.model_test_utils import get_property_names + + +def test_correct_initialization(): + external_identifier = external_identifier_fixture() + + for property_name in get_property_names(ExternalIdentifier): + assert getattr(external_identifier, property_name) is not None + + assert external_identifier.external_identifier_type == ExternalIdentifierType.OTHER + assert external_identifier.identifier == "externalIdentifierIdentifier" + assert external_identifier.comment == "externalIdentifierComment" + assert external_identifier.identifier_locator == [ + "https://spdx.test/tools-python/external_identifier_identifier_locator" + ] + assert ( + external_identifier.issuing_authority == "https://spdx.test/tools-python/external_identifier_issuing_authority" + ) + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + ExternalIdentifier("CPE22", ["identifier", "another_identifier"], 34, "locator", True) + + assert len(err.value.args[0]) == 5 + for error in err.value.args[0]: + assert error.startswith("SetterError ExternalIdentifier:") diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py new file mode 100644 index 000000000..b883b4598 --- /dev/null +++ b/tests/spdx3/model/test_external_map.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest + +from spdx_tools.spdx3.model import ExternalMap +from tests.spdx3.fixtures import external_map_fixture, hash_fixture +from tests.spdx3.model.model_test_utils import get_property_names + + +def test_correct_initialization(): + external_map = external_map_fixture() + + for property_name in get_property_names(ExternalMap): + assert getattr(external_map, property_name) is not None + + assert external_map.external_id == "https://spdx.test/tools-python/external_map_external_id" + assert external_map.verified_using == [hash_fixture()] + assert external_map.location_hint == "https://spdx.test/tools-python/external_map_location_hint" + assert external_map.defining_document == "https://spdx.test/tools-python/defining_document" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + ExternalMap(234, None, ["location hints"]) + + assert len(err.value.args[0]) == 2 + for error in err.value.args[0]: + assert error.startswith("SetterError ExternalMap:") diff --git a/tests/spdx3/model/test_external_reference.py b/tests/spdx3/model/test_external_reference.py new file mode 100644 index 000000000..91dac9fb8 --- /dev/null +++ b/tests/spdx3/model/test_external_reference.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model import ExternalReference, ExternalReferenceType +from tests.spdx3.fixtures import external_reference_fixture +from tests.spdx3.model.model_test_utils import get_property_names + + +def test_correct_initialization(): + external_reference = external_reference_fixture() + + for property_name in get_property_names(ExternalReference): + assert getattr(external_reference, property_name) is not None + + assert external_reference.external_reference_type == ExternalReferenceType.OTHER + assert external_reference.locator == ["org.apache.tomcat:tomcat:9.0.0.M4"] + assert external_reference.content_type == "externalReferenceContentType" + assert external_reference.comment == "externalReferenceComment" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + ExternalReference("OTHER", "a URI", 34, True) + + assert len(err.value.args[0]) == 4 + for error in err.value.args[0]: + assert error.startswith("SetterError ExternalReference:") diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py new file mode 100644 index 000000000..8994e1a7c --- /dev/null +++ b/tests/spdx3/model/test_hash.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model import Hash, HashAlgorithm +from tests.spdx3.fixtures import hash_fixture +from tests.spdx3.model.model_test_utils import get_property_names + + +def test_correct_initialization(): + hash = hash_fixture() + + for property_name in get_property_names(Hash): + assert getattr(hash, property_name) is not None + + assert hash.algorithm == HashAlgorithm.SHA1 + assert hash.hash_value == "71c4025dd9897b364f3ebbb42c484ff43d00791c" + assert hash.comment == "hashComment" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + Hash("SHA1", 345) + + assert len(err.value.args[0]) == 2 + for error in err.value.args[0]: + assert error.startswith("SetterError Hash:") diff --git a/tests/spdx3/model/test_namespace_map.py b/tests/spdx3/model/test_namespace_map.py new file mode 100644 index 000000000..a0e430162 --- /dev/null +++ b/tests/spdx3/model/test_namespace_map.py @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model import NamespaceMap +from tests.spdx3.fixtures import namespace_map_fixture +from tests.spdx3.model.model_test_utils import get_property_names + + +def test_correct_initialization(): + namespace_map = namespace_map_fixture() + + for property_name in get_property_names(NamespaceMap): + assert getattr(namespace_map, property_name) is not None + + assert namespace_map.prefix == "namespaceMapPrefix" + assert namespace_map.namespace == "https://spdx.test/tools-python/namespace_map_namespace" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + NamespaceMap(34, ["list of namespaces"]) + + assert len(err.value.args[0]) == 2 + for error in err.value.args[0]: + assert error.startswith("SetterError NamespaceMap:") diff --git a/tests/spdx3/validation/__init__.py b/tests/spdx3/validation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/validation/json_ld/__init__.py b/tests/spdx3/validation/json_ld/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/validation/json_ld/test_shacl_validation.py b/tests/spdx3/validation/json_ld/test_shacl_validation.py new file mode 100644 index 000000000..df2bfc17f --- /dev/null +++ b/tests/spdx3/validation/json_ld/test_shacl_validation.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os + +import pytest + +from spdx_tools.spdx3.validation.json_ld.shacl_validation import validate_against_shacl_from_file + + +@pytest.mark.skip("Currently the validation against SHACL fails, refer to process.md and the known limitations.") +def test_shacl_validation(): + # insert path to example json ld + conforms, results_graph, results_text = validate_against_shacl_from_file( + data_file=os.path.join(os.path.dirname(__file__), "../../../SPDX3_jsonld_test.jsonld"), + shacl_file=os.path.join( + os.path.dirname(__file__), "../../../../src/spdx_tools/spdx3/writer/json_ld/model.ttl" + ), + ) + # results_graph.serialize("validation_result.rdf.xml", format="pretty-xml") + print(results_text) + assert conforms diff --git a/tests/spdx3/writer/__init__.py b/tests/spdx3/writer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/writer/json_ld/__init__.py b/tests/spdx3/writer/json_ld/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/writer/json_ld/test_json_ld_writer.py b/tests/spdx3/writer/json_ld/test_json_ld_writer.py new file mode 100644 index 000000000..f46469b1f --- /dev/null +++ b/tests/spdx3/writer/json_ld/test_json_ld_writer.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os + +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload +from spdx_tools.spdx.model.document import Document as Spdx2_Document +from tests.spdx.fixtures import document_fixture + + +def test_json_writer(): + spdx2_document: Spdx2_Document = document_fixture() + payload: Payload = bump_spdx_document(spdx2_document) + + # this currently generates an actual file to look at, this should be changed to a temp file later + write_payload(payload, os.path.join(os.path.dirname(__file__), "../../../SPDX3_jsonld_test")) diff --git a/tests/spdx3/writer/tag_value/test_write_document.py b/tests/spdx3/writer/tag_value/test_write_document.py new file mode 100644 index 000000000..580c61b81 --- /dev/null +++ b/tests/spdx3/writer/tag_value/test_write_document.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2024 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import io +from datetime import datetime + +from semantic_version import Version + +from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifierType, SpdxDocument +from spdx_tools.spdx3.writer.console.spdx_document_writer import write_spdx_document + + +def test_render_creation_info(): + fake_datetime = datetime(year=2024, month=1, day=1) + spec_version = Version("3.0.0") + creation_info = CreationInfo( + spec_version=spec_version, + created=fake_datetime, + created_by=[], + profile=[ProfileIdentifierType.SOFTWARE], + ) + spdx_document = SpdxDocument( + spdx_id="SPDXRef-FOO", + name="BAR", + element=[], + root_element=[], + creation_info=creation_info, + ) + output_str = io.StringIO() + write_spdx_document(spdx_document, text_output=output_str) + + assert ( + output_str.getvalue() + == """\ +## SPDX Document +SPDXID: SPDXRef-FOO +name: BAR +# Creation Information + specVersion: 3.0.0 + created: 2024-01-01T00:00:00Z + profile: SOFTWARE + data license: CC0-1.0 +elements: +""" # noqa: W291 # elements: are printed with a space + ) diff --git a/tests/test_builder.py b/tests/test_builder.py deleted file mode 100644 index b634b8d3f..000000000 --- a/tests/test_builder.py +++ /dev/null @@ -1,748 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from unittest import TestCase - -import tests.testing_utils as testing_utils - -from spdx.document import Document, License -import spdx.parsers.tagvaluebuilders as builders -from spdx.version import Version - - -class TestDocumentBuilder(TestCase): - maxDiff = None - - def setUp(self): - self.document = Document() - self.builder = builders.DocBuilder() - - def test_correct_version(self): - version_str = 'SPDX-2.1' - self.builder.set_doc_version(self.document, version_str) - assert (self.document.version.major == 2 and - self.document.version.minor == 1) - - @testing_utils.raises(builders.CardinalityError) - def test_version_cardinality(self): - version_str = 'SPDX-2.1' - self.builder.set_doc_version(self.document, version_str) - self.builder.set_doc_version(self.document, version_str) - - @testing_utils.raises(builders.SPDXValueError) - def test_version_value(self): - version_str = '2.1' - self.builder.set_doc_version(self.document, version_str) - - def test_correct_data_lics(self): - lics_str = 'CC0-1.0' - self.builder.set_doc_data_lics(self.document, lics_str) - assert self.document.data_license == License.from_identifier(lics_str) - - @testing_utils.raises(builders.SPDXValueError) - def test_data_lics_value(self): - lics_str = 'GPL' - self.builder.set_doc_data_lics(self.document, lics_str) - - @testing_utils.raises(builders.CardinalityError) - def test_data_lics_cardinality(self): - lics_str = 'CC0-1.0' - self.builder.set_doc_data_lics(self.document, lics_str) - self.builder.set_doc_data_lics(self.document, lics_str) - - def test_correct_name(self): - name_str = 'Sample_Document-V2.1' - self.builder.set_doc_name(self.document, name_str) - assert self.document.name == name_str - - @testing_utils.raises(builders.CardinalityError) - def test_name_cardinality(self): - name_str = 'Sample_Document-V2.1' - self.builder.set_doc_name(self.document, name_str) - self.builder.set_doc_name(self.document, name_str) - - def test_correct_doc_namespace(self): - doc_namespace_str = 'https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301' - self.builder.set_doc_namespace(self.document, doc_namespace_str) - assert self.document.namespace == doc_namespace_str - - @testing_utils.raises(builders.SPDXValueError) - def test_doc_namespace_value(self): - doc_namespace_str = 'https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DOCUMENT' - self.builder.set_doc_data_lics(self.document, doc_namespace_str) - - @testing_utils.raises(builders.CardinalityError) - def test_doc_namespace_cardinality(self): - doc_namespace_str = 'https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301' - self.builder.set_doc_namespace(self.document, doc_namespace_str) - self.builder.set_doc_namespace(self.document, doc_namespace_str) - - def test_correct_data_comment(self): - comment_str = 'This is a comment.' - comment_text = '' + comment_str + '' - self.builder.set_doc_comment(self.document, comment_text) - assert self.document.comment == comment_str - - @testing_utils.raises(builders.CardinalityError) - def test_comment_cardinality(self): - comment_str = 'This is a comment.' - comment_text = '' + comment_str + '' - self.builder.set_doc_comment(self.document, comment_text) - self.builder.set_doc_comment(self.document, comment_text) - - @testing_utils.raises(builders.SPDXValueError) - def test_comment_value(self): - comment = 'slslsshello') - - @testing_utils.raises(builders.OrderError) - def test_pkg_cr_text_order(self): - self.builder.set_pkg_cr_text(self.document, 'Something') - - @testing_utils.raises(builders.OrderError) - def test_pkg_summary_order(self): - self.builder.set_pkg_summary(self.document, 'Something') - - @testing_utils.raises(builders.OrderError) - def test_set_pkg_desc_order(self): - self.builder.set_pkg_desc(self.document, 'something') - - @testing_utils.raises(builders.OrderError) - def test_set_pkg_spdx_id_order(self): - self.builder.set_pkg_spdx_id(self.document, 'SPDXRe-Package') - - @testing_utils.raises(builders.OrderError) - def test_set_pkg_files_analyzed_order(self): - self.builder.set_pkg_files_analyzed(self.document, 'True') - - @testing_utils.raises(builders.OrderError) - def test_set_pkg_comment_order(self): - self.builder.set_pkg_comment(self.document, 'something') - - def test_correct_pkg_comment(self): - self.builder.create_package(self.document, 'pkg') - self.builder.set_pkg_comment(self.document, 'something') - - @testing_utils.raises(builders.SPDXValueError) - def test_incorrect_pkg_comment(self): - self.builder.create_package(self.document, 'pkg') - self.builder.set_pkg_comment(self.document, 'not_free_form_text') - - def test_correct_pkg_spdx_id(self): - self.builder.create_package(self.document, 'pkg') - assert self.builder.set_pkg_spdx_id(self.document, 'SPDXRef-Package') - assert self.document.package.spdx_id == 'SPDXRef-Package' - - @testing_utils.raises(builders.SPDXValueError) - def test_incorrect_pkg_spdx_id(self): - self.builder.create_package(self.document, 'pkg') - assert self.builder.set_pkg_spdx_id(self.document, 'SPDXRe-Package') - - @testing_utils.raises(builders.SPDXValueError) - def test_incorrect_pkg_files_analyzed(self): - self.builder.create_package(self.document, 'pkg') - assert self.builder.set_pkg_files_analyzed(self.document, 'XYZ') - - def test_correct_pkg_files_analyzed_1(self): - self.builder.create_package(self.document, 'pkg') - assert self.builder.set_pkg_files_analyzed(self.document, 'True') - - def test_correct_pkg_files_analyzed_2(self): - self.builder.create_package(self.document, 'pkg') - assert self.builder.set_pkg_files_analyzed(self.document, 'true') - - def test_correct_pkg_ext_ref_category(self): - category = 'SECURITY' - self.builder.create_package(self.document, 'pkg') - self.builder.set_pkg_ext_ref_category(self.document, category) - assert self.document.package.pkg_ext_refs[-1].category == category - - @testing_utils.raises(builders.SPDXValueError) - def test_incorrect_pkg_ext_ref_category(self): - category = 'some_other_value' - self.builder.create_package(self.document, 'pkg') - self.builder.set_pkg_ext_ref_category(self.document, category) - - def test_correct_pkg_ext_ref_type(self): - pkg_ext_ref_type = 'cpe23Type' - self.builder.create_package(self.document, 'pkg') - self.builder.set_pkg_ext_ref_type(self.document, pkg_ext_ref_type) - assert self.document.package.pkg_ext_refs[ - -1].pkg_ext_ref_type == pkg_ext_ref_type - - @testing_utils.raises(builders.SPDXValueError) - def test_incorrect_pkg_ext_ref_type(self): - pkg_ext_ref_type = 'cpe23Type_with_special_symbols&%' - self.builder.create_package(self.document, 'pkg') - self.builder.set_pkg_ext_ref_type(self.document, pkg_ext_ref_type) - - def test_correct_pkg_ext_ref_locator(self): - locator = 'cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*' - self.builder.create_package(self.document, 'pkg') - self.builder.set_pkg_ext_ref_locator(self.document, locator) - assert self.document.package.pkg_ext_refs[-1].locator == locator - - @testing_utils.raises(builders.OrderError) - def test_pkg_ext_ref_without_pkg(self): - locator = 'cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*' - self.builder.set_pkg_ext_ref_locator(self.document, locator) - - def test_correct_pkg_ext_comment(self): - comment_str = 'This is a comment.' - comment_text = '' + comment_str + '' - self.builder.create_package(self.document, 'pkg') - self.builder.set_pkg_ext_ref_category(self.document, 'SECURITY') - self.builder.add_pkg_ext_ref_comment(self.document, comment_text) - assert self.document.package.pkg_ext_refs[-1].comment == comment_str - - @testing_utils.raises(builders.OrderError) - def test_pkg_ext_comment_without_pkg_ext_ref(self): - comment_str = 'This is a comment.' - comment_text = '' + comment_str + '' - self.builder.create_package(self.document, 'pkg') - self.builder.add_pkg_ext_ref_comment(self.document, comment_text) - - -class TestSnippetBuilder(TestCase): - maxDiff = None - - def setUp(self): - self.entity_builder = builders.EntityBuilder() - self.builder = builders.SnippetBuilder() - self.document = Document() - - def test_create_snippet(self): - assert self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - - @testing_utils.raises(builders.SPDXValueError) - def test_incorrect_snippet_spdx_id(self): - self.builder.create_snippet(self.document, 'Some_value_with_$%') - - def test_snippet_name(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snippet_name(self.document, 'Name_of_snippet') - - @testing_utils.raises(builders.OrderError) - def test_snippet_name_order(self): - self.builder.set_snippet_name(self.document, 'Name_of_snippet') - - def test_snippet_comment(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snippet_comment(self.document, 'Comment') - - @testing_utils.raises(builders.OrderError) - def test_snippet_comment_order(self): - self.builder.set_snippet_comment(self.document, 'Comment') - - @testing_utils.raises(builders.SPDXValueError) - def test_snippet_comment_text_value(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snippet_comment(self.document, 'Comment.') - - def test_snippet_copyright(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snippet_copyright(self.document, 'Copyright 2008-2010 John Smith') - - @testing_utils.raises(builders.SPDXValueError) - def test_snippet_copyright_text_value(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snippet_copyright(self.document, - 'Copyright 2008-2010 John Smith') - - @testing_utils.raises(builders.OrderError) - def test_snippet_copyright_order(self): - self.builder.set_snippet_copyright(self.document, - 'Copyright 2008-2010 John Smith') - - def test_snippet_lic_comment(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snippet_lic_comment(self.document, - 'Lic comment') - - @testing_utils.raises(builders.SPDXValueError) - def test_snippet_lic_comment_text_value(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snippet_lic_comment(self.document, - 'Lic comment') - - @testing_utils.raises(builders.OrderError) - def test_snippet_lic_comment_order(self): - self.builder.set_snippet_lic_comment(self.document, - 'Lic comment') - - def test_snippet_from_file_spdxid(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snip_from_file_spdxid(self.document, - 'SPDXRef-DoapSource') - - @testing_utils.raises(builders.SPDXValueError) - def test_snippet_from_file_spdxid_value(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snip_from_file_spdxid(self.document, - '#_$random_chars') - - @testing_utils.raises(builders.OrderError) - def test_snippet_from_file_spdxid_order(self): - self.builder.set_snip_from_file_spdxid(self.document, - 'SPDXRef-DoapSource') - - @testing_utils.raises(builders.CardinalityError) - def test_snippet_from_file_spdxid_cardinality(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snip_from_file_spdxid(self.document, - 'SPDXRef-DoapSource') - self.builder.set_snip_from_file_spdxid(self.document, - 'SPDXRef-somevalue') - - def test_snippet_conc_lics(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snip_concluded_license(self.document, - License.from_identifier( - 'Apache-2.0')) - - @testing_utils.raises(builders.SPDXValueError) - def test_snippet_conc_lics_value(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snip_concluded_license(self.document, 'Apache-2.0') - - @testing_utils.raises(builders.OrderError) - def test_snippet_conc_lics_order(self): - self.builder.set_snip_concluded_license(self.document, - License.from_identifier( - 'Apache-2.0')) - - @testing_utils.raises(builders.CardinalityError) - def test_snippet_conc_lics_cardinality(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snip_concluded_license(self.document, - License.from_identifier( - 'Apache-2.0')) - self.builder.set_snip_concluded_license(self.document, - License.from_identifier( - 'Apache-2.0')) - - def test_snippet_lics_info(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snippet_lics_info(self.document, - License.from_identifier( - 'Apache-2.0')) - self.builder.set_snippet_lics_info(self.document, - License.from_identifier( - 'GPL-2.0-or-later')) - - @testing_utils.raises(builders.SPDXValueError) - def test_snippet_lics_info_value(self): - self.builder.create_snippet(self.document, 'SPDXRef-Snippet') - self.builder.set_snippet_lics_info(self.document, 'Apache-2.0') - - @testing_utils.raises(builders.OrderError) - def test_snippet_lics_info_order(self): - self.builder.set_snippet_lics_info(self.document, - License.from_identifier( - 'Apache-2.0')) diff --git a/tests/test_config.py b/tests/test_config.py deleted file mode 100644 index 3b96db055..000000000 --- a/tests/test_config.py +++ /dev/null @@ -1,49 +0,0 @@ - -# Copyright (c) the SPDX tools authors -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from unittest import TestCase - -from spdx import config -from spdx.version import Version - - -class TestLicenseList(TestCase): - maxDiff = None - - def test_load_license_list(self): - version, licenses_map = config.load_license_list(config._licenses) - assert version == ('3', '6') - # Test some instances in licenses_map - assert licenses_map['MIT License'] == 'MIT' - assert licenses_map['MIT'] == 'MIT License' - assert licenses_map['Apache License 2.0'] == 'Apache-2.0' - assert licenses_map['Apache-2.0'] == 'Apache License 2.0' - assert licenses_map['GNU General Public License v3.0 only'] == 'GPL-3.0-only' - assert licenses_map['GPL-3.0-only'] == 'GNU General Public License v3.0 only' - - def test_config_license_list_version_constant(self): - assert config.LICENSE_LIST_VERSION == Version(major=3, minor=6) - - def test_load_exception_list(self): - version, exception_map = config.load_exception_list(config._exceptions) - assert version == ('3', '6') - # Test some instances in exception_map - assert exception_map['Bison exception 2.2'] == 'Bison-exception-2.2' - assert exception_map['Bison-exception-2.2'] == 'Bison exception 2.2' - assert exception_map['OpenVPN OpenSSL Exception'] == 'openvpn-openssl-exception' - assert exception_map['openvpn-openssl-exception'] == 'OpenVPN OpenSSL Exception' - assert exception_map['Qt GPL exception 1.0'] == 'Qt-GPL-exception-1.0' - assert exception_map['Qt-GPL-exception-1.0'] == 'Qt GPL exception 1.0' diff --git a/tests/test_conversion.py b/tests/test_conversion.py deleted file mode 100644 index 00aeada5e..000000000 --- a/tests/test_conversion.py +++ /dev/null @@ -1,266 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import codecs -import os -import tempfile -from unittest import TestCase - -from spdx.parsers.rdf import Parser as RDFParser -from spdx.parsers.rdfbuilders import Builder as RDFBuilder -from spdx.parsers.loggers import StandardLogger -from spdx.parsers.tagvalue import Parser as TVParser -from spdx.parsers.tagvaluebuilders import Builder as TVBuilder -from spdx.parsers.jsonparser import Parser as JSONParser -from spdx.parsers.yamlparser import Parser as YAMLParser -from spdx.parsers.xmlparser import Parser as XMLParser -from spdx.parsers.jsonyamlxmlbuilders import Builder as JSONYAMLXMLBuilder -import spdx.writers.rdf as rdfwriter -import spdx.writers.tagvalue as tvwriter -import spdx.writers.json as jsonwriter -import spdx.writers.yaml as yamlwriter -import spdx.writers.xml as xmlwriter - -from tests import utils_test - - -def get_temp_file(extension=''): - """ - Return a unique new temporary file location to a non-existing - temporary file that can safely be created without a risk of name - collision. - """ - - if extension and not extension.startswith('.'): - extension = '.' + extension - file_name = 'temp_file' + extension - temp_dir = tempfile.mkdtemp() - return os.path.join(temp_dir, file_name) - - -class TestConversions(TestCase): - maxDiff = None - - def parse_rdf_file(self, file_name): - with open(file_name, mode='rb') as infile: - rdfparser = RDFParser(RDFBuilder(), StandardLogger()) - doc, error = rdfparser.parse(infile) - assert not error - assert doc.validate([]) == [] - return doc - - def parse_tagvalue_file(self, file_name): - with open(file_name, mode='r') as infile: - tvparser = TVParser(TVBuilder(), StandardLogger()) - tvparser.build() - doc, error = tvparser.parse(infile.read()) - assert not error - assert doc.validate([]) == [] - return doc - - def parse_json_file(self, file_name): - with open(file_name, mode='r') as infile: - jsonparser = JSONParser(JSONYAMLXMLBuilder(), StandardLogger()) - doc, error = jsonparser.parse(infile) - assert not error - assert doc.validate([]) == [] - return doc - - def parse_yaml_file(self, file_name): - with open(file_name, mode='r') as infile: - yamlparser = YAMLParser(JSONYAMLXMLBuilder(), StandardLogger()) - doc, error = yamlparser.parse(infile) - assert not error - assert doc.validate([]) == [] - return doc - - def parse_xml_file(self, file_name): - with open(file_name, mode='r') as infile: - xmlparser = XMLParser(JSONYAMLXMLBuilder(), StandardLogger()) - doc, error = xmlparser.parse(infile) - assert not error - assert doc.validate([]) == [] - return doc - - def write_tagvalue_file(self, document, file_name): - with codecs.open(file_name, mode='w', encoding='utf-8') as out: - tvwriter.write_document(document, out) - - def write_rdf_file(self, document, file_name): - with open(file_name, mode='wb') as out: - rdfwriter.write_document(document, out) - - def write_json_file(self, document, file_name): - with open(file_name, mode='w') as out: - jsonwriter.write_document(document, out) - - def write_yaml_file(self, document, file_name): - with open(file_name, mode='w') as out: - yamlwriter.write_document(document, out) - - def write_xml_file(self, document, file_name): - with open(file_name, mode='w') as out: - xmlwriter.write_document(document, out) - - def test_tagvalue_rdf(self): - doc = self.parse_tagvalue_file(utils_test.get_test_loc('formats/SPDXTagExample.tag')) - filename = get_temp_file('.rdf') - self.write_rdf_file(doc, filename) - self.parse_rdf_file(filename) - - def test_json_rdf(self): - doc = self.parse_json_file(utils_test.get_test_loc('formats/SPDXJsonExample.json')) - filename = get_temp_file('.rdf') - self.write_rdf_file(doc, filename) - self.parse_rdf_file(filename) - - def test_yaml_rdf(self): - doc = self.parse_yaml_file(utils_test.get_test_loc('formats/SPDXYamlExample.yaml')) - filename = get_temp_file('.rdf') - self.write_rdf_file(doc, filename) - self.parse_rdf_file(filename) - - def test_xml_rdf(self): - doc = self.parse_xml_file(utils_test.get_test_loc('formats/SPDXXmlExample.xml')) - filename = get_temp_file('.rdf') - self.write_rdf_file(doc, filename) - self.parse_rdf_file(filename) - - def test_rdf_rdf(self): - doc = self.parse_rdf_file(utils_test.get_test_loc('formats/SPDXRdfExample.rdf')) - filename = get_temp_file('.rdf') - self.write_rdf_file(doc, filename) - self.parse_rdf_file(filename) - - def test_tagvalue_tagvalue(self): - doc = self.parse_tagvalue_file(utils_test.get_test_loc('formats/SPDXTagExample.tag')) - filename = get_temp_file('.tag') - self.write_tagvalue_file(doc, filename) - self.parse_tagvalue_file(filename) - - def test_rdf_tagvalue(self): - doc = self.parse_rdf_file(utils_test.get_test_loc('formats/SPDXRdfExample.rdf')) - filename = get_temp_file('.tag') - self.write_tagvalue_file(doc, filename) - self.parse_tagvalue_file(filename) - - def test_json_tagvalue(self): - doc = self.parse_json_file(utils_test.get_test_loc('formats/SPDXJsonExample.json')) - filename = get_temp_file('.tag') - self.write_tagvalue_file(doc, filename) - self.parse_tagvalue_file(filename) - - def test_yaml_tagvalue(self): - doc = self.parse_yaml_file(utils_test.get_test_loc('formats/SPDXYamlExample.yaml')) - filename = get_temp_file('.tag') - self.write_tagvalue_file(doc, filename) - self.parse_tagvalue_file(filename) - - def test_xml_tagvalue(self): - doc = self.parse_xml_file(utils_test.get_test_loc('formats/SPDXXmlExample.xml')) - filename = get_temp_file('.tag') - self.write_tagvalue_file(doc, filename) - self.parse_tagvalue_file(filename) - - def test_tagvalue_json(self): - doc = self.parse_tagvalue_file(utils_test.get_test_loc('formats/SPDXTagExample.tag')) - filename = get_temp_file('.json') - self.write_json_file(doc, filename) - self.parse_json_file(filename) - - def test_rdf_json(self): - doc = self.parse_rdf_file(utils_test.get_test_loc('formats/SPDXRdfExample.rdf')) - filename = get_temp_file('.json') - self.write_json_file(doc, filename) - self.parse_json_file(filename) - - def test_yaml_json(self): - doc = self.parse_yaml_file(utils_test.get_test_loc('formats/SPDXYamlExample.yaml')) - filename = get_temp_file('.json') - self.write_json_file(doc, filename) - self.parse_json_file(filename) - - def test_xml_json(self): - doc = self.parse_xml_file(utils_test.get_test_loc('formats/SPDXXmlExample.xml')) - filename = get_temp_file('.json') - self.write_json_file(doc, filename) - self.parse_json_file(filename) - - def test_json_json(self): - doc = self.parse_json_file(utils_test.get_test_loc('formats/SPDXJsonExample.json')) - filename = get_temp_file('.json') - self.write_json_file(doc, filename) - self.parse_json_file(filename) - - def test_tagvalue_yaml(self): - doc = self.parse_tagvalue_file(utils_test.get_test_loc('formats/SPDXTagExample.tag')) - filename = get_temp_file('.yaml') - self.write_yaml_file(doc, filename) - self.parse_yaml_file(filename) - - def test_rdf_yaml(self): - doc = self.parse_rdf_file(utils_test.get_test_loc('formats/SPDXRdfExample.rdf')) - filename = get_temp_file('.yaml') - self.write_yaml_file(doc, filename) - self.parse_yaml_file(filename) - - def test_json_yaml(self): - doc = self.parse_json_file(utils_test.get_test_loc('formats/SPDXJsonExample.json')) - filename = get_temp_file('.yaml') - self.write_yaml_file(doc, filename) - self.parse_yaml_file(filename) - - def test_xml_yaml(self): - doc = self.parse_xml_file(utils_test.get_test_loc('formats/SPDXXmlExample.xml')) - filename = get_temp_file('.yaml') - self.write_yaml_file(doc, filename) - self.parse_yaml_file(filename) - - def test_yaml_yaml(self): - doc = self.parse_yaml_file(utils_test.get_test_loc('formats/SPDXYamlExample.yaml')) - filename = get_temp_file('.yaml') - self.write_yaml_file(doc, filename) - self.parse_yaml_file(filename) - - def test_tagvalue_xml(self): - doc = self.parse_tagvalue_file(utils_test.get_test_loc('formats/SPDXTagExample.tag')) - filename = get_temp_file('.xml') - self.write_xml_file(doc, filename) - self.parse_xml_file(filename) - - def test_rdf_xml(self): - doc = self.parse_rdf_file(utils_test.get_test_loc('formats/SPDXRdfExample.rdf')) - filename = get_temp_file('.xml') - self.write_xml_file(doc, filename) - self.parse_xml_file(filename) - - def test_json_xml(self): - doc = self.parse_json_file(utils_test.get_test_loc('formats/SPDXJsonExample.json')) - filename = get_temp_file('.xml') - self.write_xml_file(doc, filename) - self.parse_xml_file(filename) - - def test_yaml_xml(self): - doc = self.parse_yaml_file(utils_test.get_test_loc('formats/SPDXYamlExample.yaml')) - filename = get_temp_file('.xml') - self.write_xml_file(doc, filename) - self.parse_xml_file(filename) - - def test_xml_xml(self): - doc = self.parse_xml_file(utils_test.get_test_loc('formats/SPDXXmlExample.xml')) - filename = get_temp_file('.xml') - self.write_xml_file(doc, filename) - self.parse_xml_file(filename) diff --git a/tests/test_creationinfo.py b/tests/test_creationinfo.py deleted file mode 100644 index 9c325bf44..000000000 --- a/tests/test_creationinfo.py +++ /dev/null @@ -1,71 +0,0 @@ - -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from datetime import datetime -from unittest import TestCase - -import spdx.config as config -from spdx.creationinfo import CreationInfo -from spdx.creationinfo import Tool -from spdx.creationinfo import Organization -from spdx.creationinfo import Person -from spdx.version import Version - - -class TestCreationInfo(TestCase): - maxDiff = None - - def test_timestamp(self): - dt = datetime(2014, 4, 8, 13, 42, 12) - ci_time = CreationInfo(created=dt) - assert ci_time.created == dt - - def test_iso_format(self): - dt = datetime(2014, 4, 8, 13, 42, 12) - ci_time = CreationInfo(created=dt) - assert ci_time.created_iso_format == "2014-04-08T13:42:12Z" - - def test_comment(self): - ci_default = CreationInfo() - assert ci_default.comment is None - ci_comment = CreationInfo(comment='Hello There') - assert ci_comment.comment == 'Hello There' - - def test_creators(self): - ci = CreationInfo() - assert len(ci.creators) == 0 - person = Person(name='Alice', email='alice@example.com') - tool = Tool(name='spdxtron-9000') - org = Organization(name='Acme', email='acme@example.com') - ci.add_creator(tool) - ci.add_creator(org) - ci.add_creator(person) - assert len(ci.creators) == 3 - assert tool in ci.creators - assert org in ci.creators - assert person in ci.creators - ci.remove_creator(person) - assert len(ci.creators) == 2 - assert tool in ci.creators - assert org in ci.creators - assert person not in ci.creators - - def test_license_list_version(self): - ci = CreationInfo() - assert ci.license_list_version == config.LICENSE_LIST_VERSION - ci = CreationInfo(license_list_version=Version(major=1, minor=0)) - assert ci.license_list_version == Version(major=1, minor=0) - assert not ci.license_list_version == Version(major=1, minor=2) diff --git a/tests/test_document.py b/tests/test_document.py deleted file mode 100644 index 073aeb7c6..000000000 --- a/tests/test_document.py +++ /dev/null @@ -1,452 +0,0 @@ -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import os -import shutil -import tempfile -from unittest import TestCase - -from spdx.checksum import Algorithm -from spdx.config import LICENSE_MAP, EXCEPTION_MAP -from spdx.creationinfo import Tool -from spdx.document import Document, ExternalDocumentRef -from spdx.document import License -from spdx.file import File -from spdx.package import Package -from spdx.utils import NoAssert -from spdx.version import Version - -from tests import utils_test - - -class TestVersion(TestCase): - maxDiff = None - - def test_creation(self): - v = Version(major=2, minor=1) - assert v.major == 2 - assert v.minor == 1 - - def test_comparison(self): - v1 = Version(major=1, minor=2) - v2 = Version(major=2, minor=1) - assert v1 != v2 - assert v1 < v2 - assert v1 <= v2 - assert v2 > v1 - assert v2 >= v1 - v3 = Version(major=1, minor=2) - assert v3 == v1 - assert not v1 < v3 - assert v1 <= v3 - - -class TestDocument(TestCase): - maxDiff = None - - def test_creation(self): - document = Document( - version=Version(major=2, minor=1), - data_license=License(full_name='Academic Free License v1.1', - identifier='AFL-1.1') - ) - document.add_ext_document_reference( - ExternalDocumentRef('DocumentRef-spdx-tool-2.1', - 'https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301', - Algorithm('SHA1', 'SOME-SHA1')) - ) - assert document.comment is None - assert document.version == Version(2, 1) - assert document.data_license.identifier == 'AFL-1.1' - assert document.ext_document_references[-1].external_document_id == 'DocumentRef-spdx-tool-2.1' - assert document.ext_document_references[-1].spdx_document_uri == 'https://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301' - assert document.ext_document_references[-1].check_sum.identifier == 'SHA1' - assert document.ext_document_references[-1].check_sum.value == 'SOME-SHA1' - - def test_document_validate_failures_returns_informative_messages(self): - doc = Document(Version(2, 1), License.from_identifier('CC0-1.0'), - 'Sample_Document-V2.1', spdx_id='SPDXRef-DOCUMENT', - namespace='https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301') - pack = doc.package = Package('some/path', NoAssert()) - file1 = File('./some/path/tofile') - file1.name = './some/path/tofile' - file1.spdx_id = 'SPDXRef-File' - file1.chk_sum = Algorithm('SHA1', 'SOME-SHA1') - lic1 = License.from_identifier('LGPL-2.1-only') - file1.add_lics(lic1) - pack.add_lics_from_file(lic1) - messages = [] - messages = doc.validate(messages) - expected = [ - 'No creators defined, must have at least one.', - 'Creation info missing created date.', - 'Package checksum must be instance of spdx.checksum.Algorithm', - 'Package download_location can not be None.', - 'Package verif_code can not be None.', - 'Package cr_text can not be None.', - 'Package must have at least one file.', - 'Package concluded license must be instance of spdx.utils.SPDXNone ' - 'or spdx.utils.NoAssert or spdx.document.License', - 'Package declared license must be instance of spdx.utils.SPDXNone ' - 'or spdx.utils.NoAssert or spdx.document.License' - ] - assert expected == messages - - def test_document_is_valid_when_using_or_later_licenses(self): - doc = Document(Version(2, 1), License.from_identifier('CC0-1.0'), - 'Sample_Document-V2.1', spdx_id='SPDXRef-DOCUMENT', - namespace='https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301') - doc.creation_info.add_creator(Tool('ScanCode')) - doc.creation_info.set_created_now() - - package = doc.package = Package(name='some/path', download_location=NoAssert()) - package.spdx_id = 'SPDXRef-Package' - package.cr_text = 'Some copyrught' - package.verif_code = 'SOME code' - package.license_declared = NoAssert() - package.conc_lics = NoAssert() - - file1 = File('./some/path/tofile') - file1.name = './some/path/tofile' - file1.spdx_id = 'SPDXRef-File' - file1.chk_sum = Algorithm('SHA1', 'SOME-SHA1') - file1.conc_lics = NoAssert() - file1.copyright = NoAssert() - - lic1 = License.from_identifier('LGPL-2.1-or-later') - file1.add_lics(lic1) - - package.add_lics_from_file(lic1) - package.add_file(file1) - messages = [] - is_valid = doc.validate(messages) - assert is_valid - assert not messages - - -class TestWriters(TestCase): - maxDiff = None - - def _get_lgpl_doc(self, or_later=False): - doc = Document(Version(2, 1), License.from_identifier('CC0-1.0'), - 'Sample_Document-V2.1', spdx_id='SPDXRef-DOCUMENT', - namespace='https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301') - doc.creation_info.add_creator(Tool('ScanCode')) - doc.creation_info.set_created_now() - - package = doc.package = Package(name='some/path', download_location=NoAssert()) - package.spdx_id = 'SPDXRef-Package' - package.cr_text = 'Some copyrught' - package.verif_code = 'SOME code' - package.check_sum = Algorithm('SHA1', 'SOME-SHA1') - package.license_declared = NoAssert() - package.conc_lics = NoAssert() - - file1 = File('./some/path/tofile') - file1.name = './some/path/tofile' - file1.spdx_id = 'SPDXRef-File' - file1.chk_sum = Algorithm('SHA1', 'SOME-SHA1') - file1.conc_lics = NoAssert() - file1.copyright = NoAssert() - - lic1 = License.from_identifier('LGPL-2.1-only') - if or_later: - lic1 = License.from_identifier('LGPL-2.1-or-later') - - file1.add_lics(lic1) - - package.add_lics_from_file(lic1) - package.add_file(file1) - return doc - - def test_write_document_rdf_with_validate(self): - from spdx.writers.rdf import write_document - doc = self._get_lgpl_doc() - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple.rdf') - with open(result_file, 'wb') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/rdf-simple.json', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_rdf_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_rdf_with_or_later_with_validate(self): - from spdx.writers.rdf import write_document - doc = self._get_lgpl_doc(or_later=True) - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple-plus.rdf') - - # test proper! - with open(result_file, 'wb') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/rdf-simple-plus.json', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_rdf_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_tv_with_validate(self): - from spdx.writers.tagvalue import write_document - doc = self._get_lgpl_doc() - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple.tv') - with open(result_file, 'w') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/tv-simple.tv', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_tv_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_tv_with_or_later_with_validate(self): - from spdx.writers.tagvalue import write_document - - doc = self._get_lgpl_doc(or_later=True) - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple-plus.tv') - - # test proper! - with open(result_file, 'w') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/tv-simple-plus.tv', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_tv_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_json_with_validate(self): - from spdx.writers.json import write_document - doc = self._get_lgpl_doc() - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple.json') - with open(result_file, 'w') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/json-simple.json', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_json_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_json_with_or_later_with_validate(self): - from spdx.writers.json import write_document - doc = self._get_lgpl_doc(or_later=True) - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple-plus.json') - with open(result_file, 'w') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/json-simple-plus.json', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_json_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_yaml_with_validate(self): - from spdx.writers.yaml import write_document - doc = self._get_lgpl_doc() - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple.yaml') - with open(result_file, 'w') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/yaml-simple.yaml', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_yaml_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_yaml_with_or_later_with_validate(self): - from spdx.writers.yaml import write_document - doc = self._get_lgpl_doc(or_later=True) - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple-plus.yaml') - with open(result_file, 'w') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/yaml-simple-plus.yaml', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_yaml_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_xml_with_validate(self): - from spdx.writers.xml import write_document - doc = self._get_lgpl_doc() - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple.xml') - with open(result_file, 'w') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/xml-simple.xml', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_xml_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_xml_with_or_later_with_validate(self): - from spdx.writers.xml import write_document - doc = self._get_lgpl_doc(or_later=True) - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple-plus.xml') - with open(result_file, 'w') as output: - write_document(doc, output, validate=True) - - expected_file = utils_test.get_test_loc( - 'doc_write/xml-simple-plus.xml', - test_data_dir=utils_test.test_data_dir) - - utils_test.check_xml_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def _get_mini_doc(self,): - doc = Document(Version(2, 1), License.from_identifier('CC0-1.0')) - doc.creation_info.add_creator(Tool('ScanCode')) - doc.creation_info.set_created_now() - - package = doc.package = Package(download_location=NoAssert()) - package.license_declared = NoAssert() - package.conc_lics = NoAssert() - return doc - - def test_write_document_tv_mini(self): - from spdx.writers.tagvalue import write_document - doc = self._get_mini_doc() - - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple.tv') - with open(result_file, 'w') as output: - write_document(doc, output, validate=False) - expected_file = utils_test.get_test_loc('doc_write/tv-mini.tv') - utils_test.check_tv_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - def test_write_document_rdf_mini(self): - from spdx.writers.rdf import write_document - doc = self._get_mini_doc() - temp_dir = '' - try: - temp_dir = tempfile.mkdtemp(prefix='test_spdx') - result_file = os.path.join(temp_dir, 'spdx-simple.rdf') - with open(result_file, 'wb') as output: - write_document(doc, output, validate=False) - expected_file = utils_test.get_test_loc('doc_write/rdf-mini.json') - utils_test.check_rdf_scan(expected_file, result_file, regen=False) - finally: - if temp_dir and os.path.exists(temp_dir): - shutil.rmtree(temp_dir) - - -class TestLicense(TestCase): - maxDiff = None - - def test_url(self): - lic = License(full_name='Apache License 1.0', identifier='Apache-1.0') - assert lic.url == 'http://spdx.org/licenses/Apache-1.0' - - def test_license_list(self): - assert LICENSE_MAP['Aladdin Free Public License'] == 'Aladdin' - assert LICENSE_MAP['Aladdin'] == 'Aladdin Free Public License' - assert LICENSE_MAP['MIT License'] == 'MIT' - assert LICENSE_MAP['MIT'] == 'MIT License' - assert LICENSE_MAP['BSD 4-Clause "Original" or "Old" License'] == 'BSD-4-Clause' - assert LICENSE_MAP['BSD-4-Clause'] == 'BSD 4-Clause "Original" or "Old" License' - - def test_from_full_name(self): - mit = License.from_full_name('MIT License') - assert mit.identifier == 'MIT' - assert mit.url == 'http://spdx.org/licenses/MIT' - - def test_from_identifier(self): - mit = License.from_identifier('MIT') - assert mit.full_name == 'MIT License' - assert mit.url == 'http://spdx.org/licenses/MIT' - - -class TestException(TestCase): - - def test_exception_list(self): - assert EXCEPTION_MAP['Linux Syscall Note'] == 'Linux-syscall-note' - assert EXCEPTION_MAP['Linux-syscall-note'] == 'Linux Syscall Note' - assert EXCEPTION_MAP['GCC Runtime Library exception 3.1'] == 'GCC-exception-3.1' - assert EXCEPTION_MAP['GCC-exception-3.1'] == 'GCC Runtime Library exception 3.1' diff --git a/tests/test_jsonyamlxml_parser.py b/tests/test_jsonyamlxml_parser.py deleted file mode 100644 index f65e01e64..000000000 --- a/tests/test_jsonyamlxml_parser.py +++ /dev/null @@ -1,67 +0,0 @@ - -# Copyright (c) Xavier Figueroa -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from collections import OrderedDict -import io -import json -from unittest import TestCase - -from spdx.parsers import jsonparser, yamlparser, xmlparser -from spdx.parsers.jsonyamlxmlbuilders import Builder -from spdx.parsers.loggers import StandardLogger - -from tests import utils_test -from tests.utils_test import TestParserUtils - - -class TestParser(TestCase): - maxDiff = None - - def check_document(self, document, expected_loc, regen=False): - result = TestParserUtils.to_dict(document) - - if regen: - with open(expected_loc, 'wb') as o: - o.write(json.dumps(result, indent=2)) - - with io.open(expected_loc, encoding='utf-8') as ex: - expected = json.load(ex, encoding='utf-8', object_pairs_hook=OrderedDict) - - self.assertEqual(expected, result) - - def test_json_parser(self): - parser = jsonparser.Parser(Builder(), StandardLogger()) - test_file = utils_test.get_test_loc('formats/SPDXJsonExample.json') - with io.open(test_file, encoding='utf-8') as f: - document, _ = parser.parse(f) - expected_loc = utils_test.get_test_loc('doc_parse/expected.json') - self.check_document(document, expected_loc) - - def test_yaml_parser(self): - parser = yamlparser.Parser(Builder(), StandardLogger()) - test_file = utils_test.get_test_loc('formats/SPDXYamlExample.yaml') - with io.open(test_file, encoding='utf-8') as f: - document, _ = parser.parse(f) - expected_loc = utils_test.get_test_loc('doc_parse/expected.json') - self.check_document(document, expected_loc) - - def test_xml_parser(self): - parser = xmlparser.Parser(Builder(), StandardLogger()) - test_file = utils_test.get_test_loc('formats/SPDXXmlExample.xml') - with io.open(test_file, encoding='utf-8') as f: - document, _ = parser.parse(f) - expected_loc = utils_test.get_test_loc('doc_parse/expected.json') - self.check_document(document, expected_loc) diff --git a/tests/test_package.py b/tests/test_package.py deleted file mode 100644 index 22f825cf1..000000000 --- a/tests/test_package.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import unittest -from unittest import TestCase - -from spdx.package import Package - - -class TestPackage(TestCase): - - def test_calc_verif_code(self): - package = Package() - package.calc_verif_code() - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/test_parsers_validation.py b/tests/test_parsers_validation.py deleted file mode 100644 index 131fe0b43..000000000 --- a/tests/test_parsers_validation.py +++ /dev/null @@ -1,38 +0,0 @@ - -# Copyright (c) SPDX Python tools authors -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -from unittest import TestCase - -from spdx.parsers import validations -from spdx import utils - - -class TestValidations(TestCase): - maxDiff = None - - def test_validate_pkg_cr_text_does_not_crash_on_None(self): - validations.validate_pkg_cr_text(None) - - def test_validate_pkg_cr_text_does_not_crash_on_NoAssert_or_SPDXNone(self): - validations.validate_pkg_cr_text(utils.NoAssert()) - validations.validate_pkg_cr_text(utils.SPDXNone()) - - def test_validate_file_cpyright_does_not_crash_on_None(self): - validations.validate_file_cpyright(None) - - def test_validate_file_cpyright_does_not_crash_on_NoAssert_or_SPDXNone(self): - validations.validate_file_cpyright(utils.NoAssert()) - validations.validate_file_cpyright(utils.SPDXNone()) diff --git a/tests/test_rdf_parser.py b/tests/test_rdf_parser.py deleted file mode 100644 index bb05e24c8..000000000 --- a/tests/test_rdf_parser.py +++ /dev/null @@ -1,78 +0,0 @@ - -# Copyright (c) the SPDX tools authors -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import io -import json -import unittest - -import six - -from spdx.parsers import rdf -from spdx.parsers.loggers import StandardLogger -from spdx.parsers.rdfbuilders import Builder as RDFBuilder - -from tests import utils_test -from tests.utils_test import TestParserUtils - - -class TestParser(unittest.TestCase): - maxDiff = None - - def test_rdf_parser(self): - parser = rdf.Parser(RDFBuilder(), StandardLogger()) - test_file = utils_test.get_test_loc('formats/SPDXRdfExample.rdf', test_data_dir=utils_test.test_data_dir) - with io.open(test_file, 'rb') as f: - document, _ = parser.parse(f) - expected_loc = utils_test.get_test_loc('doc_parse/spdx-expected.json', test_data_dir=utils_test.test_data_dir) - self.check_document(document, expected_loc) - - def check_document(self, document, expected_loc, regen=False): - result = TestParserUtils.to_dict(document) - - if regen: - data = json.dumps(result, indent=2) - if six.PY3: - data = data.encode('utf-8') - with io.open(expected_loc, 'wb') as o: - o.write(data) - - with io.open(expected_loc, 'r', encoding='utf-8') as ex: - expected = json.load(ex) - - self.check_fields(result, expected) - assert expected == result - - def check_fields(self, result, expected): - """ - Test result and expected objects field by field - to provide more specific error messages when failing - """ - assert expected['id'] == result['id'] - assert expected['specVersion'] == result['specVersion'] - assert expected['namespace'] == result['namespace'] - assert expected['name'] == result['name'] - assert expected['comment'] == result['comment'] - assert expected['dataLicense'] == result['dataLicense'] - assert expected['licenseListVersion'] == result['licenseListVersion'] - assert expected['creators'] == result['creators'] - assert expected['created'] == result['created'] - assert expected['creatorComment'] == result['creatorComment'] - assert expected['package']['files'] == result['package']['files'] - assert expected['package'] == result['package'] - assert expected['externalDocumentRefs'] == result['externalDocumentRefs'] - assert expected['extractedLicenses'] == result['extractedLicenses'] - assert expected['annotations'] == result['annotations'] - assert expected['reviews'] == result['reviews'] diff --git a/tests/test_tag_value_parser.py b/tests/test_tag_value_parser.py deleted file mode 100644 index 10afa8eec..000000000 --- a/tests/test_tag_value_parser.py +++ /dev/null @@ -1,353 +0,0 @@ -# Copyright (c) 2014 Ahmed H. Ismail -# 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. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import sys -from unittest import TestCase - -import spdx -from spdx.parsers.tagvalue import Parser -from spdx.parsers.lexers.tagvalue import Lexer -from spdx.parsers.tagvaluebuilders import Builder -from spdx.parsers.loggers import StandardLogger -from spdx.version import Version - - -class TestLexer(TestCase): - maxDiff = None - - def setUp(self): - self.l = Lexer() - self.l.build() - - def test_document(self): - data = ''' - SPDXVersion: SPDX-2.1 - # Comment. - DataLicense: CC0-1.0 - DocumentName: Sample_Document-V2.1 - SPDXID: SPDXRef-DOCUMENT - DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 - DocumentComment: This is a sample spreadsheet - ''' - self.l.input(data) - self.token_assert_helper(self.l.token(), 'DOC_VERSION', 'SPDXVersion', 2) - self.token_assert_helper(self.l.token(), 'LINE', 'SPDX-2.1', 2) - self.token_assert_helper(self.l.token(), 'DOC_LICENSE', 'DataLicense', 4) - self.token_assert_helper(self.l.token(), 'LINE', 'CC0-1.0', 4) - self.token_assert_helper(self.l.token(), 'DOC_NAME', 'DocumentName', 5) - self.token_assert_helper(self.l.token(), 'LINE', 'Sample_Document-V2.1', - 5) - self.token_assert_helper(self.l.token(), 'SPDX_ID', 'SPDXID', 6) - self.token_assert_helper(self.l.token(), 'LINE', 'SPDXRef-DOCUMENT', 6) - self.token_assert_helper(self.l.token(), 'DOC_NAMESPACE', - 'DocumentNamespace', 7) - self.token_assert_helper(self.l.token(), 'LINE', - 'https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301', - 7) - self.token_assert_helper(self.l.token(), 'DOC_COMMENT', 'DocumentComment', 8) - self.token_assert_helper(self.l.token(), 'TEXT', 'This is a sample spreadsheet', 8) - - def test_external_document_references(self): - data = ''' - ExternalDocumentRef:DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759 - ''' - self.l.input(data) - self.token_assert_helper(self.l.token(), 'EXT_DOC_REF', - 'ExternalDocumentRef', 2) - self.token_assert_helper(self.l.token(), 'DOC_REF_ID', - 'DocumentRef-spdx-tool-2.1', 2) - self.token_assert_helper(self.l.token(), 'DOC_URI', - 'http://spdx.org/spdxdocs/spdx-tools-v2.1-3F25' - '04E0-4F89-41D3-9A0C-0305E82C3301', 2) - self.token_assert_helper(self.l.token(), 'EXT_DOC_REF_CHKSUM', - 'SHA1: ' - 'd6a770ba38583ed4bb4525bd96e50461655d2759', 2) - - - def test_creation_info(self): - data = ''' - ## Creation Information - Creator: Person: Gary O'Neall - Creator: Organization: Source Auditor Inc. - Creator: Tool: SourceAuditor-V1.2 - Created: 2010-02-03T00:00:00Z - CreatorComment: This is an example of an SPDX - spreadsheet format - ''' - self.l.input(data) - self.token_assert_helper(self.l.token(), 'CREATOR', 'Creator', 3) - self.token_assert_helper(self.l.token(), 'PERSON_VALUE', "Person: Gary O'Neall", 3) - self.token_assert_helper(self.l.token(), 'CREATOR', 'Creator', 4) - self.token_assert_helper(self.l.token(), 'ORG_VALUE', 'Organization: Source Auditor Inc.', 4) - self.token_assert_helper(self.l.token(), 'CREATOR', 'Creator', 5) - self.token_assert_helper(self.l.token(), 'TOOL_VALUE', 'Tool: SourceAuditor-V1.2', 5) - self.token_assert_helper(self.l.token(), 'CREATED', 'Created', 6) - self.token_assert_helper(self.l.token(), 'DATE', '2010-02-03T00:00:00Z', 6) - - def test_review_info(self): - data = ''' - Reviewer: Person: Joe Reviewer - ReviewDate: 2010-02-10T00:00:00Z - ReviewComment: This is just an example. - Some of the non-standard licenses look like they are actually - BSD 3 clause licenses - ''' - self.l.input(data) - self.token_assert_helper(self.l.token(), 'REVIEWER', 'Reviewer', 2) - self.token_assert_helper(self.l.token(), 'PERSON_VALUE', "Person: Joe Reviewer", 2) - self.token_assert_helper(self.l.token(), 'REVIEW_DATE', 'ReviewDate', 3) - self.token_assert_helper(self.l.token(), 'DATE', '2010-02-10T00:00:00Z', 3) - self.token_assert_helper(self.l.token(), 'REVIEW_COMMENT', 'ReviewComment', 4) - self.token_assert_helper(self.l.token(), 'TEXT', '''This is just an example. - Some of the non-standard licenses look like they are actually - BSD 3 clause licenses''', 4) - - def test_pacakage(self): - data = ''' - SPDXID: SPDXRef-Package - FilesAnalyzed: False - PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (SpdxTranslatorSpdx.rdf, SpdxTranslatorSpdx.txt) - ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*: - ExternalRefComment: Some comment about the package. - ''' - self.l.input(data) - self.token_assert_helper(self.l.token(), 'SPDX_ID', 'SPDXID', 2) - self.token_assert_helper(self.l.token(), 'LINE', 'SPDXRef-Package', 2) - self.token_assert_helper(self.l.token(), 'PKG_FILES_ANALYZED', 'FilesAnalyzed', 3) - self.token_assert_helper(self.l.token(), 'LINE', 'False', 3) - self.token_assert_helper(self.l.token(), 'PKG_CHKSUM', 'PackageChecksum', 4) - self.token_assert_helper(self.l.token(), 'CHKSUM', 'SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12', 4) - self.token_assert_helper(self.l.token(), 'PKG_VERF_CODE', 'PackageVerificationCode', 5) - self.token_assert_helper(self.l.token(), 'LINE', '4e3211c67a2d28fced849ee1bb76e7391b93feba (SpdxTranslatorSpdx.rdf, SpdxTranslatorSpdx.txt)', 5) - self.token_assert_helper(self.l.token(), 'PKG_EXT_REF', 'ExternalRef', 6) - self.token_assert_helper(self.l.token(), 'LINE', 'SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:', 6) - self.token_assert_helper(self.l.token(), 'PKG_EXT_REF_COMMENT', 'ExternalRefComment', 7) - self.token_assert_helper(self.l.token(), 'TEXT', 'Some comment about the package.', 7) - - def test_unknown_tag(self): - data = ''' - SomeUnknownTag: SomeUnknownValue - ''' - self.l.input(data) - self.token_assert_helper(self.l.token(), 'UNKNOWN_TAG', 'SomeUnknownTag', 2) - self.token_assert_helper(self.l.token(), 'LINE', 'SomeUnknownValue', 2) - - def test_snippet(self): - data = ''' - SnippetSPDXID: SPDXRef-Snippet - SnippetLicenseComments: Some lic comment. - SnippetCopyrightText: Some cr text. - SnippetComment: Some snippet comment. - SnippetName: from linux kernel - SnippetFromFileSPDXID: SPDXRef-DoapSource - SnippetLicenseConcluded: Apache-2.0 - LicenseInfoInSnippet: Apache-2.0 - ''' - self.l.input(data) - self.token_assert_helper(self.l.token(), 'SNIPPET_SPDX_ID', 'SnippetSPDXID', 2) - self.token_assert_helper(self.l.token(), 'LINE', 'SPDXRef-Snippet', 2) - self.token_assert_helper(self.l.token(), 'SNIPPET_LICS_COMMENT', 'SnippetLicenseComments', 3) - self.token_assert_helper(self.l.token(), 'TEXT', 'Some lic comment.', 3) - self.token_assert_helper(self.l.token(), 'SNIPPET_CR_TEXT', 'SnippetCopyrightText', 4) - self.token_assert_helper(self.l.token(), 'TEXT', 'Some cr text.', 4) - self.token_assert_helper(self.l.token(), 'SNIPPET_COMMENT', 'SnippetComment', 5) - self.token_assert_helper(self.l.token(), 'TEXT', 'Some snippet comment.', 5) - self.token_assert_helper(self.l.token(), 'SNIPPET_NAME', 'SnippetName', 6) - self.token_assert_helper(self.l.token(), 'LINE', 'from linux kernel', 6) - self.token_assert_helper(self.l.token(), 'SNIPPET_FILE_SPDXID', - 'SnippetFromFileSPDXID', 7) - self.token_assert_helper(self.l.token(), 'LINE', 'SPDXRef-DoapSource', 7) - self.token_assert_helper(self.l.token(), 'SNIPPET_LICS_CONC', - 'SnippetLicenseConcluded', 8) - self.token_assert_helper(self.l.token(), 'LINE', 'Apache-2.0', 8) - self.token_assert_helper(self.l.token(), 'SNIPPET_LICS_INFO', - 'LicenseInfoInSnippet', 9) - self.token_assert_helper(self.l.token(), 'LINE', 'Apache-2.0', 9) - - def token_assert_helper(self, token, ttype, value, line): - assert token.type == ttype - assert token.value == value - assert token.lineno == line - - -class TestParser(TestCase): - maxDiff = None - - document_str = '\n'.join([ - 'SPDXVersion: SPDX-2.1', - 'DataLicense: CC0-1.0', - 'DocumentName: Sample_Document-V2.1', - 'SPDXID: SPDXRef-DOCUMENT', - 'DocumentComment: Sample Comment', - 'DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301' - ]) - - creation_str = '\n'.join([ - 'Creator: Person: Bob (bob@example.com)', - 'Creator: Organization: Acme.', - 'Created: 2010-02-03T00:00:00Z', - 'CreatorComment: Sample Comment' - ]) - - review_str = '\n'.join([ - 'Reviewer: Person: Bob the Reviewer', - 'ReviewDate: 2010-02-10T00:00:00Z', - 'ReviewComment: Bob was Here.', - 'Reviewer: Person: Alice the Reviewer', - 'ReviewDate: 2011-02-10T00:00:00Z', - 'ReviewComment: Alice was also here.' - ]) - - package_str = '\n'.join([ - 'PackageName: Test', - 'SPDXID: SPDXRef-Package', - 'PackageVersion: Version 0.9.2', - 'PackageDownloadLocation: http://example.com/test', - 'FilesAnalyzed: False', - 'PackageSummary: Test package', - 'PackageSourceInfo: Version 1.0 of test', - 'PackageFileName: test-1.0.zip', - 'PackageSupplier: Organization:ACME', - 'PackageOriginator: Organization:ACME', - 'PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12', - 'PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)', - 'PackageDescription: A package.', - 'PackageComment: Comment on the package.', - 'PackageCopyrightText: Copyright 2014 Acme Inc.', - 'PackageLicenseDeclared: Apache-2.0', - 'PackageLicenseConcluded: (LicenseRef-2.0 and Apache-2.0)', - 'PackageLicenseInfoFromFiles: Apache-1.0', - 'PackageLicenseInfoFromFiles: Apache-2.0', - 'PackageLicenseComments: License Comments', - 'ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:', - 'ExternalRefComment: Some comment about the package.' - ]) - - file_str = '\n'.join([ - 'FileName: testfile.java', - 'SPDXID: SPDXRef-File', - 'FileType: SOURCE', - 'FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12', - 'LicenseConcluded: Apache-2.0', - 'LicenseInfoInFile: Apache-2.0', - 'FileCopyrightText: Copyright 2014 Acme Inc.', - 'ArtifactOfProjectName: AcmeTest', - 'ArtifactOfProjectHomePage: http://www.acme.org/', - 'ArtifactOfProjectURI: http://www.acme.org/', - 'FileComment: Very long file' - ]) - - unknown_tag_str = 'SomeUnknownTag: SomeUnknownValue' - - snippet_str = '\n'.join([ - 'SnippetSPDXID: SPDXRef-Snippet', - 'SnippetLicenseComments: Some lic comment.', - 'SnippetCopyrightText: Copyright 2008-2010 John Smith ', - 'SnippetComment: Some snippet comment.', - 'SnippetName: from linux kernel', - 'SnippetFromFileSPDXID: SPDXRef-DoapSource', - 'SnippetLicenseConcluded: Apache-2.0', - 'LicenseInfoInSnippet: Apache-2.0', - ]) - - complete_str = '{0}\n{1}\n{2}\n{3}\n{4}\n{5}'.format(document_str, creation_str, review_str, package_str, file_str, snippet_str) - - def setUp(self): - self.p = Parser(Builder(), StandardLogger()) - self.p.build() - - def test_doc(self): - document, error = self.p.parse(self.complete_str) - assert document is not None - assert not error - assert document.version == Version(major=2, minor=1) - assert document.data_license.identifier == 'CC0-1.0' - assert document.name == 'Sample_Document-V2.1' - assert document.spdx_id == 'SPDXRef-DOCUMENT' - assert document.comment == 'Sample Comment' - assert document.namespace == 'https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301' - - def test_creation_info(self): - document, error = self.p.parse(self.complete_str) - assert document is not None - assert not error - assert len(document.creation_info.creators) == 2 - assert document.creation_info.comment == 'Sample Comment' - assert (document.creation_info.created_iso_format == '2010-02-03T00:00:00Z') - - def test_review(self): - document, error = self.p.parse(self.complete_str) - assert document is not None - assert not error - assert len(document.reviews) == 2 - - def test_package(self): - document, error = self.p.parse(self.complete_str) - assert document is not None - assert not error - assert document.package.name == 'Test' - assert document.package.spdx_id == 'SPDXRef-Package' - assert document.package.version == 'Version 0.9.2' - assert len(document.package.licenses_from_files) == 2 - assert (document.package.conc_lics.identifier == 'LicenseRef-2.0 AND Apache-2.0') - assert document.package.files_analyzed == 'False' - assert document.package.comment == 'Comment on the package.' - assert document.package.pkg_ext_refs[-1].category == 'SECURITY' - assert document.package.pkg_ext_refs[-1].pkg_ext_ref_type == 'cpe23Type' - assert document.package.pkg_ext_refs[-1].locator == 'cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:' - assert document.package.pkg_ext_refs[-1].comment == 'Some comment about the package.' - - def test_file(self): - document, error = self.p.parse(self.complete_str) - assert document is not None - assert not error - assert len(document.package.files) == 1 - spdx_file = document.package.files[0] - assert spdx_file.name == 'testfile.java' - assert spdx_file.spdx_id == 'SPDXRef-File' - assert spdx_file.type == spdx.file.FileType.SOURCE - assert len(spdx_file.artifact_of_project_name) == 1 - assert len(spdx_file.artifact_of_project_home) == 1 - assert len(spdx_file.artifact_of_project_uri) == 1 - - def test_unknown_tag(self): - - try: - from StringIO import StringIO - except ImportError: - from io import StringIO - - saved_out = sys.stdout - sys.stdout = StringIO() - document, error = self.p.parse(self.unknown_tag_str) - self.assertEqual(sys.stdout.getvalue(), 'Found unknown tag : SomeUnknownTag at line: 1\n') - sys.stdout = saved_out - assert error - assert document is not None - - def test_snippet(self): - document, error = self.p.parse(self.complete_str) - assert document is not None - assert not error - assert len(document.snippet) == 1 - assert document.snippet[-1].spdx_id == 'SPDXRef-Snippet' - assert document.snippet[-1].name == 'from linux kernel' - assert document.snippet[-1].comment == 'Some snippet comment.' - assert document.snippet[-1].copyright == ' Copyright 2008-2010 John Smith ' - assert document.snippet[-1].license_comment == 'Some lic comment.' - assert document.snippet[-1].snip_from_file_spdxid == 'SPDXRef-DoapSource' - assert document.snippet[-1].conc_lics.identifier == 'Apache-2.0' - assert document.snippet[-1].licenses_in_snippet[-1].identifier == 'Apache-2.0' diff --git a/tests/testing_utils.LICENSE b/tests/testing_utils.LICENSE deleted file mode 100644 index 2fb889408..000000000 --- a/tests/testing_utils.LICENSE +++ /dev/null @@ -1,502 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/tests/testing_utils.py b/tests/testing_utils.py deleted file mode 100644 index b8ff607c6..000000000 --- a/tests/testing_utils.py +++ /dev/null @@ -1,81 +0,0 @@ -# Subset of nose tools (the parts included have not been modified) -# Borrowed from: -# https://raw.githubusercontent.com/nose-devs/nose/7c26ad1e6b7d308cafa328ad34736d34028c122a/nose/tools/nontrivial.py -# Copyright (c) 2005-2009 Jason Pellerin and others. -# -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, -# Fifth Floor, Boston, MA 02110-1301 USA -# - -"""Tools not exempt from being descended into in tracebacks""" - -import six - - -def make_decorator(func): - """ - Wraps a test decorator so as to properly replicate metadata - of the decorated function, including nose's additional stuff - (namely, setup and teardown). - """ - def decorate(newfunc): - if hasattr(func, 'compat_func_name'): - name = func.compat_func_name - else: - name = func.__name__ - newfunc.__dict__ = func.__dict__ - newfunc.__doc__ = func.__doc__ - newfunc.__module__ = func.__module__ - if not hasattr(newfunc, 'compat_co_firstlineno'): - newfunc.compat_co_firstlineno = six.get_function_code(func).co_firstlineno - try: - newfunc.__name__ = name - except TypeError: - # can't set func name in 2.3 - newfunc.compat_func_name = name - return newfunc - return decorate - - -def raises(*exceptions): - """Test must raise one of expected exceptions to pass. - - Example use:: - - @raises(TypeError, ValueError) - def test_raises_type_error(): - raise TypeError("This test passes") - - @raises(Exception) - def test_that_fails_by_passing(): - pass - - If you want to test many assertions about exceptions in a single test, - you may want to use `assert_raises` instead. - """ - valid = ' or '.join([e.__name__ for e in exceptions]) - def decorate(func): - name = func.__name__ - def newfunc(*arg, **kw): - try: - func(*arg, **kw) - except exceptions: - pass - except: - raise - else: - message = "%s() did not raise %s" % (name, valid) - raise AssertionError(message) - newfunc = make_decorator(func)(newfunc) - return newfunc - return decorate - diff --git a/tests/utils_test.py b/tests/utils_test.py deleted file mode 100644 index 01faf8c53..000000000 --- a/tests/utils_test.py +++ /dev/null @@ -1,516 +0,0 @@ - -# Copyright (c) the SPDX tools authors -# 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. - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -from collections import OrderedDict -import io -import json -import ntpath -import os -import posixpath -import re - -import xmltodict -import yaml - -import spdx -from spdx import utils - - -test_data_dir = os.path.join(os.path.dirname(__file__), 'data') - - -def get_test_loc(test_path, test_data_dir=test_data_dir, debug=False, exists=True): - """ - Given a `test_path` relative to the `test_data_dir` directory, return the - location to a test file or directory for this path. No copy is done. - """ - if debug: - import inspect - caller = inspect.stack()[1][3] - print('\nget_test_loc,%(caller)s,"%(test_path)s","%(test_data_dir)s"' % locals()) - - assert test_path - assert test_data_dir - - if not os.path.exists(test_data_dir): - raise IOError("[Errno 2] No such directory: test_data_dir not found:" - " '%(test_data_dir)s'" % locals()) - - tpath = to_os_native_path(test_path) - test_loc = os.path.abspath(os.path.join(test_data_dir, tpath)) - - if exists and not os.path.exists(test_loc): - raise IOError("[Errno 2] No such file or directory: " - "test_path not found: '%(test_loc)s'" % locals()) - - return test_loc - - -def to_os_native_path(path): - """ - Normalize a path to use the native OS path separator. - """ - path = path.replace(posixpath.sep, os.path.sep) - path = path.replace(ntpath.sep, os.path.sep) - path = path.rstrip(os.path.sep) - return path - - -def strip_variable_text(rdf_text): - """ - Return rdf_text stripped from variable parts such as rdf nodeids - """ - - replace_nid = re.compile('rdf:nodeID="[^\"]*"').sub - rdf_text = replace_nid('', rdf_text) - - replace_creation = re.compile('.*', re.DOTALL).sub - rdf_text = replace_creation('', rdf_text) - - replace_pcc = re.compile('.*', re.DOTALL).sub - rdf_text = replace_pcc('', rdf_text) - return rdf_text - - -def load_and_clean_rdf(location): - """ - Return plain Python nested data for the SPDX RDF file at location suitable - for comparison. The file content is cleaned from variable parts such as - dates, generated UUIDs and versions - - NOTE: we use plain dicts to avoid ordering issues in XML. the SPDX tool and - lxml do not seem to return a consistent ordering that is needed for tests. - """ - with io.open(location, encoding='utf-8') as l: - content = l.read() - content = strip_variable_text(content) - data = xmltodict.parse(content, dict_constructor=dict) - return sort_nested(data) - - -def sort_nested(data): - """ - Return a new dict with any nested list sorted recursively. - """ - if isinstance(data, dict): - new_data = {} - for k, v in data.items(): - if isinstance(v, list): - v = sorted(v) - if isinstance(v, dict): - v = sort_nested(v) - new_data[k] = v - return new_data - elif isinstance(data, list): - new_data = [] - for v in sorted(data): - if isinstance(v, list): - v = sort_nested(v) - if isinstance(v, dict): - v = sort_nested(v) - new_data.append(v) - return new_data - - -def check_rdf_scan(expected_file, result_file, regen=False): - """ - Check that expected and result_file are equal. - Both are paths to SPDX RDF XML files, UTF-8 encoded. - """ - result = load_and_clean_rdf(result_file) - if regen: - expected = result - with io.open(expected_file, 'w', encoding='utf-8') as o: - json.dump(expected, o, indent=2) - else: - with io.open(expected_file, 'r', encoding='utf-8') as i: - expected = sort_nested(json.load(i)) - assert expected == result - - -def load_and_clean_tv(location): - """ - Return a mapping for the SPDX TV file at location suitable for comparison. - The file content is cleaned from variable parts such as dates, generated - UUIDs and versions - """ - with io.open(location, encoding='utf-8') as l: - content = l.read() - content = [l for l in content.splitlines(False) - if l and l.strip() and not l.startswith(('Creator: ', 'Created: ',))] - return '\n'.join(content) - - -def check_tv_scan(expected_file, result_file, regen=False): - """ - Check that expected and result_file are equal. - Both are paths to plain SPDX tv text files, UTF-8 encoded. - """ - result = load_and_clean_tv(result_file) - if regen: - with io.open(expected_file, 'w') as o: - o.write(result) - - expected = load_and_clean_tv(expected_file) - assert expected == result - - -def load_and_clean_json(location): - """ - Return plain Python nested data for the SPDX JSON file at location suitable - for comparison. The file content is cleaned from variable parts such as - dates, generated UUIDs and versions - """ - with io.open(location, encoding='utf-8') as l: - content = l.read() - data = json.loads(content) - - if 'creationInfo' in data['Document']: - del(data['Document']['creationInfo']) - - return sort_nested(data) - - -def check_json_scan(expected_file, result_file, regen=False): - """ - Check that expected_file and result_file are equal. - Both are paths to SPDX JSON files, UTF-8 encoded. - """ - result = load_and_clean_json(result_file) - if regen: - with io.open(expected_file, 'w', encoding='utf-8') as o: - o.write(result) - - expected = load_and_clean_json(expected_file) - assert expected == result - - -def load_and_clean_yaml(location): - """ - Return plain Python nested data for the SPDX YAML file at location suitable - for comparison. The file content is cleaned from variable parts such as - dates, generated UUIDs and versions - """ - with io.open(location, encoding='utf-8') as l: - content = l.read() - data = yaml.safe_load(content) - - if 'creationInfo' in data['Document']: - del(data['Document']['creationInfo']) - - return sort_nested(data) - - -def check_yaml_scan(expected_file, result_file, regen=False): - """ - Check that expected_file and result_file are equal. - Both are paths to SPDX YAML files, UTF-8 encoded. - """ - result = load_and_clean_yaml(result_file) - if regen: - with io.open(expected_file, 'w', encoding='utf-8') as o: - o.write(result) - - expected = load_and_clean_yaml(expected_file) - assert expected == result - - -def load_and_clean_xml(location): - """ - Return plain Python nested data for the SPDX XML file at location suitable - for comparison. The file content is cleaned from variable parts such as - dates, generated UUIDs and versions - """ - with io.open(location, encoding='utf-8') as l: - content = l.read() - data = xmltodict.parse(content, encoding='utf-8') - - if 'creationInfo' in data['SpdxDocument']['Document']: - del(data['SpdxDocument']['Document']['creationInfo']) - - return sort_nested(data) - - -def check_xml_scan(expected_file, result_file, regen=False): - """ - Check that expected_file and result_file are equal. - Both are paths to SPDX XML files, UTF-8 encoded. - """ - result = load_and_clean_xml(result_file) - if regen: - with io.open(expected_file, 'w', encoding='utf-8') as o: - o.write(result) - - expected = load_and_clean_xml(expected_file) - assert expected == result - - -class TestParserUtils(object): - """ - Helper class to represent SPDX Document models as Python types after parsing - to be compared to expected data from a JSON file. - """ - - @classmethod - def license_to_dict(cls, license): - """ - Represents spdx.document.License, spdx.document.LicenseConjunction or - spdx.document.LicenseDisjunction as a Python dictionary - """ - CONJ_SEP = re.compile(' AND | and ') - DISJ_SEP = re.compile(' OR | or ') - - license_dict = OrderedDict() - - if isinstance(license, spdx.document.LicenseConjunction): - license_dict['type'] = 'Conjunction' - sep_regex = CONJ_SEP - elif isinstance(license, spdx.document.LicenseDisjunction): - license_dict['type'] = 'Disjunction' - sep_regex = DISJ_SEP - else: - license_dict['type'] = 'Single' - license_dict['identifier'] = license.identifier - license_dict['name'] = license.full_name - return license_dict - - license_dict['identifier'] = sorted(sep_regex.split(license.identifier)) - license_dict['name'] = sorted(sep_regex.split(license.full_name)) - - return license_dict - - @classmethod - def version_to_dict(cls, version): - """ - Represents spdx.version.Version as a Python dictionary - """ - return OrderedDict([ - ('major', int(version.major)), - ('minor', int(version.minor)) - ]) - - @classmethod - def entity_to_dict(cls, entity): - """ - Represents spdx.creationInfo.Creator subclasses as a dictionary - """ - entity_dict = OrderedDict(name=entity.name) - - if isinstance(entity, spdx.creationinfo.Tool): - entity_dict['type'] = 'Tool' - return entity_dict - - entity_dict['email'] = entity.email - entity_dict['type'] = 'Person' - - if isinstance(entity, spdx.creationinfo.Organization): - entity_dict['type'] = 'Organization' - return entity_dict - - return entity_dict - - @classmethod - def checksum_to_dict(cls, checksum): - """ - Represents spdx.checksum.Algorithm as a Python dictionary - """ - return OrderedDict([ - ('identifier', checksum.identifier), - ('value', checksum.value)]) - - @classmethod - def package_to_dict(cls, package): - """ - Represents spdx.package.Package as a Python dictionary - """ - lics_from_files = sorted(package.licenses_from_files, key=lambda lic: lic.identifier) - return OrderedDict([ - ('id', package.spdx_id), - ('name', package.name), - ('packageFileName', package.file_name), - ('summary', package.summary), - ('description', package.description), - ('versionInfo', package.version), - ('sourceInfo', package.source_info), - ('downloadLocation', package.download_location), - ('homepage', package.homepage), - ('originator', cls.entity_to_dict(package.originator)), - ('supplier', cls.entity_to_dict(package.supplier)), - ('licenseConcluded', cls.license_to_dict(package.conc_lics)), - ('licenseDeclared', cls.license_to_dict(package.license_declared)), - ('copyrightText', package.cr_text), - ('licenseComment', package.license_comment), - ('checksum', cls.checksum_to_dict(package.check_sum)), - ('files', cls.files_to_list(sorted(package.files))), - ('licenseInfoFromFiles', [cls.license_to_dict(lic) for lic in lics_from_files]), - ('verificationCode', OrderedDict([ - ('value', package.verif_code), - ('excludedFilesNames', sorted(package.verif_exc_files))]) - ) - ]) - - @classmethod - def files_to_list(cls, files): - """ - Represents a list of spdx.file.File as a Python list of dictionaries - """ - files_list = [] - - for file in files: - lics_from_files = sorted(file.licenses_in_file, key=lambda lic: lic.identifier) - contributors = sorted(file.contributors, key=lambda c: c.name) - file_dict = OrderedDict([ - ('id', file.spdx_id), - ('name', file.name), - ('type', file.type), - ('comment', file.comment), - ('licenseConcluded', cls.license_to_dict(file.conc_lics)), - ('copyrightText', file.copyright), - ('licenseComment', file.license_comment), - ('notice', file.notice), - ('checksum', cls.checksum_to_dict(file.chk_sum)), - ('licenseInfoFromFiles', [cls.license_to_dict(lic) for lic in lics_from_files]), - ('contributors', [cls.entity_to_dict(contributor) for contributor in contributors]), - ('dependencies', sorted(file.dependencies)), - ('artifactOfProjectName', file.artifact_of_project_name), - ('artifactOfProjectHome', file.artifact_of_project_home), - ('artifactOfProjectURI', file.artifact_of_project_uri), - ]) - files_list.append(file_dict) - - return files_list - - @classmethod - def ext_document_references_to_list(cls, ext_doc_refs): - """ - Represents a list of spdx.document.ExternalDocumentRef as a Python list of dictionaries - """ - ext_doc_refs_list = [] - - for ext_doc_ref in ext_doc_refs: - ext_doc_ref_dict = OrderedDict([ - ('externalDocumentId', ext_doc_ref.external_document_id), - ('spdxDocumentNamespace', ext_doc_ref.spdx_document_uri), - ('checksum', cls.checksum_to_dict(ext_doc_ref.check_sum)), - ]) - ext_doc_refs_list.append(ext_doc_ref_dict) - - return ext_doc_refs_list - - @classmethod - def extracted_licenses_to_list(cls, extracted_licenses): - """ - Represents a list of spdx.document.ExtractedLicense as a Python list of dictionaries - """ - extracted_licenses_list = [] - - for extracted_license in extracted_licenses: - extracted_license_dict = OrderedDict([ - ('name', extracted_license.full_name), - ('identifier', extracted_license.identifier), - ('text', extracted_license.text), - ('comment', extracted_license.comment), - ('cross_refs', sorted(extracted_license.cross_ref)), - ]) - if extracted_license_dict not in extracted_licenses_list: - extracted_licenses_list.append(extracted_license_dict) - - return extracted_licenses_list - - @classmethod - def annotations_to_list(cls, annotations): - """ - Represents a list of spdx.annotation.Annotation as a Python list of dictionaries - """ - annotations_list = [] - - for annotation in annotations: - annotation_dict = OrderedDict([ - ('id', annotation.spdx_id), - ('comment', annotation.comment), - ('type', annotation.annotation_type), - ('annotator', cls.entity_to_dict(annotation.annotator)), - ('date', utils.datetime_iso_format(annotation.annotation_date)), - ]) - annotations_list.append(annotation_dict) - - return annotations_list - - @classmethod - def reviews_to_list(cls, reviews): - """ - Represents a list of spdx.review.Review as a Python list of dictionaries - """ - reviews_list = [] - - for review in reviews: - review_dict = OrderedDict([ - ('comment', review.comment), - ('reviewer', cls.entity_to_dict(review.reviewer)), - ('date', utils.datetime_iso_format(review.review_date)) - ]) - reviews_list.append(review_dict) - - return reviews_list - - @classmethod - def snippets_to_list(cls, snippets): - """ - Represents a list of spdx.snippet.Snippet as a Python list of dictionaries - """ - snippets_list = [] - - for snippet in snippets: - lics_from_snippet = sorted(snippet.licenses_in_snippet, key=lambda lic: lic.identifier) - snippet_dict = OrderedDict([ - ('id', snippet.spdx_id), - ('name', snippet.name), - ('comment', snippet.comment), - ('copyrightText', snippet.copyright), - ('licenseComments', snippet.license_comment), - ('fileId', snippet.snip_from_file_spdxid), - ('licenseConcluded', cls.license_to_dict(snippet.conc_lics)), - ('licenseInfoFromSnippet', [cls.license_to_dict(lic) for lic in lics_from_snippet]), - ]) - snippets_list.append(snippet_dict) - - return snippets_list - - @classmethod - def to_dict(cls, doc): - """ - Represents a SPDX Document (spdx.document.Document) as nested Python types - """ - creators = sorted(doc.creation_info.creators, key=lambda c: c.name) - return OrderedDict([ - ('id', doc.spdx_id), - ('specVersion', cls.version_to_dict(doc.version)), - ('namespace', doc.namespace), - ('name', doc.name), - ('comment', doc.comment), - ('dataLicense', cls.license_to_dict(doc.data_license)), - ('licenseListVersion', cls.version_to_dict(doc.creation_info.license_list_version)), - ('creators', [cls.entity_to_dict(creator) for creator in creators]), - ('created', utils.datetime_iso_format(doc.creation_info.created)), - ('creatorComment', doc.creation_info.comment), - ('package', cls.package_to_dict(doc.package)), - ('externalDocumentRefs', cls.ext_document_references_to_list(sorted(doc.ext_document_references))), - ('extractedLicenses', cls.extracted_licenses_to_list(sorted(doc.extracted_licenses))), - ('annotations', cls.annotations_to_list(sorted(doc.annotations))), - ('reviews', cls.reviews_to_list(sorted(doc.reviews))), - ('snippets', cls.snippets_to_list(sorted(doc.snippet))), - ]) diff --git a/tox.ini b/tox.ini deleted file mode 100644 index f69130f63..000000000 --- a/tox.ini +++ /dev/null @@ -1,24 +0,0 @@ -[tox] -envlist = - py{27,35,36,37,py,py3} -skipsdist = True - -[testenv] -commands = - {envbindir}/python -m pip install '{toxinidir}[format]' - {envbindir}/coverage run --rcfile={toxinidir}/.coveragerc -m unittest discover -s tests - {envbindir}/coverage report --rcfile={toxinidir}/.coveragerc --show-missing - {envbindir}/coverage html --directory={envtmpdir}/htmlcov --rcfile={toxinidir}/.coveragerc {posargs} -deps = - coverage - xmltodict - -[testenv:coverage] -setenv = - COVERAGE_DEBUG_FILE={envtmpdir}/coverage-debug - COVERAGE_FILE={envtmpdir}/coverage-data -commands = - {envbindir}/python -m pip install '{toxinidir}[format]' - {envbindir}/coverage run --rcfile={toxinidir}/.coveragerc {envbindir}/trial jsonschema - {envbindir}/coverage report --rcfile={toxinidir}/.coveragerc --show-missing - {envbindir}/coverage html --directory={envtmpdir}/htmlcov --rcfile={toxinidir}/.coveragerc {posargs}