From a1b5e3f7b0c8e7beaefe69d30e42720925378cb5 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sat, 5 Nov 2016 09:41:16 -0400 Subject: [PATCH] documentation update v1.4.4 --- analyzers/archive-analyzer.html | 26 +- analyzers/assembly-analyzer.html | 26 +- analyzers/autoconf.html | 26 +- analyzers/central-analyzer.html | 26 +- analyzers/cmake.html | 26 +- analyzers/cocoapods.html | 272 + analyzers/composer-lock.html | 12 +- analyzers/index.html | 50 +- analyzers/jar-analyzer.html | 26 +- analyzers/nexus-analyzer.html | 26 +- analyzers/nodejs.html | 26 +- analyzers/nuspec-analyzer.html | 26 +- analyzers/openssl.html | 26 +- analyzers/python.html | 26 +- analyzers/ruby-gemspec.html | 26 +- analyzers/swift.html | 272 + current.txt | 2 +- data/cachenvd.html | 19 +- data/database.html | 21 +- data/index.html | 22 +- data/mirrornvd.html | 19 +- data/proxy.html | 19 +- data/tlsfailure.html | 173 + data/upgrade.html | 12 +- dependency-analysis.html | 12 +- .../apidocs/allclasses-frame.html | 6 +- .../apidocs/allclasses-noframe.html | 6 +- .../apidocs/constant-values.html | 8 +- .../apidocs/deprecated-list.html | 8 +- dependency-check-ant/apidocs/help-doc.html | 8 +- dependency-check-ant/apidocs/index-all.html | 19 +- dependency-check-ant/apidocs/index.html | 4 +- .../ant/logging/AntLoggerAdapter.html | 11 +- .../ant/logging/AntLoggerFactory.html | 8 +- .../logging/class-use/AntLoggerAdapter.html | 8 +- .../logging/class-use/AntLoggerFactory.html | 8 +- .../ant/logging/package-frame.html | 6 +- .../ant/logging/package-summary.html | 11 +- .../ant/logging/package-tree.html | 8 +- .../ant/logging/package-use.html | 8 +- .../taskdefs/Check.ReportFormats.html | 8 +- .../owasp/dependencycheck/taskdefs/Check.html | 162 +- .../owasp/dependencycheck/taskdefs/Purge.html | 8 +- .../dependencycheck/taskdefs/Update.html | 8 +- .../class-use/Check.ReportFormats.html | 8 +- .../taskdefs/class-use/Check.html | 8 +- .../taskdefs/class-use/Purge.html | 8 +- .../taskdefs/class-use/Update.html | 8 +- .../taskdefs/package-frame.html | 6 +- .../taskdefs/package-summary.html | 8 +- .../taskdefs/package-tree.html | 8 +- .../dependencycheck/taskdefs/package-use.html | 8 +- .../org/slf4j/impl/StaticLoggerBinder.html | 8 +- .../impl/class-use/StaticLoggerBinder.html | 8 +- .../apidocs/org/slf4j/impl/package-frame.html | 6 +- .../org/slf4j/impl/package-summary.html | 8 +- .../apidocs/org/slf4j/impl/package-tree.html | 8 +- .../apidocs/org/slf4j/impl/package-use.html | 8 +- .../apidocs/overview-frame.html | 6 +- .../apidocs/overview-summary.html | 10 +- .../apidocs/overview-tree.html | 8 +- .../apidocs/serialized-form.html | 24 +- dependency-check-ant/checkstyle.html | 12 +- ...org.owasp.dependencycheck.ant.logging.html | 2 +- ...es-org.owasp.dependencycheck.taskdefs.html | 2 +- .../cobertura/frame-sourcefiles.html | 4 +- ...org.owasp.dependencycheck.ant.logging.html | 6 +- ...ry-org.owasp.dependencycheck.taskdefs.html | 8 +- .../frame-summary-org.slf4j.impl.html | 2 +- .../cobertura/frame-summary.html | 8 +- ...ncycheck.ant.logging.AntLoggerAdapter.html | 678 +- ...ncycheck.ant.logging.AntLoggerFactory.html | 4 +- ....owasp.dependencycheck.taskdefs.Check.html | 1302 +- ....owasp.dependencycheck.taskdefs.Purge.html | 2 +- ...owasp.dependencycheck.taskdefs.Update.html | 2 +- .../org.slf4j.impl.StaticLoggerBinder.html | 6 +- dependency-check-ant/config-purge.html | 12 +- dependency-check-ant/config-update.html | 10 +- dependency-check-ant/configuration.html | 29 +- dependency-check-ant/dependency-analysis.html | 16 +- .../dependency-updates-report.html | 77 +- dependency-check-ant/findbugs.html | 12 +- dependency-check-ant/index.html | 12 +- dependency-check-ant/integration.html | 10 +- dependency-check-ant/issue-tracking.html | 10 +- dependency-check-ant/license.html | 10 +- dependency-check-ant/mail-lists.html | 10 +- .../plugin-updates-report.html | 14 +- dependency-check-ant/project-info.html | 10 +- dependency-check-ant/project-reports.html | 10 +- dependency-check-ant/project-summary.html | 12 +- dependency-check-ant/source-repository.html | 10 +- dependency-check-ant/surefire-report.html | 24 +- dependency-check-ant/taglist.html | 10 +- dependency-check-ant/team-list.html | 10 +- dependency-check-ant/xref-test/index.html | 2 +- .../taskdefs/package-frame.html | 2 +- .../taskdefs/package-summary.html | 2 +- .../xref-test/overview-frame.html | 2 +- .../xref-test/overview-summary.html | 4 +- dependency-check-ant/xref/index.html | 2 +- .../ant/logging/AntLoggerAdapter.html | 473 +- .../ant/logging/package-frame.html | 2 +- .../ant/logging/package-summary.html | 2 +- .../owasp/dependencycheck/taskdefs/Check.html | 1089 +- .../taskdefs/package-frame.html | 2 +- .../taskdefs/package-summary.html | 2 +- .../xref/org/slf4j/impl/package-frame.html | 2 +- .../xref/org/slf4j/impl/package-summary.html | 2 +- dependency-check-ant/xref/overview-frame.html | 2 +- .../xref/overview-summary.html | 4 +- .../apidocs/allclasses-frame.html | 6 +- .../apidocs/allclasses-noframe.html | 6 +- .../apidocs/constant-values.html | 65 +- .../apidocs/deprecated-list.html | 8 +- dependency-check-cli/apidocs/help-doc.html | 8 +- dependency-check-cli/apidocs/index-all.html | 21 +- dependency-check-cli/apidocs/index.html | 4 +- .../org/owasp/dependencycheck/App.html | 8 +- .../dependencycheck/CliParser.ARGUMENT.html | 88 +- .../org/owasp/dependencycheck/CliParser.html | 114 +- .../InvalidScanPathException.html | 8 +- .../owasp/dependencycheck/class-use/App.html | 8 +- .../class-use/CliParser.ARGUMENT.html | 8 +- .../dependencycheck/class-use/CliParser.html | 8 +- .../class-use/InvalidScanPathException.html | 8 +- .../owasp/dependencycheck/package-frame.html | 6 +- .../dependencycheck/package-summary.html | 8 +- .../owasp/dependencycheck/package-tree.html | 8 +- .../owasp/dependencycheck/package-use.html | 8 +- .../apidocs/overview-tree.html | 8 +- .../apidocs/serialized-form.html | 8 +- dependency-check-cli/arguments.html | 10 +- dependency-check-cli/checkstyle.html | 12 +- ...ame-summary-org.owasp.dependencycheck.html | 10 +- .../cobertura/frame-summary.html | 6 +- .../org.owasp.dependencycheck.App.html | 1176 +- .../org.owasp.dependencycheck.CliParser.html | 2829 +- ...endencycheck.InvalidScanPathException.html | 2 +- dependency-check-cli/dependency-analysis.html | 14 +- .../dependency-updates-report.html | 77 +- dependency-check-cli/findbugs.html | 10 +- dependency-check-cli/index.html | 16 +- dependency-check-cli/integration.html | 10 +- dependency-check-cli/issue-tracking.html | 10 +- dependency-check-cli/license.html | 10 +- dependency-check-cli/mail-lists.html | 10 +- .../plugin-updates-report.html | 14 +- dependency-check-cli/pmd.html | 48 +- dependency-check-cli/project-info.html | 10 +- dependency-check-cli/project-reports.html | 10 +- dependency-check-cli/project-summary.html | 12 +- dependency-check-cli/source-repository.html | 10 +- dependency-check-cli/surefire-report.html | 28 +- dependency-check-cli/taglist.html | 10 +- dependency-check-cli/team-list.html | 10 +- dependency-check-cli/xref-test/index.html | 2 +- .../owasp/dependencycheck/package-frame.html | 2 +- .../dependencycheck/package-summary.html | 2 +- .../xref-test/overview-frame.html | 2 +- .../xref-test/overview-summary.html | 4 +- dependency-check-cli/xref/index.html | 2 +- .../xref/org/owasp/dependencycheck/App.html | 1007 +- .../org/owasp/dependencycheck/CliParser.html | 2211 +- .../owasp/dependencycheck/package-frame.html | 2 +- .../dependencycheck/package-summary.html | 2 +- dependency-check-cli/xref/overview-frame.html | 2 +- .../xref/overview-summary.html | 4 +- .../apidocs/allclasses-frame.html | 6 +- .../apidocs/allclasses-noframe.html | 6 +- .../apidocs/constant-values.html | 8 +- .../apidocs/deprecated-list.html | 8 +- dependency-check-core/apidocs/help-doc.html | 8 +- dependency-check-core/apidocs/index-all.html | 85 +- dependency-check-core/apidocs/index.html | 4 +- .../org/owasp/dependencycheck/Engine.html | 285 +- .../agent/DependencyCheckScanAgent.html | 8 +- .../class-use/DependencyCheckScanAgent.html | 8 +- .../dependencycheck/agent/package-frame.html | 6 +- .../agent/package-summary.html | 8 +- .../dependencycheck/agent/package-tree.html | 8 +- .../dependencycheck/agent/package-use.html | 8 +- .../analyzer/AbstractAnalyzer.html | 36 +- .../analyzer/AbstractFileTypeAnalyzer.html | 12 +- .../analyzer/AbstractSuppressionAnalyzer.html | 10 +- .../analyzer/AnalysisPhase.html | 8 +- .../dependencycheck/analyzer/Analyzer.html | 33 +- .../analyzer/AnalyzerService.html | 8 +- .../analyzer/ArchiveAnalyzer.html | 39 +- .../analyzer/AssemblyAnalyzer.html | 22 +- .../analyzer/AutoconfAnalyzer.html | 12 +- .../analyzer/CMakeAnalyzer.html | 19 +- .../dependencycheck/analyzer/CPEAnalyzer.html | 33 +- .../analyzer/CentralAnalyzer.html | 12 +- .../analyzer/CocoaPodsAnalyzer.html | 12 +- .../analyzer/ComposerLockAnalyzer.html | 12 +- .../analyzer/CpeSuppressionAnalyzer.html | 10 +- .../analyzer/DependencyBundlingAnalyzer.html | 76 +- .../analyzer/Experimental.html | 8 +- .../analyzer/FalsePositiveAnalyzer.html | 10 +- .../analyzer/FileNameAnalyzer.html | 26 +- .../analyzer/FileTypeAnalyzer.html | 10 +- .../analyzer/HintAnalyzer.html | 26 +- .../JarAnalyzer.ClassNameInformation.html | 8 +- .../dependencycheck/analyzer/JarAnalyzer.html | 22 +- .../analyzer/NexusAnalyzer.html | 40 +- .../analyzer/NodePackageAnalyzer.html | 12 +- .../analyzer/NuspecAnalyzer.html | 12 +- .../analyzer/NvdCveAnalyzer.html | 33 +- .../analyzer/OpenSSLAnalyzer.html | 12 +- .../analyzer/PythonDistributionAnalyzer.html | 22 +- .../analyzer/PythonPackageAnalyzer.html | 12 +- .../analyzer/RubyBundleAuditAnalyzer.html | 12 +- .../analyzer/RubyBundlerAnalyzer.html | 12 +- .../analyzer/RubyGemspecAnalyzer.html | 12 +- .../analyzer/SwiftPackageManagerAnalyzer.html | 12 +- .../VulnerabilitySuppressionAnalyzer.html | 10 +- .../analyzer/class-use/AbstractAnalyzer.html | 38 +- .../class-use/AbstractFileTypeAnalyzer.html | 8 +- .../AbstractSuppressionAnalyzer.html | 8 +- .../analyzer/class-use/AnalysisPhase.html | 8 +- .../analyzer/class-use/Analyzer.html | 8 +- .../analyzer/class-use/AnalyzerService.html | 8 +- .../analyzer/class-use/ArchiveAnalyzer.html | 8 +- .../analyzer/class-use/AssemblyAnalyzer.html | 8 +- .../analyzer/class-use/AutoconfAnalyzer.html | 8 +- .../analyzer/class-use/CMakeAnalyzer.html | 8 +- .../analyzer/class-use/CPEAnalyzer.html | 8 +- .../analyzer/class-use/CentralAnalyzer.html | 8 +- .../analyzer/class-use/CocoaPodsAnalyzer.html | 8 +- .../class-use/ComposerLockAnalyzer.html | 8 +- .../class-use/CpeSuppressionAnalyzer.html | 8 +- .../class-use/DependencyBundlingAnalyzer.html | 8 +- .../analyzer/class-use/Experimental.html | 8 +- .../class-use/FalsePositiveAnalyzer.html | 8 +- .../analyzer/class-use/FileNameAnalyzer.html | 8 +- .../analyzer/class-use/FileTypeAnalyzer.html | 23 +- .../analyzer/class-use/HintAnalyzer.html | 8 +- .../JarAnalyzer.ClassNameInformation.html | 8 +- .../analyzer/class-use/JarAnalyzer.html | 8 +- .../analyzer/class-use/NexusAnalyzer.html | 8 +- .../class-use/NodePackageAnalyzer.html | 8 +- .../analyzer/class-use/NuspecAnalyzer.html | 8 +- .../analyzer/class-use/NvdCveAnalyzer.html | 8 +- .../analyzer/class-use/OpenSSLAnalyzer.html | 8 +- .../class-use/PythonDistributionAnalyzer.html | 8 +- .../class-use/PythonPackageAnalyzer.html | 8 +- .../class-use/RubyBundleAuditAnalyzer.html | 8 +- .../class-use/RubyBundlerAnalyzer.html | 8 +- .../class-use/RubyGemspecAnalyzer.html | 8 +- .../SwiftPackageManagerAnalyzer.html | 8 +- .../VulnerabilitySuppressionAnalyzer.html | 8 +- .../analyzer/exception/AnalysisException.html | 8 +- .../exception/ArchiveExtractionException.html | 8 +- .../class-use/AnalysisException.html | 8 +- .../class-use/ArchiveExtractionException.html | 8 +- .../analyzer/exception/package-frame.html | 6 +- .../analyzer/exception/package-summary.html | 8 +- .../analyzer/exception/package-tree.html | 8 +- .../analyzer/exception/package-use.html | 8 +- .../analyzer/package-frame.html | 6 +- .../analyzer/package-summary.html | 8 +- .../analyzer/package-tree.html | 18 +- .../dependencycheck/analyzer/package-use.html | 8 +- .../dependencycheck/class-use/Engine.html | 8 +- .../data/central/CentralSearch.html | 8 +- .../data/central/class-use/CentralSearch.html | 8 +- .../data/central/package-frame.html | 6 +- .../data/central/package-summary.html | 8 +- .../data/central/package-tree.html | 8 +- .../data/central/package-use.html | 8 +- .../data/composer/ComposerDependency.html | 8 +- .../data/composer/ComposerException.html | 8 +- .../data/composer/ComposerLockParser.html | 8 +- .../class-use/ComposerDependency.html | 8 +- .../composer/class-use/ComposerException.html | 8 +- .../class-use/ComposerLockParser.html | 8 +- .../data/composer/package-frame.html | 6 +- .../data/composer/package-summary.html | 8 +- .../data/composer/package-tree.html | 8 +- .../data/composer/package-use.html | 8 +- .../data/cpe/CpeMemoryIndex.html | 8 +- .../dependencycheck/data/cpe/Fields.html | 8 +- .../dependencycheck/data/cpe/IndexEntry.html | 8 +- .../data/cpe/IndexException.html | 8 +- .../data/cpe/class-use/CpeMemoryIndex.html | 8 +- .../data/cpe/class-use/Fields.html | 8 +- .../data/cpe/class-use/IndexEntry.html | 8 +- .../data/cpe/class-use/IndexException.html | 8 +- .../data/cpe/package-frame.html | 6 +- .../data/cpe/package-summary.html | 8 +- .../data/cpe/package-tree.html | 8 +- .../dependencycheck/data/cpe/package-use.html | 8 +- .../owasp/dependencycheck/data/cwe/CweDB.html | 8 +- .../dependencycheck/data/cwe/CweHandler.html | 8 +- .../data/cwe/class-use/CweDB.html | 8 +- .../data/cwe/class-use/CweHandler.html | 8 +- .../data/cwe/package-frame.html | 6 +- .../data/cwe/package-summary.html | 8 +- .../data/cwe/package-tree.html | 8 +- .../dependencycheck/data/cwe/package-use.html | 8 +- .../data/lucene/AbstractTokenizingFilter.html | 8 +- .../data/lucene/AlphaNumericTokenizer.html | 8 +- .../data/lucene/DependencySimilarity.html | 8 +- .../data/lucene/FieldAnalyzer.html | 8 +- .../data/lucene/LuceneUtils.html | 8 +- .../data/lucene/SearchFieldAnalyzer.html | 8 +- .../lucene/TokenPairConcatenatingFilter.html | 8 +- .../data/lucene/UrlTokenizingFilter.html | 8 +- .../class-use/AbstractTokenizingFilter.html | 8 +- .../class-use/AlphaNumericTokenizer.html | 8 +- .../class-use/DependencySimilarity.html | 8 +- .../data/lucene/class-use/FieldAnalyzer.html | 8 +- .../data/lucene/class-use/LuceneUtils.html | 8 +- .../lucene/class-use/SearchFieldAnalyzer.html | 8 +- .../TokenPairConcatenatingFilter.html | 8 +- .../lucene/class-use/UrlTokenizingFilter.html | 8 +- .../data/lucene/package-frame.html | 6 +- .../data/lucene/package-summary.html | 8 +- .../data/lucene/package-tree.html | 8 +- .../data/lucene/package-use.html | 8 +- .../data/nexus/MavenArtifact.html | 8 +- .../data/nexus/NexusSearch.html | 33 +- .../data/nexus/class-use/MavenArtifact.html | 8 +- .../data/nexus/class-use/NexusSearch.html | 8 +- .../data/nexus/package-frame.html | 6 +- .../data/nexus/package-summary.html | 8 +- .../data/nexus/package-tree.html | 8 +- .../data/nexus/package-use.html | 8 +- .../data/nuget/NugetPackage.html | 8 +- .../data/nuget/NuspecParseException.html | 8 +- .../data/nuget/NuspecParser.html | 8 +- .../data/nuget/XPathNuspecParser.html | 8 +- .../data/nuget/class-use/NugetPackage.html | 8 +- .../nuget/class-use/NuspecParseException.html | 8 +- .../data/nuget/class-use/NuspecParser.html | 8 +- .../nuget/class-use/XPathNuspecParser.html | 8 +- .../data/nuget/package-frame.html | 6 +- .../data/nuget/package-summary.html | 8 +- .../data/nuget/package-tree.html | 8 +- .../data/nuget/package-use.html | 8 +- .../data/nvdcve/ConnectionFactory.html | 8 +- .../data/nvdcve/CorruptDatabaseException.html | 8 +- .../dependencycheck/data/nvdcve/CveDB.html | 8 +- .../data/nvdcve/DatabaseException.html | 8 +- .../data/nvdcve/DatabaseProperties.html | 8 +- .../data/nvdcve/DriverLoadException.html | 8 +- .../data/nvdcve/DriverLoader.html | 8 +- .../nvdcve/class-use/ConnectionFactory.html | 8 +- .../class-use/CorruptDatabaseException.html | 8 +- .../data/nvdcve/class-use/CveDB.html | 8 +- .../nvdcve/class-use/DatabaseException.html | 8 +- .../nvdcve/class-use/DatabaseProperties.html | 8 +- .../nvdcve/class-use/DriverLoadException.html | 8 +- .../data/nvdcve/class-use/DriverLoader.html | 8 +- .../data/nvdcve/package-frame.html | 6 +- .../data/nvdcve/package-summary.html | 8 +- .../data/nvdcve/package-tree.html | 8 +- .../data/nvdcve/package-use.html | 8 +- .../data/update/BaseUpdater.html | 8 +- .../data/update/CachedWebDataSource.html | 8 +- .../data/update/CpeUpdater.html | 19 +- .../data/update/EngineVersionCheck.html | 8 +- .../data/update/NvdCveUpdater.html | 8 +- .../data/update/UpdateService.html | 8 +- .../data/update/class-use/BaseUpdater.html | 11 +- .../update/class-use/CachedWebDataSource.html | 11 +- .../data/update/class-use/CpeUpdater.html | 8 +- .../update/class-use/EngineVersionCheck.html | 8 +- .../data/update/class-use/NvdCveUpdater.html | 8 +- .../data/update/class-use/UpdateService.html | 8 +- .../data/update/cpe/CPEHandler.Element.html | 8 +- .../data/update/cpe/CPEHandler.html | 8 +- .../dependencycheck/data/update/cpe/Cpe.html | 8 +- .../cpe/class-use/CPEHandler.Element.html | 8 +- .../data/update/cpe/class-use/CPEHandler.html | 8 +- .../data/update/cpe/class-use/Cpe.html | 8 +- .../data/update/cpe/package-frame.html | 6 +- .../data/update/cpe/package-summary.html | 8 +- .../data/update/cpe/package-tree.html | 8 +- .../data/update/cpe/package-use.html | 8 +- .../exception/InvalidDataException.html | 8 +- .../update/exception/UpdateException.html | 8 +- .../class-use/InvalidDataException.html | 8 +- .../exception/class-use/UpdateException.html | 8 +- .../data/update/exception/package-frame.html | 6 +- .../update/exception/package-summary.html | 8 +- .../data/update/exception/package-tree.html | 8 +- .../data/update/exception/package-use.html | 8 +- .../data/update/nvd/DownloadTask.html | 8 +- .../update/nvd/NvdCve12Handler.Element.html | 8 +- .../data/update/nvd/NvdCve12Handler.html | 8 +- .../update/nvd/NvdCve20Handler.Element.html | 8 +- .../data/update/nvd/NvdCve20Handler.html | 8 +- .../data/update/nvd/NvdCveInfo.html | 8 +- .../data/update/nvd/ProcessTask.html | 29 +- .../data/update/nvd/UpdateableNvdCve.html | 8 +- .../update/nvd/class-use/DownloadTask.html | 8 +- .../class-use/NvdCve12Handler.Element.html | 8 +- .../update/nvd/class-use/NvdCve12Handler.html | 8 +- .../class-use/NvdCve20Handler.Element.html | 8 +- .../update/nvd/class-use/NvdCve20Handler.html | 8 +- .../data/update/nvd/class-use/NvdCveInfo.html | 8 +- .../update/nvd/class-use/ProcessTask.html | 8 +- .../nvd/class-use/UpdateableNvdCve.html | 8 +- .../data/update/nvd/package-frame.html | 6 +- .../data/update/nvd/package-summary.html | 11 +- .../data/update/nvd/package-tree.html | 8 +- .../data/update/nvd/package-use.html | 11 +- .../data/update/package-frame.html | 6 +- .../data/update/package-summary.html | 11 +- .../data/update/package-tree.html | 8 +- .../data/update/package-use.html | 8 +- .../dependency/Confidence.html | 8 +- .../dependency/Dependency.html | 8 +- .../dependencycheck/dependency/Evidence.html | 14 +- .../dependency/EvidenceCollection.html | 8 +- .../dependency/Identifier.html | 8 +- .../dependencycheck/dependency/Reference.html | 8 +- .../dependency/Vulnerability.html | 8 +- .../dependency/VulnerabilityComparator.html | 8 +- .../dependency/VulnerableSoftware.html | 8 +- .../dependency/class-use/Confidence.html | 8 +- .../dependency/class-use/Dependency.html | 61 +- .../dependency/class-use/Evidence.html | 8 +- .../class-use/EvidenceCollection.html | 8 +- .../dependency/class-use/Identifier.html | 8 +- .../dependency/class-use/Reference.html | 8 +- .../dependency/class-use/Vulnerability.html | 8 +- .../class-use/VulnerabilityComparator.html | 8 +- .../class-use/VulnerableSoftware.html | 8 +- .../dependency/package-frame.html | 6 +- .../dependency/package-summary.html | 8 +- .../dependency/package-tree.html | 8 +- .../dependency/package-use.html | 8 +- .../exception/ExceptionCollection.html | 14 +- .../exception/InitializationException.html | 8 +- .../exception/NoDataException.html | 8 +- .../exception/ReportException.html | 8 +- .../exception/ScanAgentException.html | 8 +- .../class-use/ExceptionCollection.html | 8 +- .../class-use/InitializationException.html | 10 +- .../exception/class-use/NoDataException.html | 8 +- .../exception/class-use/ReportException.html | 8 +- .../class-use/ScanAgentException.html | 8 +- .../exception/package-frame.html | 6 +- .../exception/package-summary.html | 8 +- .../exception/package-tree.html | 8 +- .../exception/package-use.html | 8 +- .../owasp/dependencycheck/package-frame.html | 6 +- .../dependencycheck/package-summary.html | 8 +- .../owasp/dependencycheck/package-tree.html | 8 +- .../owasp/dependencycheck/package-use.html | 8 +- .../dependencycheck/reporting/EscapeTool.html | 8 +- .../reporting/ReportGenerator.Format.html | 8 +- .../reporting/ReportGenerator.html | 8 +- .../reporting/VelocityLoggerRedirect.html | 8 +- .../reporting/class-use/EscapeTool.html | 8 +- .../class-use/ReportGenerator.Format.html | 8 +- .../reporting/class-use/ReportGenerator.html | 8 +- .../class-use/VelocityLoggerRedirect.html | 8 +- .../reporting/package-frame.html | 6 +- .../reporting/package-summary.html | 8 +- .../reporting/package-tree.html | 8 +- .../reporting/package-use.html | 8 +- .../owasp/dependencycheck/utils/DBUtils.html | 8 +- .../owasp/dependencycheck/utils/DateUtil.html | 8 +- .../utils/DependencyVersion.html | 35 +- .../utils/DependencyVersionUtil.html | 8 +- .../dependencycheck/utils/ExtractionUtil.html | 8 +- .../utils/FileFilterBuilder.html | 8 +- .../owasp/dependencycheck/utils/Filter.html | 8 +- .../org/owasp/dependencycheck/utils/Pair.html | 8 +- .../dependencycheck/utils/UrlStringUtils.html | 8 +- .../utils/class-use/DBUtils.html | 8 +- .../utils/class-use/DateUtil.html | 8 +- .../utils/class-use/DependencyVersion.html | 8 +- .../class-use/DependencyVersionUtil.html | 8 +- .../utils/class-use/ExtractionUtil.html | 8 +- .../utils/class-use/FileFilterBuilder.html | 8 +- .../utils/class-use/Filter.html | 8 +- .../dependencycheck/utils/class-use/Pair.html | 8 +- .../utils/class-use/UrlStringUtils.html | 8 +- .../dependencycheck/utils/package-frame.html | 6 +- .../utils/package-summary.html | 8 +- .../dependencycheck/utils/package-tree.html | 8 +- .../dependencycheck/utils/package-use.html | 8 +- .../xml/hints/HintErrorHandler.html | 8 +- .../xml/hints/HintHandler.html | 8 +- .../xml/hints/HintParseException.html | 8 +- .../dependencycheck/xml/hints/HintParser.html | 8 +- .../dependencycheck/xml/hints/HintRule.html | 8 +- .../dependencycheck/xml/hints/Hints.html | 8 +- .../xml/hints/VendorDuplicatingHintRule.html | 8 +- .../xml/hints/class-use/HintErrorHandler.html | 8 +- .../xml/hints/class-use/HintHandler.html | 8 +- .../hints/class-use/HintParseException.html | 8 +- .../xml/hints/class-use/HintParser.html | 8 +- .../xml/hints/class-use/HintRule.html | 8 +- .../xml/hints/class-use/Hints.html | 8 +- .../class-use/VendorDuplicatingHintRule.html | 8 +- .../xml/hints/package-frame.html | 6 +- .../xml/hints/package-summary.html | 8 +- .../xml/hints/package-tree.html | 8 +- .../xml/hints/package-use.html | 8 +- .../dependencycheck/xml/pom/License.html | 8 +- .../owasp/dependencycheck/xml/pom/Model.html | 8 +- .../dependencycheck/xml/pom/PomHandler.html | 8 +- .../xml/pom/PomParseException.html | 8 +- .../dependencycheck/xml/pom/PomParser.html | 23 +- .../dependencycheck/xml/pom/PomUtils.html | 8 +- .../xml/pom/class-use/License.html | 8 +- .../xml/pom/class-use/Model.html | 14 +- .../xml/pom/class-use/PomHandler.html | 8 +- .../xml/pom/class-use/PomParseException.html | 14 +- .../xml/pom/class-use/PomParser.html | 8 +- .../xml/pom/class-use/PomUtils.html | 8 +- .../xml/pom/package-frame.html | 6 +- .../xml/pom/package-summary.html | 8 +- .../dependencycheck/xml/pom/package-tree.html | 8 +- .../dependencycheck/xml/pom/package-use.html | 8 +- .../xml/suppression/PropertyType.html | 8 +- .../suppression/SuppressionErrorHandler.html | 8 +- .../xml/suppression/SuppressionHandler.html | 8 +- .../SuppressionParseException.html | 8 +- .../xml/suppression/SuppressionParser.html | 8 +- .../xml/suppression/SuppressionRule.html | 8 +- .../suppression/class-use/PropertyType.html | 8 +- .../class-use/SuppressionErrorHandler.html | 8 +- .../class-use/SuppressionHandler.html | 8 +- .../class-use/SuppressionParseException.html | 8 +- .../class-use/SuppressionParser.html | 8 +- .../class-use/SuppressionRule.html | 8 +- .../xml/suppression/package-frame.html | 6 +- .../xml/suppression/package-summary.html | 8 +- .../xml/suppression/package-tree.html | 8 +- .../xml/suppression/package-use.html | 8 +- .../apidocs/overview-frame.html | 6 +- .../apidocs/overview-summary.html | 10 +- .../apidocs/overview-tree.html | 18 +- .../apidocs/serialized-form.html | 8 +- dependency-check-core/checkstyle.html | 92 +- dependency-check-core/checkstyle.rss | 36 +- ...es-org.owasp.dependencycheck.analyzer.html | 22 +- ...rg.owasp.dependencycheck.data.central.html | 2 +- ...-org.owasp.dependencycheck.dependency.html | 2 +- ...s-org.owasp.dependencycheck.exception.html | 2 +- ...sourcefiles-org.owasp.dependencycheck.html | 5 +- ...files-org.owasp.dependencycheck.utils.html | 2 +- ...s-org.owasp.dependencycheck.xml.hints.html | 2 +- ...les-org.owasp.dependencycheck.xml.pom.html | 2 +- ...owasp.dependencycheck.xml.suppression.html | 4 +- .../cobertura/frame-sourcefiles.html | 43 +- ...mmary-org.owasp.dependencycheck.agent.html | 2 +- ...sp.dependencycheck.analyzer.exception.html | 2 +- ...ry-org.owasp.dependencycheck.analyzer.html | 36 +- ...rg.owasp.dependencycheck.data.central.html | 6 +- ...g.owasp.dependencycheck.data.composer.html | 2 +- ...ry-org.owasp.dependencycheck.data.cpe.html | 2 +- ...ry-org.owasp.dependencycheck.data.cwe.html | 2 +- ...org.owasp.dependencycheck.data.lucene.html | 2 +- ...-org.owasp.dependencycheck.data.nexus.html | 6 +- ...-org.owasp.dependencycheck.data.nuget.html | 6 +- ...org.owasp.dependencycheck.data.nvdcve.html | 2 +- ...owasp.dependencycheck.data.update.cpe.html | 2 +- ...dependencycheck.data.update.exception.html | 2 +- ...org.owasp.dependencycheck.data.update.html | 8 +- ...owasp.dependencycheck.data.update.nvd.html | 6 +- ...-org.owasp.dependencycheck.dependency.html | 6 +- ...y-org.owasp.dependencycheck.exception.html | 6 +- ...ame-summary-org.owasp.dependencycheck.html | 32 +- ...y-org.owasp.dependencycheck.reporting.html | 2 +- ...mmary-org.owasp.dependencycheck.utils.html | 6 +- ...y-org.owasp.dependencycheck.xml.hints.html | 6 +- ...ary-org.owasp.dependencycheck.xml.pom.html | 6 +- ...owasp.dependencycheck.xml.suppression.html | 8 +- .../cobertura/frame-summary.html | 30 +- ...rg.owasp.dependencycheck.AnalysisTask.html | 235 + .../org.owasp.dependencycheck.Engine.html | 1825 +- ...ycheck.agent.DependencyCheckScanAgent.html | 2 +- ...ndencycheck.analyzer.AbstractAnalyzer.html | 23 +- ...eck.analyzer.AbstractFileTypeAnalyzer.html | 52 +- ....analyzer.AbstractSuppressionAnalyzer.html | 98 +- ...ependencycheck.analyzer.AnalysisPhase.html | 4 +- ...asp.dependencycheck.analyzer.Analyzer.html | 18 +- ...endencycheck.analyzer.AnalyzerService.html | 32 +- ...endencycheck.analyzer.ArchiveAnalyzer.html | 1515 +- ...ndencycheck.analyzer.AssemblyAnalyzer.html | 607 +- ...ndencycheck.analyzer.AutoconfAnalyzer.html | 543 +- ...ependencycheck.analyzer.CMakeAnalyzer.html | 416 +- ....dependencycheck.analyzer.CPEAnalyzer.html | 2352 +- ...endencycheck.analyzer.CentralAnalyzer.html | 30 +- ...dencycheck.analyzer.CocoaPodsAnalyzer.html | 12 +- ...cycheck.analyzer.ComposerLockAnalyzer.html | 242 +- ...check.analyzer.CpeSuppressionAnalyzer.html | 12 +- ...k.analyzer.DependencyBundlingAnalyzer.html | 1332 +- ...dependencycheck.analyzer.Experimental.html | 2 +- ...ycheck.analyzer.FalsePositiveAnalyzer.html | 291 +- ...ndencycheck.analyzer.FileNameAnalyzer.html | 8 +- ...ndencycheck.analyzer.FileTypeAnalyzer.html | 2 +- ...dependencycheck.analyzer.HintAnalyzer.html | 22 +- ....dependencycheck.analyzer.JarAnalyzer.html | 2155 +- ...ependencycheck.analyzer.NexusAnalyzer.html | 490 +- ...ncycheck.analyzer.NodePackageAnalyzer.html | 12 +- ...pendencycheck.analyzer.NuspecAnalyzer.html | 12 +- ...pendencycheck.analyzer.NvdCveAnalyzer.html | 30 +- ...endencycheck.analyzer.OpenSSLAnalyzer.html | 12 +- ...k.analyzer.PythonDistributionAnalyzer.html | 932 +- ...ycheck.analyzer.PythonPackageAnalyzer.html | 621 +- ...heck.analyzer.RubyBundleAuditAnalyzer.html | 18 +- ...ncycheck.analyzer.RubyBundlerAnalyzer.html | 12 +- ...ncycheck.analyzer.RubyGemspecAnalyzer.html | 12 +- ....analyzer.SwiftPackageManagerAnalyzer.html | 12 +- ...yzer.VulnerabilitySuppressionAnalyzer.html | 12 +- ....analyzer.exception.AnalysisException.html | 2 +- ....exception.ArchiveExtractionException.html | 2 +- ...dencycheck.data.central.CentralSearch.html | 130 +- ...heck.data.composer.ComposerDependency.html | 2 +- ...check.data.composer.ComposerException.html | 2 +- ...heck.data.composer.ComposerLockParser.html | 2 +- ...pendencycheck.data.cpe.CpeMemoryIndex.html | 26 +- ...owasp.dependencycheck.data.cpe.Fields.html | 2 +- ...p.dependencycheck.data.cpe.IndexEntry.html | 34 +- ...pendencycheck.data.cpe.IndexException.html | 2 +- ....owasp.dependencycheck.data.cwe.CweDB.html | 2 +- ...p.dependencycheck.data.cwe.CweHandler.html | 2 +- ....data.lucene.AbstractTokenizingFilter.html | 26 +- ...eck.data.lucene.AlphaNumericTokenizer.html | 8 +- ...heck.data.lucene.DependencySimilarity.html | 2 +- ...ndencycheck.data.lucene.FieldAnalyzer.html | 2 +- ...pendencycheck.data.lucene.LuceneUtils.html | 14 +- ...check.data.lucene.SearchFieldAnalyzer.html | 26 +- ...a.lucene.TokenPairConcatenatingFilter.html | 50 +- ...check.data.lucene.UrlTokenizingFilter.html | 20 +- ...endencycheck.data.nexus.MavenArtifact.html | 2 +- ...ependencycheck.data.nexus.NexusSearch.html | 372 +- ...pendencycheck.data.nuget.NugetPackage.html | 2 +- ...check.data.nuget.NuspecParseException.html | 2 +- ...pendencycheck.data.nuget.NuspecParser.html | 2 +- ...ncycheck.data.nuget.XPathNuspecParser.html | 128 +- ...cycheck.data.nvdcve.ConnectionFactory.html | 6 +- ....data.nvdcve.CorruptDatabaseException.html | 2 +- ...asp.dependencycheck.data.nvdcve.CveDB.html | 206 +- ...cycheck.data.nvdcve.DatabaseException.html | 2 +- ...ycheck.data.nvdcve.DatabaseProperties.html | 2 +- ...check.data.nvdcve.DriverLoadException.html | 2 +- ...endencycheck.data.nvdcve.DriverLoader.html | 2 +- ...ependencycheck.data.nvdcve.DriverShim.html | 2 +- ...pendencycheck.data.update.BaseUpdater.html | 2 +- ...check.data.update.CachedWebDataSource.html | 2 +- ...ependencycheck.data.update.CpeUpdater.html | 377 +- ...ycheck.data.update.EngineVersionCheck.html | 4 +- ...ndencycheck.data.update.NvdCveUpdater.html | 2 +- ...ndencycheck.data.update.UpdateService.html | 2 +- ...dencycheck.data.update.cpe.CPEHandler.html | 2 +- ...p.dependencycheck.data.update.cpe.Cpe.html | 2 +- ...update.exception.InvalidDataException.html | 2 +- ...data.update.exception.UpdateException.html | 2 +- ...ncycheck.data.update.nvd.DownloadTask.html | 6 +- ...check.data.update.nvd.NvdCve12Handler.html | 2 +- ...check.data.update.nvd.NvdCve20Handler.html | 2 +- ...dencycheck.data.update.nvd.NvdCveInfo.html | 2 +- ...encycheck.data.update.nvd.ProcessTask.html | 415 +- ...heck.data.update.nvd.UpdateableNvdCve.html | 2 +- ...dependencycheck.dependency.Confidence.html | 4 +- ...dependencycheck.dependency.Dependency.html | 118 +- ...p.dependencycheck.dependency.Evidence.html | 454 +- ...cycheck.dependency.EvidenceCollection.html | 82 +- ...dependencycheck.dependency.Identifier.html | 34 +- ....dependencycheck.dependency.Reference.html | 2 +- ...endencycheck.dependency.Vulnerability.html | 10 +- ...ck.dependency.VulnerabilityComparator.html | 4 +- ...cycheck.dependency.VulnerableSoftware.html | 52 +- ...cycheck.exception.ExceptionCollection.html | 24 +- ...eck.exception.InitializationException.html | 6 +- ...ndencycheck.exception.NoDataException.html | 2 +- ...ndencycheck.exception.ReportException.html | 2 +- ...ncycheck.exception.ScanAgentException.html | 2 +- ....dependencycheck.reporting.EscapeTool.html | 2 +- ...ndencycheck.reporting.ReportGenerator.html | 2 +- ...heck.reporting.VelocityLoggerRedirect.html | 2 +- ...g.owasp.dependencycheck.utils.DBUtils.html | 18 +- ....owasp.dependencycheck.utils.DateUtil.html | 2 +- ...pendencycheck.utils.DependencyVersion.html | 644 +- ...encycheck.utils.DependencyVersionUtil.html | 28 +- ....dependencycheck.utils.ExtractionUtil.html | 2 +- ...pendencycheck.utils.FileFilterBuilder.html | 2 +- ...rg.owasp.dependencycheck.utils.Filter.html | 44 +- .../org.owasp.dependencycheck.utils.Pair.html | 26 +- ....dependencycheck.utils.UrlStringUtils.html | 36 +- ...dencycheck.xml.hints.HintErrorHandler.html | 2 +- ...dependencycheck.xml.hints.HintHandler.html | 2 +- ...ncycheck.xml.hints.HintParseException.html | 2 +- ....dependencycheck.xml.hints.HintParser.html | 93 +- ...sp.dependencycheck.xml.hints.HintRule.html | 4 +- ...owasp.dependencycheck.xml.hints.Hints.html | 2 +- ...k.xml.hints.VendorDuplicatingHintRule.html | 2 +- ...owasp.dependencycheck.xml.pom.License.html | 2 +- ...g.owasp.dependencycheck.xml.pom.Model.html | 4 +- ...sp.dependencycheck.xml.pom.PomHandler.html | 2 +- ...ndencycheck.xml.pom.PomParseException.html | 2 +- ...asp.dependencycheck.xml.pom.PomParser.html | 177 +- ...wasp.dependencycheck.xml.pom.PomUtils.html | 2 +- ...ncycheck.xml.suppression.PropertyType.html | 34 +- ...l.suppression.SuppressionErrorHandler.html | 2 +- ...ck.xml.suppression.SuppressionHandler.html | 70 +- ...suppression.SuppressionParseException.html | 16 +- ...eck.xml.suppression.SuppressionParser.html | 239 +- ...check.xml.suppression.SuppressionRule.html | 90 +- dependency-check-core/cpd.html | 132 +- .../dependency-analysis.html | 14 +- .../dependency-updates-report.html | 85 +- dependency-check-core/failsafe-report.html | 104 +- dependency-check-core/findbugs.html | 12 +- dependency-check-core/index.html | 10 +- dependency-check-core/integration.html | 10 +- dependency-check-core/issue-tracking.html | 10 +- dependency-check-core/license.html | 10 +- dependency-check-core/mail-lists.html | 10 +- .../plugin-updates-report.html | 14 +- dependency-check-core/pmd.html | 107 +- dependency-check-core/project-info.html | 10 +- dependency-check-core/project-reports.html | 10 +- dependency-check-core/project-summary.html | 12 +- dependency-check-core/source-repository.html | 10 +- dependency-check-core/surefire-report.html | 338 +- dependency-check-core/taglist.html | 71 +- dependency-check-core/team-list.html | 10 +- .../xref-test/allclasses-frame.html | 6 + dependency-check-core/xref-test/index.html | 2 +- .../dependencycheck/AnalysisTaskTest.html | 113 + .../org/owasp/dependencycheck/EngineTest.html | 109 + .../analyzer/CMakeAnalyzerTest.html | 281 +- .../analyzer/ComposerLockAnalyzerTest.html | 184 +- .../DependencyBundlingAnalyzerTest.html | 224 +- .../analyzer/package-frame.html | 2 +- .../analyzer/package-summary.html | 2 +- .../data/central/package-frame.html | 2 +- .../data/central/package-summary.html | 2 +- .../data/composer/package-frame.html | 2 +- .../data/composer/package-summary.html | 2 +- .../data/cpe/package-frame.html | 2 +- .../data/cpe/package-summary.html | 2 +- .../data/cwe/package-frame.html | 2 +- .../data/cwe/package-summary.html | 2 +- .../data/lucene/package-frame.html | 2 +- .../data/lucene/package-summary.html | 2 +- .../data/nexus/NexusSearchTest.html | 107 +- .../data/nexus/package-frame.html | 2 +- .../data/nexus/package-summary.html | 2 +- .../data/nuget/package-frame.html | 2 +- .../data/nuget/package-summary.html | 2 +- .../data/nvdcve/package-frame.html | 2 +- .../data/nvdcve/package-summary.html | 2 +- .../data/update/nvd/package-frame.html | 2 +- .../data/update/nvd/package-summary.html | 2 +- .../data/update/package-frame.html | 2 +- .../data/update/package-summary.html | 2 +- .../dependency/package-frame.html | 2 +- .../dependency/package-summary.html | 2 +- .../owasp/dependencycheck/package-frame.html | 8 +- .../dependencycheck/package-summary.html | 12 +- .../reporting/package-frame.html | 2 +- .../reporting/package-summary.html | 2 +- .../utils/DependencyVersionTest.html | 199 +- .../dependencycheck/utils/package-frame.html | 2 +- .../utils/package-summary.html | 2 +- .../xml/hints/package-frame.html | 2 +- .../xml/hints/package-summary.html | 2 +- .../xml/pom/package-frame.html | 2 +- .../xml/pom/package-summary.html | 2 +- .../xml/suppression/package-frame.html | 2 +- .../xml/suppression/package-summary.html | 2 +- .../xref-test/overview-frame.html | 2 +- .../xref-test/overview-summary.html | 4 +- .../xref/allclasses-frame.html | 3 + dependency-check-core/xref/index.html | 2 +- .../owasp/dependencycheck/AnalysisTask.html | 132 + .../org/owasp/dependencycheck/Engine.html | 1272 +- .../dependencycheck/agent/package-frame.html | 2 +- .../agent/package-summary.html | 2 +- .../analyzer/AbstractAnalyzer.html | 10 +- .../analyzer/AbstractFileTypeAnalyzer.html | 2 +- .../analyzer/AbstractSuppressionAnalyzer.html | 79 +- .../dependencycheck/analyzer/Analyzer.html | 10 +- .../analyzer/ArchiveAnalyzer.html | 1170 +- .../analyzer/AssemblyAnalyzer.html | 586 +- .../analyzer/AutoconfAnalyzer.html | 496 +- .../analyzer/CMakeAnalyzer.html | 313 +- .../dependencycheck/analyzer/CPEAnalyzer.html | 1587 +- .../analyzer/CentralAnalyzer.html | 2 +- .../analyzer/ComposerLockAnalyzer.html | 195 +- .../analyzer/DependencyBundlingAnalyzer.html | 975 +- .../analyzer/FalsePositiveAnalyzer.html | 118 +- .../analyzer/FileNameAnalyzer.html | 2 +- .../analyzer/HintAnalyzer.html | 4 +- .../dependencycheck/analyzer/JarAnalyzer.html | 1846 +- .../analyzer/NexusAnalyzer.html | 371 +- .../analyzer/NvdCveAnalyzer.html | 2 +- .../analyzer/PythonDistributionAnalyzer.html | 717 +- .../analyzer/PythonPackageAnalyzer.html | 572 +- .../analyzer/RubyBundleAuditAnalyzer.html | 2 +- .../analyzer/exception/package-frame.html | 2 +- .../analyzer/exception/package-summary.html | 2 +- .../analyzer/package-frame.html | 2 +- .../analyzer/package-summary.html | 2 +- .../data/central/CentralSearch.html | 115 +- .../data/central/package-frame.html | 2 +- .../data/central/package-summary.html | 2 +- .../data/composer/package-frame.html | 2 +- .../data/composer/package-summary.html | 2 +- .../data/cpe/package-frame.html | 2 +- .../data/cpe/package-summary.html | 2 +- .../data/cwe/package-frame.html | 2 +- .../data/cwe/package-summary.html | 2 +- .../data/lucene/package-frame.html | 2 +- .../data/lucene/package-summary.html | 2 +- .../data/nexus/NexusSearch.html | 312 +- .../data/nexus/package-frame.html | 2 +- .../data/nexus/package-summary.html | 2 +- .../data/nuget/XPathNuspecParser.html | 90 +- .../data/nuget/package-frame.html | 2 +- .../data/nuget/package-summary.html | 2 +- .../dependencycheck/data/nvdcve/CveDB.html | 30 +- .../data/nvdcve/package-frame.html | 2 +- .../data/nvdcve/package-summary.html | 2 +- .../data/update/CpeUpdater.html | 316 +- .../data/update/EngineVersionCheck.html | 2 +- .../data/update/cpe/package-frame.html | 2 +- .../data/update/cpe/package-summary.html | 2 +- .../data/update/exception/package-frame.html | 2 +- .../update/exception/package-summary.html | 2 +- .../data/update/nvd/ProcessTask.html | 295 +- .../data/update/nvd/package-frame.html | 2 +- .../data/update/nvd/package-summary.html | 2 +- .../data/update/package-frame.html | 2 +- .../data/update/package-summary.html | 2 +- .../dependencycheck/dependency/Evidence.html | 335 +- .../dependency/package-frame.html | 2 +- .../dependency/package-summary.html | 2 +- .../exception/ExceptionCollection.html | 10 +- .../exception/package-frame.html | 2 +- .../exception/package-summary.html | 2 +- .../owasp/dependencycheck/package-frame.html | 5 +- .../dependencycheck/package-summary.html | 7 +- .../reporting/package-frame.html | 2 +- .../reporting/package-summary.html | 2 +- .../utils/DependencyVersion.html | 457 +- .../dependencycheck/utils/package-frame.html | 2 +- .../utils/package-summary.html | 2 +- .../dependencycheck/xml/hints/HintParser.html | 89 +- .../xml/hints/package-frame.html | 2 +- .../xml/hints/package-summary.html | 2 +- .../owasp/dependencycheck/xml/pom/Model.html | 2 +- .../dependencycheck/xml/pom/PomParser.html | 130 +- .../xml/pom/package-frame.html | 2 +- .../xml/pom/package-summary.html | 2 +- .../xml/suppression/SuppressionParser.html | 187 +- .../xml/suppression/package-frame.html | 2 +- .../xml/suppression/package-summary.html | 2 +- .../xref/overview-frame.html | 2 +- .../xref/overview-summary.html | 4 +- .../configuration-purge.html | 12 +- .../configuration-update.html | 12 +- dependency-check-gradle/configuration.html | 23 +- dependency-check-gradle/index.html | 16 +- dependency-check-jenkins/index.html | 12 +- dependency-check-maven/aggregate-mojo.html | 177 +- .../apidocs/allclasses-frame.html | 9 +- .../apidocs/allclasses-noframe.html | 9 +- .../apidocs/constant-values.html | 18 +- .../apidocs/deprecated-list.html | 18 +- dependency-check-maven/apidocs/help-doc.html | 22 +- dependency-check-maven/apidocs/index-all.html | 151 +- dependency-check-maven/apidocs/index.html | 11 +- .../dependencycheck/maven/AggregateMojo.html | 14 +- .../maven/BaseDependencyCheckMojo.html | 14 +- .../dependencycheck/maven/CheckMojo.html | 14 +- .../owasp/dependencycheck/maven/HelpMojo.html | 14 +- .../dependencycheck/maven/MavenEngine.html | 16 +- .../dependencycheck/maven/PurgeMojo.html | 14 +- .../dependencycheck/maven/UpdateMojo.html | 14 +- .../maven/class-use/AggregateMojo.html | 14 +- .../class-use/BaseDependencyCheckMojo.html | 31 +- .../maven/class-use/CheckMojo.html | 14 +- .../maven/class-use/HelpMojo.html | 14 +- .../maven/class-use/MavenEngine.html | 31 +- .../maven/class-use/PurgeMojo.html | 14 +- .../maven/class-use/UpdateMojo.html | 14 +- .../dependencycheck/maven/package-frame.html | 6 +- .../maven/package-summary.html | 18 +- .../dependencycheck/maven/package-tree.html | 22 +- .../dependencycheck/maven/package-use.html | 31 +- .../apidocs/overview-tree.html | 25 +- dependency-check-maven/apidocs/package-list | 2 - dependency-check-maven/check-mojo.html | 177 +- dependency-check-maven/checkstyle.html | 14 +- dependency-check-maven/checkstyle.rss | 72 +- .../cobertura/frame-packages.html | 6 - .../cobertura/frame-sourcefiles.html | 9 - ...mmary-org.owasp.dependencycheck.maven.html | 11 +- .../cobertura/frame-summary.html | 8 +- ...p.dependencycheck.maven.AggregateMojo.html | 8 +- ...cycheck.maven.BaseDependencyCheckMojo.html | 2817 +- ...owasp.dependencycheck.maven.CheckMojo.html | 13 +- ....owasp.dependencycheck.maven.HelpMojo.html | 470 +- ...asp.dependencycheck.maven.MavenEngine.html | 2 +- ...owasp.dependencycheck.maven.PurgeMojo.html | 2 +- ...wasp.dependencycheck.maven.UpdateMojo.html | 6 +- dependency-check-maven/configuration.html | 19 +- .../dependency-analysis.html | 16 +- .../dependency-updates-report.html | 77 +- dependency-check-maven/findbugs.html | 12 +- dependency-check-maven/help-mojo.html | 25 +- dependency-check-maven/index.html | 26 +- dependency-check-maven/integration.html | 10 +- dependency-check-maven/issue-tracking.html | 10 +- dependency-check-maven/license.html | 10 +- dependency-check-maven/mail-lists.html | 10 +- dependency-check-maven/plugin-info.html | 18 +- .../plugin-updates-report.html | 18 +- dependency-check-maven/pmd.html | 12 +- dependency-check-maven/project-info.html | 10 +- dependency-check-maven/project-reports.html | 10 +- dependency-check-maven/project-summary.html | 12 +- dependency-check-maven/purge-mojo.html | 175 +- dependency-check-maven/source-repository.html | 10 +- dependency-check-maven/surefire-report.html | 16 +- dependency-check-maven/taglist.html | 12 +- dependency-check-maven/team-list.html | 10 +- dependency-check-maven/update-only-mojo.html | 175 +- dependency-check-maven/xref-test/index.html | 2 +- .../dependencycheck/maven/package-frame.html | 2 +- .../maven/package-summary.html | 2 +- .../xref-test/overview-frame.html | 2 +- .../xref-test/overview-summary.html | 4 +- .../xref/allclasses-frame.html | 9 - dependency-check-maven/xref/index.html | 2 +- .../dependencycheck/maven/AggregateMojo.html | 6 +- .../maven/BaseDependencyCheckMojo.html | 2084 +- .../dependencycheck/maven/CheckMojo.html | 8 +- .../owasp/dependencycheck/maven/HelpMojo.html | 344 +- .../dependencycheck/maven/UpdateMojo.html | 4 +- .../dependencycheck/maven/package-frame.html | 2 +- .../maven/package-summary.html | 2 +- .../xref/overview-frame.html | 8 +- .../xref/overview-summary.html | 14 +- .../apidocs/allclasses-frame.html | 6 +- .../apidocs/allclasses-noframe.html | 6 +- .../apidocs/constant-values.html | 45 +- .../apidocs/deprecated-list.html | 8 +- dependency-check-utils/apidocs/help-doc.html | 8 +- dependency-check-utils/apidocs/index-all.html | 22 +- dependency-check-utils/apidocs/index.html | 4 +- .../owasp/dependencycheck/utils/Checksum.html | 17 +- .../utils/DownloadFailedException.html | 8 +- .../dependencycheck/utils/Downloader.html | 8 +- .../utils/ExpectedOjectInputStream.html | 8 +- .../utils/ExtractionException.html | 8 +- .../dependencycheck/utils/FileUtils.html | 51 +- .../utils/InvalidSettingException.html | 8 +- .../utils/SSLSocketFactoryEx.html | 8 +- .../dependencycheck/utils/Settings.KEYS.html | 66 +- .../owasp/dependencycheck/utils/Settings.html | 8 +- .../utils/URLConnectionFactory.html | 8 +- .../utils/URLConnectionFailureException.html | 8 +- .../utils/class-use/Checksum.html | 8 +- .../class-use/DownloadFailedException.html | 8 +- .../utils/class-use/Downloader.html | 8 +- .../class-use/ExpectedOjectInputStream.html | 8 +- .../utils/class-use/ExtractionException.html | 8 +- .../utils/class-use/FileUtils.html | 8 +- .../class-use/InvalidSettingException.html | 8 +- .../utils/class-use/SSLSocketFactoryEx.html | 8 +- .../utils/class-use/Settings.KEYS.html | 8 +- .../utils/class-use/Settings.html | 8 +- .../utils/class-use/URLConnectionFactory.html | 8 +- .../URLConnectionFailureException.html | 8 +- .../dependencycheck/utils/package-frame.html | 6 +- .../utils/package-summary.html | 8 +- .../dependencycheck/utils/package-tree.html | 8 +- .../dependencycheck/utils/package-use.html | 8 +- .../apidocs/overview-tree.html | 8 +- .../apidocs/serialized-form.html | 8 +- dependency-check-utils/checkstyle.html | 19 +- ...files-org.owasp.dependencycheck.utils.html | 8 +- .../cobertura/frame-sourcefiles.html | 8 +- ...mmary-org.owasp.dependencycheck.utils.html | 16 +- .../cobertura/frame-summary.html | 6 +- ....owasp.dependencycheck.utils.Checksum.html | 242 +- ...cycheck.utils.DownloadFailedException.html | 2 +- ...wasp.dependencycheck.utils.Downloader.html | 542 +- ...ycheck.utils.ExpectedOjectInputStream.html | 2 +- ...ndencycheck.utils.ExtractionException.html | 2 +- ...owasp.dependencycheck.utils.FileUtils.html | 160 +- ...cycheck.utils.InvalidSettingException.html | 2 +- ...endencycheck.utils.SSLSocketFactoryEx.html | 111 +- ....owasp.dependencycheck.utils.Settings.html | 1566 +- ...dencycheck.utils.URLConnectionFactory.html | 4 +- ...k.utils.URLConnectionFailureException.html | 2 +- .../dependency-analysis.html | 19 +- .../dependency-updates-report.html | 78 +- dependency-check-utils/findbugs.html | 19 +- dependency-check-utils/index.html | 12 +- dependency-check-utils/integration.html | 12 +- dependency-check-utils/issue-tracking.html | 12 +- dependency-check-utils/license.html | 12 +- dependency-check-utils/mail-lists.html | 12 +- .../plugin-updates-report.html | 23 +- dependency-check-utils/pmd.html | 19 +- dependency-check-utils/project-info.html | 12 +- dependency-check-utils/project-reports.html | 24 +- dependency-check-utils/project-summary.html | 14 +- dependency-check-utils/source-repository.html | 12 +- dependency-check-utils/surefire-report.html | 49 +- dependency-check-utils/taglist.html | 21 +- dependency-check-utils/team-list.html | 12 +- dependency-check-utils/xref-test/index.html | 2 +- .../dependencycheck/utils/package-frame.html | 2 +- .../utils/package-summary.html | 2 +- .../xref-test/overview-frame.html | 2 +- .../xref-test/overview-summary.html | 4 +- dependency-check-utils/xref/index.html | 2 +- .../owasp/dependencycheck/utils/Checksum.html | 191 +- .../dependencycheck/utils/Downloader.html | 393 +- .../dependencycheck/utils/FileUtils.html | 112 +- .../utils/SSLSocketFactoryEx.html | 93 +- .../owasp/dependencycheck/utils/Settings.html | 1259 +- .../utils/URLConnectionFactory.html | 2 +- .../dependencycheck/utils/package-frame.html | 2 +- .../utils/package-summary.html | 2 +- .../xref/overview-frame.html | 2 +- .../xref/overview-summary.html | 4 +- dependency-updates-report.html | 71 +- general/SampleReport.html | 42408 ++++++++++++---- general/dependency-check.pdf | Bin 329686 -> 673791 bytes general/dependency-check.pptx | Bin 569997 -> 919099 bytes general/hints.html | 307 + general/internals.html | 19 +- general/scan_iso.html | 19 +- general/suppression.html | 21 +- general/thereport.html | 19 +- index.html | 21 +- integration.html | 12 +- issue-tracking.html | 12 +- license.html | 12 +- mail-lists.html | 12 +- modules.html | 12 +- plugin-updates-report.html | 16 +- project-info.html | 12 +- project-reports.html | 12 +- project-summary.html | 14 +- related.html | 19 +- source-repository.html | 12 +- surefire-report.html | 12 +- team-list.html | 12 +- xref-test/allclasses-frame.html | 6 + xref-test/index.html | 2 +- .../dependencycheck/AnalysisTaskTest.html | 113 + .../org/owasp/dependencycheck/EngineTest.html | 109 + .../analyzer/CMakeAnalyzerTest.html | 281 +- .../analyzer/ComposerLockAnalyzerTest.html | 184 +- .../DependencyBundlingAnalyzerTest.html | 224 +- .../analyzer/package-frame.html | 2 +- .../analyzer/package-summary.html | 2 +- .../data/central/package-frame.html | 2 +- .../data/central/package-summary.html | 2 +- .../data/composer/package-frame.html | 2 +- .../data/composer/package-summary.html | 2 +- .../data/cpe/package-frame.html | 2 +- .../data/cpe/package-summary.html | 2 +- .../data/cwe/package-frame.html | 2 +- .../data/cwe/package-summary.html | 2 +- .../data/lucene/package-frame.html | 2 +- .../data/lucene/package-summary.html | 2 +- .../data/nexus/NexusSearchTest.html | 107 +- .../data/nexus/package-frame.html | 2 +- .../data/nexus/package-summary.html | 2 +- .../data/nuget/package-frame.html | 2 +- .../data/nuget/package-summary.html | 2 +- .../data/nvdcve/package-frame.html | 2 +- .../data/nvdcve/package-summary.html | 2 +- .../data/update/nvd/package-frame.html | 2 +- .../data/update/nvd/package-summary.html | 2 +- .../data/update/package-frame.html | 2 +- .../data/update/package-summary.html | 2 +- .../dependency/package-frame.html | 2 +- .../dependency/package-summary.html | 2 +- .../dependencycheck/maven/package-frame.html | 2 +- .../maven/package-summary.html | 2 +- .../owasp/dependencycheck/package-frame.html | 8 +- .../dependencycheck/package-summary.html | 12 +- .../reporting/package-frame.html | 2 +- .../reporting/package-summary.html | 2 +- .../taskdefs/package-frame.html | 2 +- .../taskdefs/package-summary.html | 2 +- .../utils/DependencyVersionTest.html | 199 +- .../dependencycheck/utils/package-frame.html | 2 +- .../utils/package-summary.html | 2 +- .../xml/hints/package-frame.html | 2 +- .../xml/hints/package-summary.html | 2 +- .../xml/pom/package-frame.html | 2 +- .../xml/pom/package-summary.html | 2 +- .../xml/suppression/package-frame.html | 2 +- .../xml/suppression/package-summary.html | 2 +- xref-test/overview-frame.html | 2 +- xref-test/overview-summary.html | 4 +- xref/allclasses-frame.html | 9 +- xref/index.html | 2 +- .../owasp/dependencycheck/AnalysisTask.html | 132 + xref/org/owasp/dependencycheck/App.html | 1007 +- xref/org/owasp/dependencycheck/CliParser.html | 2211 +- xref/org/owasp/dependencycheck/Engine.html | 1272 +- .../dependencycheck/agent/package-frame.html | 2 +- .../agent/package-summary.html | 2 +- .../analyzer/AbstractAnalyzer.html | 10 +- .../analyzer/AbstractFileTypeAnalyzer.html | 2 +- .../analyzer/AbstractSuppressionAnalyzer.html | 79 +- .../dependencycheck/analyzer/Analyzer.html | 10 +- .../analyzer/ArchiveAnalyzer.html | 1170 +- .../analyzer/AssemblyAnalyzer.html | 586 +- .../analyzer/AutoconfAnalyzer.html | 496 +- .../analyzer/CMakeAnalyzer.html | 313 +- .../dependencycheck/analyzer/CPEAnalyzer.html | 1587 +- .../analyzer/CentralAnalyzer.html | 2 +- .../analyzer/ComposerLockAnalyzer.html | 195 +- .../analyzer/DependencyBundlingAnalyzer.html | 975 +- .../analyzer/FalsePositiveAnalyzer.html | 118 +- .../analyzer/FileNameAnalyzer.html | 2 +- .../analyzer/HintAnalyzer.html | 4 +- .../dependencycheck/analyzer/JarAnalyzer.html | 1846 +- .../analyzer/NexusAnalyzer.html | 371 +- .../analyzer/NvdCveAnalyzer.html | 2 +- .../analyzer/PythonDistributionAnalyzer.html | 717 +- .../analyzer/PythonPackageAnalyzer.html | 572 +- .../analyzer/RubyBundleAuditAnalyzer.html | 2 +- .../analyzer/exception/package-frame.html | 2 +- .../analyzer/exception/package-summary.html | 2 +- .../analyzer/package-frame.html | 2 +- .../analyzer/package-summary.html | 2 +- .../ant/logging/AntLoggerAdapter.html | 473 +- .../ant/logging/package-frame.html | 2 +- .../ant/logging/package-summary.html | 2 +- .../data/central/CentralSearch.html | 115 +- .../data/central/package-frame.html | 2 +- .../data/central/package-summary.html | 2 +- .../data/composer/package-frame.html | 2 +- .../data/composer/package-summary.html | 2 +- .../data/cpe/package-frame.html | 2 +- .../data/cpe/package-summary.html | 2 +- .../data/cwe/package-frame.html | 2 +- .../data/cwe/package-summary.html | 2 +- .../data/lucene/package-frame.html | 2 +- .../data/lucene/package-summary.html | 2 +- .../data/nexus/NexusSearch.html | 312 +- .../data/nexus/package-frame.html | 2 +- .../data/nexus/package-summary.html | 2 +- .../data/nuget/XPathNuspecParser.html | 90 +- .../data/nuget/package-frame.html | 2 +- .../data/nuget/package-summary.html | 2 +- .../dependencycheck/data/nvdcve/CveDB.html | 30 +- .../data/nvdcve/package-frame.html | 2 +- .../data/nvdcve/package-summary.html | 2 +- .../data/update/CpeUpdater.html | 316 +- .../data/update/EngineVersionCheck.html | 2 +- .../data/update/cpe/package-frame.html | 2 +- .../data/update/cpe/package-summary.html | 2 +- .../data/update/exception/package-frame.html | 2 +- .../update/exception/package-summary.html | 2 +- .../data/update/nvd/ProcessTask.html | 295 +- .../data/update/nvd/package-frame.html | 2 +- .../data/update/nvd/package-summary.html | 2 +- .../data/update/package-frame.html | 2 +- .../data/update/package-summary.html | 2 +- .../dependencycheck/dependency/Evidence.html | 335 +- .../dependency/package-frame.html | 2 +- .../dependency/package-summary.html | 2 +- .../exception/ExceptionCollection.html | 10 +- .../exception/package-frame.html | 2 +- .../exception/package-summary.html | 2 +- .../dependencycheck/maven/AggregateMojo.html | 6 +- .../maven/BaseDependencyCheckMojo.html | 2084 +- .../dependencycheck/maven/CheckMojo.html | 8 +- .../dependencycheck/maven/UpdateMojo.html | 4 +- .../dependencycheck/maven/package-frame.html | 2 +- .../maven/package-summary.html | 2 +- .../owasp/dependencycheck/package-frame.html | 5 +- .../dependencycheck/package-summary.html | 7 +- .../reporting/package-frame.html | 2 +- .../reporting/package-summary.html | 2 +- .../owasp/dependencycheck/taskdefs/Check.html | 1089 +- .../taskdefs/package-frame.html | 2 +- .../taskdefs/package-summary.html | 2 +- .../owasp/dependencycheck/utils/Checksum.html | 191 +- .../utils/DependencyVersion.html | 457 +- .../dependencycheck/utils/Downloader.html | 393 +- .../dependencycheck/utils/FileUtils.html | 112 +- .../utils/SSLSocketFactoryEx.html | 93 +- .../owasp/dependencycheck/utils/Settings.html | 1259 +- .../utils/URLConnectionFactory.html | 2 +- .../dependencycheck/utils/package-frame.html | 2 +- .../utils/package-summary.html | 2 +- .../dependencycheck/xml/hints/HintParser.html | 89 +- .../xml/hints/package-frame.html | 2 +- .../xml/hints/package-summary.html | 2 +- .../owasp/dependencycheck/xml/pom/Model.html | 2 +- .../dependencycheck/xml/pom/PomParser.html | 130 +- .../xml/pom/package-frame.html | 2 +- .../xml/pom/package-summary.html | 2 +- .../xml/suppression/SuppressionParser.html | 187 +- .../xml/suppression/package-frame.html | 2 +- .../xml/suppression/package-summary.html | 2 +- xref/org/slf4j/impl/StaticLoggerBinder.html | 131 +- xref/org/slf4j/impl/package-frame.html | 2 +- xref/org/slf4j/impl/package-summary.html | 2 +- xref/overview-frame.html | 5 +- xref/overview-summary.html | 9 +- 1217 files changed, 79708 insertions(+), 51391 deletions(-) create mode 100644 analyzers/cocoapods.html create mode 100644 analyzers/swift.html create mode 100644 data/tlsfailure.html create mode 100644 dependency-check-core/cobertura/org.owasp.dependencycheck.AnalysisTask.html create mode 100644 dependency-check-core/xref-test/org/owasp/dependencycheck/AnalysisTaskTest.html create mode 100644 dependency-check-core/xref-test/org/owasp/dependencycheck/EngineTest.html create mode 100644 dependency-check-core/xref/org/owasp/dependencycheck/AnalysisTask.html create mode 100644 general/hints.html create mode 100644 xref-test/org/owasp/dependencycheck/AnalysisTaskTest.html create mode 100644 xref-test/org/owasp/dependencycheck/EngineTest.html create mode 100644 xref/org/owasp/dependencycheck/AnalysisTask.html diff --git a/analyzers/archive-analyzer.html b/analyzers/archive-analyzer.html index 55b32a964..c8e43e764 100644 --- a/analyzers/archive-analyzer.html +++ b/analyzers/archive-analyzer.html @@ -1,13 +1,13 @@ - + dependency-check – Archive Analyzer @@ -59,9 +59,9 @@
  • Archive Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/assembly-analyzer.html b/analyzers/assembly-analyzer.html index c0a6377e7..c1c396a0d 100644 --- a/analyzers/assembly-analyzer.html +++ b/analyzers/assembly-analyzer.html @@ -1,13 +1,13 @@ - + dependency-check – Assembly Analyzer @@ -59,9 +59,9 @@
  • Assembly Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/autoconf.html b/analyzers/autoconf.html index d1fa7f712..ed195450e 100644 --- a/analyzers/autoconf.html +++ b/analyzers/autoconf.html @@ -1,13 +1,13 @@ - + dependency-check – Autoconf Analyzer @@ -59,9 +59,9 @@
  • Autoconf Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/central-analyzer.html b/analyzers/central-analyzer.html index 6d1cd3ac5..c922a5812 100644 --- a/analyzers/central-analyzer.html +++ b/analyzers/central-analyzer.html @@ -1,13 +1,13 @@ - + dependency-check – Central Analyzer @@ -59,9 +59,9 @@
  • Central Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/cmake.html b/analyzers/cmake.html index 1733e82ef..a649651c0 100644 --- a/analyzers/cmake.html +++ b/analyzers/cmake.html @@ -1,13 +1,13 @@ - + dependency-check – CMake Analyzer @@ -59,9 +59,9 @@
  • CMake Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/cocoapods.html b/analyzers/cocoapods.html new file mode 100644 index 000000000..1934a6759 --- /dev/null +++ b/analyzers/cocoapods.html @@ -0,0 +1,272 @@ + + + + + + + + + dependency-check – CocoaPods Analyzer + + + + + + + + + + + + + + + + + + Fork me on GitHub + + + + + +
    + + + + + +
    +
    + +
    + + +
    + +

    CocoaPods Analyzer

    +

    Experimental: This analyzer is considered experimental. While this analyzer may be useful and provide valid results more testing must be completed to ensure that the false negative/false positive rates are acceptable.

    +

    OWASP dependency-check includes an analyzer that will analyze SWIFT and Objective-C packages by scanning CocoaPods specification file.

    +

    Files Types Scanned: *.podspec

    +
    +
    +
    + +
    + + + + diff --git a/analyzers/composer-lock.html b/analyzers/composer-lock.html index 686907cb8..e1f42bae1 100644 --- a/analyzers/composer-lock.html +++ b/analyzers/composer-lock.html @@ -1,13 +1,13 @@ - + dependency-check – Composer Lock Analyzer @@ -59,9 +59,9 @@
  • Composer Lock Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@ @@ -342,6 +356,15 @@ +CocoaPods + +CocoaPods .podspec files + +Extracts dependency information from specification file. + + + + Composer Lock PHP Composer Lock files (composer.lock) @@ -349,7 +372,7 @@ Parses PHP Composer lock files for exact versions of dependencies. - + Node.js @@ -358,7 +381,7 @@ Parse JSON format for metadata. - + Python @@ -367,7 +390,7 @@ Regex scan of Python source files for setuptools metadata; Parse RFC822 header format for metadata in all other artifacts. - + Ruby Gemspec @@ -375,6 +398,15 @@ Regex scan Gemspec initialization blocks for metadata. + + + +SWIFT + +SWIFT Package Manager’s Package.swift + +Extracts dependency information from swift package file. + diff --git a/analyzers/jar-analyzer.html b/analyzers/jar-analyzer.html index 5e47f0c74..88c67c3f0 100644 --- a/analyzers/jar-analyzer.html +++ b/analyzers/jar-analyzer.html @@ -1,13 +1,13 @@ - + dependency-check – Jar Analyzer @@ -59,9 +59,9 @@
  • Jar Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/nexus-analyzer.html b/analyzers/nexus-analyzer.html index 89d7a982a..34427c079 100644 --- a/analyzers/nexus-analyzer.html +++ b/analyzers/nexus-analyzer.html @@ -1,13 +1,13 @@ - + dependency-check – Nexus Analyzer @@ -59,9 +59,9 @@
  • Nexus Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/nodejs.html b/analyzers/nodejs.html index 0703ebea1..b3d8b1ecd 100644 --- a/analyzers/nodejs.html +++ b/analyzers/nodejs.html @@ -1,13 +1,13 @@ - + dependency-check – Node.js Analyzer @@ -59,9 +59,9 @@
  • Node.js Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/nuspec-analyzer.html b/analyzers/nuspec-analyzer.html index e457b88c0..1fe19af82 100644 --- a/analyzers/nuspec-analyzer.html +++ b/analyzers/nuspec-analyzer.html @@ -1,13 +1,13 @@ - + dependency-check – Nuspec Analyzer @@ -59,9 +59,9 @@
  • Nuspec Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/openssl.html b/analyzers/openssl.html index 535001009..3e5bcd818 100644 --- a/analyzers/openssl.html +++ b/analyzers/openssl.html @@ -1,13 +1,13 @@ - + dependency-check – OpenSSL Analyzer @@ -59,9 +59,9 @@
  • OpenSSL Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/python.html b/analyzers/python.html index eeb0ed107..9c6eb546b 100644 --- a/analyzers/python.html +++ b/analyzers/python.html @@ -1,13 +1,13 @@ - + dependency-check – Python Analyzer @@ -59,9 +59,9 @@
  • Python Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/ruby-gemspec.html b/analyzers/ruby-gemspec.html index a29429fb5..af20b5c91 100644 --- a/analyzers/ruby-gemspec.html +++ b/analyzers/ruby-gemspec.html @@ -1,13 +1,13 @@ - + dependency-check – Ruby Gemspec Analyzer @@ -59,9 +59,9 @@
  • Ruby Gemspec Analyzer
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,14 +74,14 @@ diff --git a/analyzers/swift.html b/analyzers/swift.html new file mode 100644 index 000000000..26b253739 --- /dev/null +++ b/analyzers/swift.html @@ -0,0 +1,272 @@ + + + + + + + + + dependency-check – SWIFT Package Manager Analyzer + + + + + + + + + + + + + + + + + + Fork me on GitHub + + + + + +
    + + + + + +
    +
    + +
    + + +
    + +

    SWIFT Package Manager Analyzer

    +

    Experimental: This analyzer is considered experimental. While this analyzer may be useful and provide valid results more testing must be completed to ensure that the false negative/false positive rates are acceptable.

    +

    OWASP dependency-check includes an analyzer that will scan the SWIFT Package Manager’s Package.swift file to obtain information on the dependencies used.

    +

    Files Types Scanned: Package.swift

    +
    +
    +
    + +
    + + + + diff --git a/current.txt b/current.txt index 3c80e4f0f..e1df5de7a 100644 --- a/current.txt +++ b/current.txt @@ -1 +1 @@ -1.4.3 \ No newline at end of file +1.4.4 \ No newline at end of file diff --git a/data/cachenvd.html b/data/cachenvd.html index 8f2456d81..6f57a738d 100644 --- a/data/cachenvd.html +++ b/data/cachenvd.html @@ -1,13 +1,13 @@ - + dependency-check – Snapshotting the NVD @@ -59,9 +59,9 @@
  • Snapshotting the NVD
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,7 +74,7 @@ - +
  • diff --git a/data/database.html b/data/database.html index 3c020c608..7da4def46 100644 --- a/data/database.html +++ b/data/database.html @@ -1,13 +1,13 @@ - + dependency-check – Using a Database Server @@ -59,9 +59,9 @@
  • Using a Database Server
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,7 +74,7 @@
    - +
  • @@ -286,7 +293,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies> <dependency> <groupId>org.mariadb.jdbc</groupId> diff --git a/data/index.html b/data/index.html index b4767b43c..696fe0b8b 100644 --- a/data/index.html +++ b/data/index.html @@ -1,13 +1,13 @@ - + dependency-check – Internet Access Required @@ -59,9 +59,9 @@
  • Internet Access Required
  • -
  • | Last Published: 2016-09-06
  • +
  • | Last Published: 2016-11-05
  • - Version: 1.4.3 + Version: 1.4.4
  • @@ -74,7 +74,7 @@
    - +
  • @@ -245,7 +252,8 @@

    There are two reasons dependency-check needs access to the Internet. Below you will find a discussion of each problem and possibly resolutions if you are facing organizational constraints.

    Local NVD Database

    -

    OWASP dependency-check maintains a local copy of the NVD data hosted by NIST. By default, a local H2 database instance is used. As each instance maintains its own copy of the NVD the machine will need access to nvd.nist.gov in order to download the NVD data feeds. While the initial download of the NVD data feed is large, if after the initial download the tool is run at least once every seven days only two small XML files containing the recent modifications will need to be downloaded.

    +

    OWASP dependency-check maintains a local copy of the NVD CVE data hosted by NIST. By default, a local H2 database instance is used. As each instance maintains its own copy of the NVD the machine will need access to nvd.nist.gov in order to download the NVD data feeds. While the initial download of the NVD data feed is large, if after the initial download the tool is run at least once every seven days only two small XML files containing the recent modifications will need to be downloaded.

    +

    In some installations OpenJDK may not be able to download the NVD CVE data. Please see the TLS Failures article for more information.

    If your build servers are using dependency-check and are unable to access the Internet you have a few options:

      diff --git a/data/mirrornvd.html b/data/mirrornvd.html index c9d5668de..6979e043f 100644 --- a/data/mirrornvd.html +++ b/data/mirrornvd.html @@ -1,13 +1,13 @@ - + dependency-check – Mirroring the NVD from NIST @@ -59,9 +59,9 @@
    1. Mirroring the NVD from NIST
    2. -
    3. | Last Published: 2016-09-06
    4. +
    5. | Last Published: 2016-11-05
    6. - Version: 1.4.3 + Version: 1.4.4
    7. @@ -74,7 +74,7 @@ - +
    8. diff --git a/data/proxy.html b/data/proxy.html index 94e049fd9..e23fc2001 100644 --- a/data/proxy.html +++ b/data/proxy.html @@ -1,13 +1,13 @@ - + dependency-check – Proxy Configuration @@ -59,9 +59,9 @@
    9. Proxy Configuration
    10. -
    11. | Last Published: 2016-09-06
    12. +
    13. | Last Published: 2016-11-05
    14. - Version: 1.4.3 + Version: 1.4.4
    15. @@ -74,7 +74,7 @@
      - +
    16. diff --git a/data/tlsfailure.html b/data/tlsfailure.html new file mode 100644 index 000000000..eb4f22e9b --- /dev/null +++ b/data/tlsfailure.html @@ -0,0 +1,173 @@ + + + + + + + + + dependency-check – NVD CVE Download Failures + + + + + + + + + + + + + + + + + + Fork me on GitHub + + + + + +
      + + + + + +
      +
      + +
      + + +
      + +

      NVD CVE Download Failures

      +

      In some installations of the JRE (such as OpenJDK on CentOS/RHEL/Amazon Linux) do not have the correct libraries to support EC cryptography. If you run into problems running dependency-check you may need to install Bouncy Castle and configure Java to use the more robust cryptographic provider.

      +

      Helpful Links * Stackoverflow discussion * Bouncy Castle

      +
      +
      +
      + +
      + +
      +
      +
      +

      Copyright © 2012–2016 + OWASP. + All rights reserved. +

      +
      + + +
      +
      + + diff --git a/data/upgrade.html b/data/upgrade.html index bbf1326a5..a4a29e706 100644 --- a/data/upgrade.html +++ b/data/upgrade.html @@ -1,13 +1,13 @@ - + dependency-check – Database Upgrades @@ -59,9 +59,9 @@
    17. Database Upgrades
    18. -
    19. | Last Published: 2016-09-06
    20. +
    21. | Last Published: 2016-11-05
    22. - Version: 1.4.3 + Version: 1.4.4
    23. @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@

    org.apache.lucene:lucene-analyzers-common

    @@ -1062,7 +1059,7 @@ -
    jar
    Newer versions4.8.0 Next Minor
    4.8.1
    4.9.0
    4.9.1
    4.10.0
    4.10.1
    4.10.2
    4.10.3
    4.10.4 Latest Minor
    5.0.0 Next Major
    5.1.0
    5.2.0
    5.2.1
    5.3.0
    5.3.1
    5.3.2
    5.4.0
    5.4.1
    5.5.0
    5.5.1
    5.5.2
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major
    +4.8.0 Next Minor
    4.8.1
    4.9.0
    4.9.1
    4.10.0
    4.10.1
    4.10.2
    4.10.3
    4.10.4 Latest Minor
    5.0.0 Next Major
    5.1.0
    5.2.0
    5.2.1
    5.3.0
    5.3.1
    5.3.2
    5.4.0
    5.4.1
    5.5.0
    5.5.1
    5.5.2
    5.5.3
    6.0.0
    6.0.1
    6.1.0
    6.2.0
    6.2.1 Latest Major

    org.apache.lucene:lucene-core

    @@ -1089,7 +1086,7 @@ -
    jar
    Newer versions4.8.0 Next Minor
    4.8.1
    4.9.0
    4.9.1
    4.10.0
    4.10.1
    4.10.2
    4.10.3
    4.10.4 Latest Minor
    5.0.0 Next Major
    5.1.0
    5.2.0
    5.2.1
    5.3.0
    5.3.1
    5.3.2
    5.4.0
    5.4.1
    5.5.0
    5.5.1
    5.5.2
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major
    +4.8.0 Next Minor
    4.8.1
    4.9.0
    4.9.1
    4.10.0
    4.10.1
    4.10.2
    4.10.3
    4.10.4 Latest Minor
    5.0.0 Next Major
    5.1.0
    5.2.0
    5.2.1
    5.3.0
    5.3.1
    5.3.2
    5.4.0
    5.4.1
    5.5.0
    5.5.1
    5.5.2
    5.5.3
    6.0.0
    6.0.1
    6.1.0
    6.2.0
    6.2.1 Latest Major

    org.apache.lucene:lucene-queryparser

    @@ -1116,7 +1113,7 @@ -
    jar
    Newer versions4.8.0 Next Minor
    4.8.1
    4.9.0
    4.9.1
    4.10.0
    4.10.1
    4.10.2
    4.10.3
    4.10.4 Latest Minor
    5.0.0 Next Major
    5.1.0
    5.2.0
    5.2.1
    5.3.0
    5.3.1
    5.3.2
    5.4.0
    5.4.1
    5.5.0
    5.5.1
    5.5.2
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major
    +4.8.0 Next Minor
    4.8.1
    4.9.0
    4.9.1
    4.10.0
    4.10.1
    4.10.2
    4.10.3
    4.10.4 Latest Minor
    5.0.0 Next Major
    5.1.0
    5.2.0
    5.2.1
    5.3.0
    5.3.1
    5.3.2
    5.4.0
    5.4.1
    5.5.0
    5.5.1
    5.5.2
    5.5.3
    6.0.0
    6.0.1
    6.1.0
    6.2.0
    6.2.1 Latest Major

    org.apache.lucene:lucene-test-framework

    @@ -1143,7 +1140,7 @@ -
    jar
    Newer versions4.8.0 Next Minor
    4.8.1
    4.9.0
    4.9.1
    4.10.0
    4.10.1
    4.10.2
    4.10.3
    4.10.4 Latest Minor
    5.0.0 Next Major
    5.1.0
    5.2.0
    5.2.1
    5.3.0
    5.3.1
    5.3.2
    5.4.0
    5.4.1
    5.5.0
    5.5.1
    5.5.2
    6.0.0
    6.0.1
    6.1.0
    6.2.0 Latest Major
    +4.8.0 Next Minor
    4.8.1
    4.9.0
    4.9.1
    4.10.0
    4.10.1
    4.10.2
    4.10.3
    4.10.4 Latest Minor
    5.0.0 Next Major
    5.1.0
    5.2.0
    5.2.1
    5.3.0
    5.3.1
    5.3.2
    5.4.0
    5.4.1
    5.5.0
    5.5.1
    5.5.2
    5.5.3
    6.0.0
    6.0.1
    6.1.0
    6.2.0
    6.2.1 Latest Major

    org.apache.maven:maven-core

    @@ -1245,7 +1242,7 @@
    - + @@ -1254,7 +1251,7 @@ - + @@ -1263,10 +1260,7 @@ - - - -
    Status There is at least one newer minor version available. Minor updates are sometimes passive.
     No newer versions available.
    Group Id org.apache.maven.plugin-tools
    maven-plugin-annotations
    Current Version3.4
    3.5
    Scope
    Typejar
    Newer versions3.5 Next Minor
    +jar

    org.apache.maven.reporting:maven-reporting-api

    @@ -1416,13 +1410,13 @@ -
    jar
    Newer versions1.25 Next Minor
    1.26
    1.27 Latest Minor
    +1.25 Next Minor
    1.26
    1.27
    1.28
    1.29 Latest Minor

    org.jsoup:jsoup

    - + @@ -1440,7 +1434,10 @@ -
    Status No newer versions available.
     There is at least one newer minor version available. Minor updates are sometimes passive.
    Group Id org.jsoup
    Typejar
    +jar + +Newer versions +1.10.1 Next Minor

    org.owasp:dependency-check-core

    @@ -1455,7 +1452,7 @@ - + @@ -1479,7 +1476,7 @@ - + diff --git a/dependency-check-ant/findbugs.html b/dependency-check-ant/findbugs.html index e1e51781f..9303d3b23 100644 --- a/dependency-check-ant/findbugs.html +++ b/dependency-check-ant/findbugs.html @@ -1,13 +1,13 @@ - + dependency-check-ant – FindBugs Bug Detector Report @@ -52,7 +52,7 @@ @@ -264,7 +264,7 @@ - +
    dependency-check-core
    Current Version1.4.3
    1.4.4
    Scope compile
    dependency-check-utils
    Current Version1.4.3
    1.4.4
    Scope compile
    Inconsistent synchronization of org.owasp.dependencycheck.taskdefs.Check.path; locked 44% of time MT_CORRECTNESS IS2_INCONSISTENT_SYNC887909 Medium
    diff --git a/dependency-check-ant/index.html b/dependency-check-ant/index.html index 1ade09a95..6612839b5 100644 --- a/dependency-check-ant/index.html +++ b/dependency-check-ant/index.html @@ -1,13 +1,13 @@ - + dependency-check-ant – About @@ -52,7 +52,7 @@ @@ -150,7 +150,7 @@
      -
    1. Download dependency-check-ant from bintray here.
    2. +
    3. Download dependency-check-ant from bintray here.
    4. Unzip the archive
    5. diff --git a/dependency-check-ant/integration.html b/dependency-check-ant/integration.html index 2d72a7996..ade3c5fb7 100644 --- a/dependency-check-ant/integration.html +++ b/dependency-check-ant/integration.html @@ -1,13 +1,13 @@ - + dependency-check-ant – CI Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/issue-tracking.html b/dependency-check-ant/issue-tracking.html index 44aece404..c84d8a870 100644 --- a/dependency-check-ant/issue-tracking.html +++ b/dependency-check-ant/issue-tracking.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Issue Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/license.html b/dependency-check-ant/license.html index 81bc5614e..a9e700a57 100644 --- a/dependency-check-ant/license.html +++ b/dependency-check-ant/license.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Licenses @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/mail-lists.html b/dependency-check-ant/mail-lists.html index e05fc2670..624033d42 100644 --- a/dependency-check-ant/mail-lists.html +++ b/dependency-check-ant/mail-lists.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Mailing Lists @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/plugin-updates-report.html b/dependency-check-ant/plugin-updates-report.html index 1f1ada4cb..ad0341958 100644 --- a/dependency-check-ant/plugin-updates-report.html +++ b/dependency-check-ant/plugin-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Plugin Updates Report @@ -52,7 +52,7 @@ @@ -398,7 +398,7 @@ org.apache.maven.plugins maven-resources-plugin -3.0.0 +3.0.1 @@ -679,7 +679,7 @@ maven-resources-plugin Current Version -3.0.0 +3.0.1

      Plugin org.apache.maven.plugins:maven-site-plugin

      diff --git a/dependency-check-ant/project-info.html b/dependency-check-ant/project-info.html index f97296ae8..19abc15a2 100644 --- a/dependency-check-ant/project-info.html +++ b/dependency-check-ant/project-info.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Information @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/project-reports.html b/dependency-check-ant/project-reports.html index 8203aad6c..8c5d7efa8 100644 --- a/dependency-check-ant/project-reports.html +++ b/dependency-check-ant/project-reports.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Generated Reports @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/project-summary.html b/dependency-check-ant/project-summary.html index 4aa52ae8c..472f0e1cc 100644 --- a/dependency-check-ant/project-summary.html +++ b/dependency-check-ant/project-summary.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Summary @@ -52,7 +52,7 @@ @@ -238,7 +238,7 @@ - + diff --git a/dependency-check-ant/source-repository.html b/dependency-check-ant/source-repository.html index 880c2d00c..a7cf7c6f5 100644 --- a/dependency-check-ant/source-repository.html +++ b/dependency-check-ant/source-repository.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Source Code Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/surefire-report.html b/dependency-check-ant/surefire-report.html index 9e894dd88..f71f9ac27 100644 --- a/dependency-check-ant/surefire-report.html +++ b/dependency-check-ant/surefire-report.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Surefire Report @@ -52,7 +52,7 @@ @@ -259,7 +259,7 @@ function toggleDisplay(elementId) { -
      dependency-check-ant
      Version1.4.3
      1.4.4
      Type jar
      0 0 100%16.115

      +21.722

      Note: failures are anticipated and checked for with assertions while errors are unanticipated.


      Package List

      @@ -280,7 +280,7 @@ function toggleDisplay(elementId) { 0 0 100% -16.115
      +21.722

      Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.

      org.owasp.dependencycheck.taskdefs

      @@ -302,7 +302,7 @@ function toggleDisplay(elementId) { 0 0 100% -16.115

      +21.722

      Test Cases

      [Summary] [Package List] [Test Cases]

      @@ -312,19 +312,19 @@ function toggleDisplay(elementId) { testGetFailBuildOnCVSS -0.317 +0.418 testAddDirSet -6.823 +7.814 testAddFileSet -4.663 +5.717 testAddFileList -4.244

      +7.686
      diff --git a/dependency-check-ant/taglist.html b/dependency-check-ant/taglist.html index 4afe3fb96..db11a7640 100644 --- a/dependency-check-ant/taglist.html +++ b/dependency-check-ant/taglist.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Tag List report @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/team-list.html b/dependency-check-ant/team-list.html index 1a748342b..184f1175f 100644 --- a/dependency-check-ant/team-list.html +++ b/dependency-check-ant/team-list.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Team @@ -52,7 +52,7 @@ diff --git a/dependency-check-ant/xref-test/index.html b/dependency-check-ant/xref-test/index.html index 2cc37fffa..fd383e15f 100644 --- a/dependency-check-ant/xref-test/index.html +++ b/dependency-check-ant/xref-test/index.html @@ -4,7 +4,7 @@ - Dependency-Check Ant Task 1.4.3 Reference + Dependency-Check Ant Task 1.4.4 Reference diff --git a/dependency-check-ant/xref-test/org/owasp/dependencycheck/taskdefs/package-frame.html b/dependency-check-ant/xref-test/org/owasp/dependencycheck/taskdefs/package-frame.html index 5f18161b7..84f22a278 100644 --- a/dependency-check-ant/xref-test/org/owasp/dependencycheck/taskdefs/package-frame.html +++ b/dependency-check-ant/xref-test/org/owasp/dependencycheck/taskdefs/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check Ant Task 1.4.4 Reference Package org.owasp.dependencycheck.taskdefs diff --git a/dependency-check-ant/xref-test/org/owasp/dependencycheck/taskdefs/package-summary.html b/dependency-check-ant/xref-test/org/owasp/dependencycheck/taskdefs/package-summary.html index 159df5aeb..f2a9f2c55 100644 --- a/dependency-check-ant/xref-test/org/owasp/dependencycheck/taskdefs/package-summary.html +++ b/dependency-check-ant/xref-test/org/owasp/dependencycheck/taskdefs/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check Ant Task 1.4.4 Reference Package org.owasp.dependencycheck.taskdefs diff --git a/dependency-check-ant/xref-test/overview-frame.html b/dependency-check-ant/xref-test/overview-frame.html index b7cdf2a83..5cd9f3b1c 100644 --- a/dependency-check-ant/xref-test/overview-frame.html +++ b/dependency-check-ant/xref-test/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference + Dependency-Check Ant Task 1.4.4 Reference diff --git a/dependency-check-ant/xref-test/overview-summary.html b/dependency-check-ant/xref-test/overview-summary.html index 1e7563905..4f1e055da 100644 --- a/dependency-check-ant/xref-test/overview-summary.html +++ b/dependency-check-ant/xref-test/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference + Dependency-Check Ant Task 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Ant Task 1.4.3 Reference

      +

      Dependency-Check Ant Task 1.4.4 Reference

      diff --git a/dependency-check-ant/xref/index.html b/dependency-check-ant/xref/index.html index 2cc37fffa..fd383e15f 100644 --- a/dependency-check-ant/xref/index.html +++ b/dependency-check-ant/xref/index.html @@ -4,7 +4,7 @@ - Dependency-Check Ant Task 1.4.3 Reference + Dependency-Check Ant Task 1.4.4 Reference diff --git a/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/AntLoggerAdapter.html b/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/AntLoggerAdapter.html index acddbbbba..5b4488ba0 100644 --- a/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/AntLoggerAdapter.html +++ b/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/AntLoggerAdapter.html @@ -32,253 +32,258 @@ 24import org.slf4j.helpers.MessageFormatter; 2526/** -27 * An instance of {@link org.slf4j.Logger} which simply calls the log method on the delegate Ant task. -28 * -29 * @author colezlaw -30 */ -31publicclassAntLoggerAdapterextends MarkerIgnoringBase { -32 -33/** -34 * A reference to the Ant task used for logging. -35 */ -36private Task task; -37 +27 * An instance of {@link org.slf4j.Logger} which simply calls the log method on +28 * the delegate Ant task. +29 * +30 * @author colezlaw +31 */ +32publicclassAntLoggerAdapterextends MarkerIgnoringBase { +33 +34/** +35 * serialization UID. +36 */ +37privatestaticfinallong serialVersionUID = -1337; 38/** -39 * Constructs an Ant Logger Adapter. -40 * -41 * @param task the Ant Task to use for logging -42 */ -43publicAntLoggerAdapter(Task task) { -44super(); -45this.task = task; -46 } -47 -48/** -49 * Sets the current Ant task to use for logging. -50 * -51 * @param task the Ant task to use for logging -52 */ -53publicvoid setTask(Task task) { -54this.task = task; -55 } -56 -57 @Override -58publicboolean isTraceEnabled() { -59// Might be a more efficient way to do this, but Ant doesn't enable or disable -60// various levels globally - it just fires things at registered Listeners. -61returntrue; -62 } -63 -64 @Override -65publicvoid trace(String msg) { -66if (task != null) { -67 task.log(msg, Project.MSG_VERBOSE); -68 } -69 } -70 -71 @Override -72publicvoid trace(String format, Object arg) { -73if (task != null) { -74final FormattingTuple tp = MessageFormatter.format(format, arg); -75 task.log(tp.getMessage(), Project.MSG_VERBOSE); -76 } -77 } -78 -79 @Override -80publicvoid trace(String format, Object arg1, Object arg2) { -81if (task != null) { -82final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -83 task.log(tp.getMessage(), Project.MSG_VERBOSE); -84 } -85 } -86 -87 @Override -88publicvoid trace(String format, Object... arguments) { -89if (task != null) { -90final FormattingTuple tp = MessageFormatter.format(format, arguments); -91 task.log(tp.getMessage(), Project.MSG_VERBOSE); -92 } -93 } -94 -95 @Override -96publicvoid trace(String msg, Throwable t) { -97if (task != null) { -98 task.log(msg, t, Project.MSG_VERBOSE); -99 } -100 } -101 -102 @Override -103publicboolean isDebugEnabled() { -104returntrue; +39 * A reference to the Ant task used for logging. +40 */ +41privatetransient Task task; +42 +43/** +44 * Constructs an Ant Logger Adapter. +45 * +46 * @param task the Ant Task to use for logging +47 */ +48publicAntLoggerAdapter(Task task) { +49super(); +50this.task = task; +51 } +52 +53/** +54 * Sets the current Ant task to use for logging. +55 * +56 * @param task the Ant task to use for logging +57 */ +58publicvoid setTask(Task task) { +59this.task = task; +60 } +61 +62 @Override +63publicboolean isTraceEnabled() { +64// Might be a more efficient way to do this, but Ant doesn't enable or disable +65// various levels globally - it just fires things at registered Listeners. +66returntrue; +67 } +68 +69 @Override +70publicvoid trace(String msg) { +71if (task != null) { +72 task.log(msg, Project.MSG_VERBOSE); +73 } +74 } +75 +76 @Override +77publicvoid trace(String format, Object arg) { +78if (task != null) { +79final FormattingTuple tp = MessageFormatter.format(format, arg); +80 task.log(tp.getMessage(), Project.MSG_VERBOSE); +81 } +82 } +83 +84 @Override +85publicvoid trace(String format, Object arg1, Object arg2) { +86if (task != null) { +87final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +88 task.log(tp.getMessage(), Project.MSG_VERBOSE); +89 } +90 } +91 +92 @Override +93publicvoid trace(String format, Object... arguments) { +94if (task != null) { +95final FormattingTuple tp = MessageFormatter.format(format, arguments); +96 task.log(tp.getMessage(), Project.MSG_VERBOSE); +97 } +98 } +99 +100 @Override +101publicvoid trace(String msg, Throwable t) { +102if (task != null) { +103 task.log(msg, t, Project.MSG_VERBOSE); +104 } 105 } 106107 @Override -108publicvoid debug(String msg) { -109if (task != null) { -110 task.log(msg, Project.MSG_DEBUG); -111 } -112 } -113 -114 @Override -115publicvoid debug(String format, Object arg) { -116if (task != null) { -117final FormattingTuple tp = MessageFormatter.format(format, arg); -118 task.log(tp.getMessage(), Project.MSG_DEBUG); -119 } -120 } -121 -122 @Override -123publicvoid debug(String format, Object arg1, Object arg2) { -124if (task != null) { -125final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -126 task.log(tp.getMessage(), Project.MSG_DEBUG); -127 } -128 } -129 -130 @Override -131publicvoid debug(String format, Object... arguments) { -132if (task != null) { -133final FormattingTuple tp = MessageFormatter.format(format, arguments); -134 task.log(tp.getMessage(), Project.MSG_DEBUG); -135 } -136 } -137 -138 @Override -139publicvoid debug(String msg, Throwable t) { -140if (task != null) { -141 task.log(msg, t, Project.MSG_DEBUG); -142 } -143 } -144 -145 @Override -146publicboolean isInfoEnabled() { -147returntrue; +108publicboolean isDebugEnabled() { +109returntrue; +110 } +111 +112 @Override +113publicvoid debug(String msg) { +114if (task != null) { +115 task.log(msg, Project.MSG_DEBUG); +116 } +117 } +118 +119 @Override +120publicvoid debug(String format, Object arg) { +121if (task != null) { +122final FormattingTuple tp = MessageFormatter.format(format, arg); +123 task.log(tp.getMessage(), Project.MSG_DEBUG); +124 } +125 } +126 +127 @Override +128publicvoid debug(String format, Object arg1, Object arg2) { +129if (task != null) { +130final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +131 task.log(tp.getMessage(), Project.MSG_DEBUG); +132 } +133 } +134 +135 @Override +136publicvoid debug(String format, Object... arguments) { +137if (task != null) { +138final FormattingTuple tp = MessageFormatter.format(format, arguments); +139 task.log(tp.getMessage(), Project.MSG_DEBUG); +140 } +141 } +142 +143 @Override +144publicvoid debug(String msg, Throwable t) { +145if (task != null) { +146 task.log(msg, t, Project.MSG_DEBUG); +147 } 148 } 149150 @Override -151publicvoid info(String msg) { -152if (task != null) { -153 task.log(msg, Project.MSG_INFO); -154 } -155 } -156 -157 @Override -158publicvoid info(String format, Object arg) { -159if (task != null) { -160final FormattingTuple tp = MessageFormatter.format(format, arg); -161 task.log(tp.getMessage(), Project.MSG_INFO); -162 } -163 } -164 -165 @Override -166publicvoid info(String format, Object arg1, Object arg2) { -167if (task != null) { -168final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -169 task.log(tp.getMessage(), Project.MSG_INFO); -170 } -171 } -172 -173 @Override -174publicvoid info(String format, Object... arguments) { -175if (task != null) { -176final FormattingTuple tp = MessageFormatter.format(format, arguments); -177 task.log(tp.getMessage(), Project.MSG_INFO); -178 } -179 } -180 -181 @Override -182publicvoid info(String msg, Throwable t) { -183if (task != null) { -184 task.log(msg, t, Project.MSG_INFO); -185 } -186 } -187 -188 @Override -189publicboolean isWarnEnabled() { -190returntrue; +151publicboolean isInfoEnabled() { +152returntrue; +153 } +154 +155 @Override +156publicvoid info(String msg) { +157if (task != null) { +158 task.log(msg, Project.MSG_INFO); +159 } +160 } +161 +162 @Override +163publicvoid info(String format, Object arg) { +164if (task != null) { +165final FormattingTuple tp = MessageFormatter.format(format, arg); +166 task.log(tp.getMessage(), Project.MSG_INFO); +167 } +168 } +169 +170 @Override +171publicvoid info(String format, Object arg1, Object arg2) { +172if (task != null) { +173final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +174 task.log(tp.getMessage(), Project.MSG_INFO); +175 } +176 } +177 +178 @Override +179publicvoid info(String format, Object... arguments) { +180if (task != null) { +181final FormattingTuple tp = MessageFormatter.format(format, arguments); +182 task.log(tp.getMessage(), Project.MSG_INFO); +183 } +184 } +185 +186 @Override +187publicvoid info(String msg, Throwable t) { +188if (task != null) { +189 task.log(msg, t, Project.MSG_INFO); +190 } 191 } 192193 @Override -194publicvoid warn(String msg) { -195if (task != null) { -196 task.log(msg, Project.MSG_WARN); -197 } -198 } -199 -200 @Override -201publicvoid warn(String format, Object arg) { -202if (task != null) { -203final FormattingTuple tp = MessageFormatter.format(format, arg); -204 task.log(tp.getMessage(), Project.MSG_WARN); -205 } -206 } -207 -208 @Override -209publicvoid warn(String format, Object... arguments) { -210if (task != null) { -211final FormattingTuple tp = MessageFormatter.format(format, arguments); -212 task.log(tp.getMessage(), Project.MSG_WARN); -213 } -214 } -215 -216 @Override -217publicvoid warn(String format, Object arg1, Object arg2) { -218if (task != null) { -219final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -220 task.log(tp.getMessage(), Project.MSG_WARN); -221 } -222 } -223 -224 @Override -225publicvoid warn(String msg, Throwable t) { -226if (task != null) { -227 task.log(msg, t, Project.MSG_WARN); -228 } -229 } -230 -231 @Override -232publicboolean isErrorEnabled() { -233returntrue; +194publicboolean isWarnEnabled() { +195returntrue; +196 } +197 +198 @Override +199publicvoid warn(String msg) { +200if (task != null) { +201 task.log(msg, Project.MSG_WARN); +202 } +203 } +204 +205 @Override +206publicvoid warn(String format, Object arg) { +207if (task != null) { +208final FormattingTuple tp = MessageFormatter.format(format, arg); +209 task.log(tp.getMessage(), Project.MSG_WARN); +210 } +211 } +212 +213 @Override +214publicvoid warn(String format, Object... arguments) { +215if (task != null) { +216final FormattingTuple tp = MessageFormatter.format(format, arguments); +217 task.log(tp.getMessage(), Project.MSG_WARN); +218 } +219 } +220 +221 @Override +222publicvoid warn(String format, Object arg1, Object arg2) { +223if (task != null) { +224final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +225 task.log(tp.getMessage(), Project.MSG_WARN); +226 } +227 } +228 +229 @Override +230publicvoid warn(String msg, Throwable t) { +231if (task != null) { +232 task.log(msg, t, Project.MSG_WARN); +233 } 234 } 235236 @Override -237publicvoid error(String msg) { -238if (task != null) { -239 task.log(msg, Project.MSG_ERR); -240 } -241 } -242 -243 @Override -244publicvoid error(String format, Object arg) { -245if (task != null) { -246final FormattingTuple tp = MessageFormatter.format(format, arg); -247 task.log(tp.getMessage(), Project.MSG_ERR); -248 } -249 } -250 -251 @Override -252publicvoid error(String format, Object arg1, Object arg2) { -253if (task != null) { -254final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -255 task.log(tp.getMessage(), Project.MSG_ERR); -256 } -257 } -258 -259 @Override -260publicvoid error(String format, Object... arguments) { -261if (task != null) { -262final FormattingTuple tp = MessageFormatter.format(format, arguments); -263 task.log(tp.getMessage(), Project.MSG_ERR); -264 } -265 } -266 -267 @Override -268publicvoid error(String msg, Throwable t) { -269if (task != null) { -270 task.log(msg, t, Project.MSG_ERR); -271 } -272 } -273 } +237publicboolean isErrorEnabled() { +238returntrue; +239 } +240 +241 @Override +242publicvoid error(String msg) { +243if (task != null) { +244 task.log(msg, Project.MSG_ERR); +245 } +246 } +247 +248 @Override +249publicvoid error(String format, Object arg) { +250if (task != null) { +251final FormattingTuple tp = MessageFormatter.format(format, arg); +252 task.log(tp.getMessage(), Project.MSG_ERR); +253 } +254 } +255 +256 @Override +257publicvoid error(String format, Object arg1, Object arg2) { +258if (task != null) { +259final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +260 task.log(tp.getMessage(), Project.MSG_ERR); +261 } +262 } +263 +264 @Override +265publicvoid error(String format, Object... arguments) { +266if (task != null) { +267final FormattingTuple tp = MessageFormatter.format(format, arguments); +268 task.log(tp.getMessage(), Project.MSG_ERR); +269 } +270 } +271 +272 @Override +273publicvoid error(String msg, Throwable t) { +274if (task != null) { +275 task.log(msg, t, Project.MSG_ERR); +276 } +277 } +278 }
      diff --git a/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/package-frame.html b/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/package-frame.html index 2b11c19df..292ed0d0c 100644 --- a/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/package-frame.html +++ b/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference Package org.owasp.dependencycheck.ant.logging + Dependency-Check Ant Task 1.4.4 Reference Package org.owasp.dependencycheck.ant.logging diff --git a/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/package-summary.html b/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/package-summary.html index 4a041fea8..f069a4b2e 100644 --- a/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/package-summary.html +++ b/dependency-check-ant/xref/org/owasp/dependencycheck/ant/logging/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference Package org.owasp.dependencycheck.ant.logging + Dependency-Check Ant Task 1.4.4 Reference Package org.owasp.dependencycheck.ant.logging diff --git a/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/Check.html b/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/Check.html index 4d625b854..8a93e8d4a 100644 --- a/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/Check.html +++ b/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/Check.html @@ -355,677 +355,700 @@ 347this.suppressionFile = suppressionFile; 348 } 349/** -350 * flag indicating whether or not to show a summary of findings. +350 * The path to the suppression file.351 */ -352privateboolean showSummary = true; +352private String hintsFile; 353354/** -355 * Get the value of showSummary. +355 * Get the value of hintsFile.356 * -357 * @return the value of showSummary +357 * @return the value of hintsFile358 */ -359publicboolean isShowSummary() { -360return showSummary; +359public String getHintsFile() { +360return hintsFile; 361 } 362363/** -364 * Set the value of showSummary. +364 * Set the value of hintsFile.365 * -366 * @param showSummary new value of showSummary +366 * @param hintsFile new value of hintsFile367 */ -368publicvoid setShowSummary(boolean showSummary) { -369this.showSummary = showSummary; +368publicvoid setHintsFile(String hintsFile) { +369this.hintsFile = hintsFile; 370 } -371 -372/** -373 * Whether experimental analyzers are enabled. -374 */ -375private Boolean enableExperimental; -376 -377/** -378 * Get the value of enableExperimental. -379 * -380 * @return the value of enableExperimental -381 */ -382public Boolean isEnableExperimental() { -383return enableExperimental; -384 } -385 -386/** -387 * Set the value of enableExperimental. -388 * -389 * @param enableExperimental new value of enableExperimental -390 */ -391publicvoid setEnableExperimental(Boolean enableExperimental) { -392this.enableExperimental = enableExperimental; -393 } -394 -395/** -396 * Whether or not the Jar Analyzer is enabled. -397 */ -398private Boolean jarAnalyzerEnabled; -399 -400/** -401 * Returns whether or not the analyzer is enabled. -402 * -403 * @return true if the analyzer is enabled -404 */ -405public Boolean isJarAnalyzerEnabled() { -406return jarAnalyzerEnabled; -407 } -408 -409/** -410 * Sets whether or not the analyzer is enabled. -411 * -412 * @param jarAnalyzerEnabled the value of the new setting -413 */ -414publicvoid setJarAnalyzerEnabled(Boolean jarAnalyzerEnabled) { -415this.jarAnalyzerEnabled = jarAnalyzerEnabled; -416 } +371/** +372 * flag indicating whether or not to show a summary of findings. +373 */ +374privateboolean showSummary = true; +375 +376/** +377 * Get the value of showSummary. +378 * +379 * @return the value of showSummary +380 */ +381publicboolean isShowSummary() { +382return showSummary; +383 } +384 +385/** +386 * Set the value of showSummary. +387 * +388 * @param showSummary new value of showSummary +389 */ +390publicvoid setShowSummary(boolean showSummary) { +391this.showSummary = showSummary; +392 } +393 +394/** +395 * Whether experimental analyzers are enabled. +396 */ +397private Boolean enableExperimental; +398 +399/** +400 * Get the value of enableExperimental. +401 * +402 * @return the value of enableExperimental +403 */ +404public Boolean isEnableExperimental() { +405return enableExperimental; +406 } +407 +408/** +409 * Set the value of enableExperimental. +410 * +411 * @param enableExperimental new value of enableExperimental +412 */ +413publicvoid setEnableExperimental(Boolean enableExperimental) { +414this.enableExperimental = enableExperimental; +415 } +416417/** -418 * Whether or not the Archive Analyzer is enabled. +418 * Whether or not the Jar Analyzer is enabled.419 */ -420private Boolean archiveAnalyzerEnabled; +420private Boolean jarAnalyzerEnabled; 421422/**423 * Returns whether or not the analyzer is enabled.424 *425 * @return true if the analyzer is enabled426 */ -427public Boolean isArchiveAnalyzerEnabled() { -428return archiveAnalyzerEnabled; +427public Boolean isJarAnalyzerEnabled() { +428return jarAnalyzerEnabled; 429 } -430/** -431 * Whether or not the .NET Assembly Analyzer is enabled. -432 */ -433private Boolean assemblyAnalyzerEnabled; -434 -435/** -436 * Sets whether or not the analyzer is enabled. -437 * -438 * @param archiveAnalyzerEnabled the value of the new setting -439 */ -440publicvoid setArchiveAnalyzerEnabled(Boolean archiveAnalyzerEnabled) { -441this.archiveAnalyzerEnabled = archiveAnalyzerEnabled; -442 } +430 +431/** +432 * Sets whether or not the analyzer is enabled. +433 * +434 * @param jarAnalyzerEnabled the value of the new setting +435 */ +436publicvoid setJarAnalyzerEnabled(Boolean jarAnalyzerEnabled) { +437this.jarAnalyzerEnabled = jarAnalyzerEnabled; +438 } +439/** +440 * Whether or not the Archive Analyzer is enabled. +441 */ +442private Boolean archiveAnalyzerEnabled; 443444/**445 * Returns whether or not the analyzer is enabled.446 *447 * @return true if the analyzer is enabled448 */ -449public Boolean isAssemblyAnalyzerEnabled() { -450return assemblyAnalyzerEnabled; +449public Boolean isArchiveAnalyzerEnabled() { +450return archiveAnalyzerEnabled; 451 } -452 -453/** -454 * Sets whether or not the analyzer is enabled. -455 * -456 * @param assemblyAnalyzerEnabled the value of the new setting -457 */ -458publicvoid setAssemblyAnalyzerEnabled(Boolean assemblyAnalyzerEnabled) { -459this.assemblyAnalyzerEnabled = assemblyAnalyzerEnabled; -460 } -461/** -462 * Whether or not the .NET Nuspec Analyzer is enabled. -463 */ -464private Boolean nuspecAnalyzerEnabled; +452/** +453 * Whether or not the .NET Assembly Analyzer is enabled. +454 */ +455private Boolean assemblyAnalyzerEnabled; +456 +457/** +458 * Sets whether or not the analyzer is enabled. +459 * +460 * @param archiveAnalyzerEnabled the value of the new setting +461 */ +462publicvoid setArchiveAnalyzerEnabled(Boolean archiveAnalyzerEnabled) { +463this.archiveAnalyzerEnabled = archiveAnalyzerEnabled; +464 } 465466/**467 * Returns whether or not the analyzer is enabled.468 *469 * @return true if the analyzer is enabled470 */ -471public Boolean isNuspecAnalyzerEnabled() { -472return nuspecAnalyzerEnabled; +471public Boolean isAssemblyAnalyzerEnabled() { +472return assemblyAnalyzerEnabled; 473 } 474475/**476 * Sets whether or not the analyzer is enabled.477 * -478 * @param nuspecAnalyzerEnabled the value of the new setting +478 * @param assemblyAnalyzerEnabled the value of the new setting479 */ -480publicvoid setNuspecAnalyzerEnabled(Boolean nuspecAnalyzerEnabled) { -481this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled; +480publicvoid setAssemblyAnalyzerEnabled(Boolean assemblyAnalyzerEnabled) { +481this.assemblyAnalyzerEnabled = assemblyAnalyzerEnabled; 482 } 483/** -484 * Whether or not the PHP Composer Analyzer is enabled. +484 * Whether or not the .NET Nuspec Analyzer is enabled.485 */ -486private Boolean composerAnalyzerEnabled; +486private Boolean nuspecAnalyzerEnabled; 487488/** -489 * Get the value of composerAnalyzerEnabled. +489 * Returns whether or not the analyzer is enabled.490 * -491 * @return the value of composerAnalyzerEnabled +491 * @return true if the analyzer is enabled492 */ -493public Boolean isComposerAnalyzerEnabled() { -494return composerAnalyzerEnabled; +493public Boolean isNuspecAnalyzerEnabled() { +494return nuspecAnalyzerEnabled; 495 } 496497/** -498 * Set the value of composerAnalyzerEnabled. +498 * Sets whether or not the analyzer is enabled.499 * -500 * @param composerAnalyzerEnabled new value of composerAnalyzerEnabled +500 * @param nuspecAnalyzerEnabled the value of the new setting501 */ -502publicvoid setComposerAnalyzerEnabled(Boolean composerAnalyzerEnabled) { -503this.composerAnalyzerEnabled = composerAnalyzerEnabled; +502publicvoid setNuspecAnalyzerEnabled(Boolean nuspecAnalyzerEnabled) { +503this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled; 504 } 505/** -506 * Whether the autoconf analyzer should be enabled. +506 * Whether or not the PHP Composer Analyzer is enabled.507 */ -508private Boolean autoconfAnalyzerEnabled; +508private Boolean composerAnalyzerEnabled; 509510/** -511 * Get the value of autoconfAnalyzerEnabled. +511 * Get the value of composerAnalyzerEnabled.512 * -513 * @return the value of autoconfAnalyzerEnabled +513 * @return the value of composerAnalyzerEnabled514 */ -515public Boolean isAutoconfAnalyzerEnabled() { -516return autoconfAnalyzerEnabled; +515public Boolean isComposerAnalyzerEnabled() { +516return composerAnalyzerEnabled; 517 } 518519/** -520 * Set the value of autoconfAnalyzerEnabled. +520 * Set the value of composerAnalyzerEnabled.521 * -522 * @param autoconfAnalyzerEnabled new value of autoconfAnalyzerEnabled +522 * @param composerAnalyzerEnabled new value of composerAnalyzerEnabled523 */ -524publicvoid setAutoconfAnalyzerEnabled(Boolean autoconfAnalyzerEnabled) { -525this.autoconfAnalyzerEnabled = autoconfAnalyzerEnabled; +524publicvoid setComposerAnalyzerEnabled(Boolean composerAnalyzerEnabled) { +525this.composerAnalyzerEnabled = composerAnalyzerEnabled; 526 } 527/** -528 * Whether the CMake analyzer should be enabled. +528 * Whether the autoconf analyzer should be enabled.529 */ -530private Boolean cmakeAnalyzerEnabled; +530private Boolean autoconfAnalyzerEnabled; 531532/** -533 * Get the value of cmakeAnalyzerEnabled. +533 * Get the value of autoconfAnalyzerEnabled.534 * -535 * @return the value of cmakeAnalyzerEnabled +535 * @return the value of autoconfAnalyzerEnabled536 */ -537public Boolean isCMakeAnalyzerEnabled() { -538return cmakeAnalyzerEnabled; +537public Boolean isAutoconfAnalyzerEnabled() { +538return autoconfAnalyzerEnabled; 539 } 540541/** -542 * Set the value of cmakeAnalyzerEnabled. +542 * Set the value of autoconfAnalyzerEnabled.543 * -544 * @param cmakeAnalyzerEnabled new value of cmakeAnalyzerEnabled +544 * @param autoconfAnalyzerEnabled new value of autoconfAnalyzerEnabled545 */ -546publicvoid setCMakeAnalyzerEnabled(Boolean cmakeAnalyzerEnabled) { -547this.cmakeAnalyzerEnabled = cmakeAnalyzerEnabled; +546publicvoid setAutoconfAnalyzerEnabled(Boolean autoconfAnalyzerEnabled) { +547this.autoconfAnalyzerEnabled = autoconfAnalyzerEnabled; 548 } 549/** -550 * Whether or not the openssl analyzer is enabled. +550 * Whether the CMake analyzer should be enabled.551 */ -552private Boolean opensslAnalyzerEnabled; +552private Boolean cmakeAnalyzerEnabled; 553554/** -555 * Get the value of opensslAnalyzerEnabled. +555 * Get the value of cmakeAnalyzerEnabled.556 * -557 * @return the value of opensslAnalyzerEnabled +557 * @return the value of cmakeAnalyzerEnabled558 */ -559public Boolean isOpensslAnalyzerEnabled() { -560return opensslAnalyzerEnabled; +559public Boolean isCMakeAnalyzerEnabled() { +560return cmakeAnalyzerEnabled; 561 } 562563/** -564 * Set the value of opensslAnalyzerEnabled. +564 * Set the value of cmakeAnalyzerEnabled.565 * -566 * @param opensslAnalyzerEnabled new value of opensslAnalyzerEnabled +566 * @param cmakeAnalyzerEnabled new value of cmakeAnalyzerEnabled567 */ -568publicvoid setOpensslAnalyzerEnabled(Boolean opensslAnalyzerEnabled) { -569this.opensslAnalyzerEnabled = opensslAnalyzerEnabled; +568publicvoid setCMakeAnalyzerEnabled(Boolean cmakeAnalyzerEnabled) { +569this.cmakeAnalyzerEnabled = cmakeAnalyzerEnabled; 570 } 571/** -572 * Whether or not the Node.js Analyzer is enabled. +572 * Whether or not the openssl analyzer is enabled.573 */ -574private Boolean nodeAnalyzerEnabled; +574private Boolean opensslAnalyzerEnabled; 575576/** -577 * Get the value of nodeAnalyzerEnabled. +577 * Get the value of opensslAnalyzerEnabled.578 * -579 * @return the value of nodeAnalyzerEnabled +579 * @return the value of opensslAnalyzerEnabled580 */ -581public Boolean isNodeAnalyzerEnabled() { -582return nodeAnalyzerEnabled; +581public Boolean isOpensslAnalyzerEnabled() { +582return opensslAnalyzerEnabled; 583 } 584585/** -586 * Set the value of nodeAnalyzerEnabled. +586 * Set the value of opensslAnalyzerEnabled.587 * -588 * @param nodeAnalyzerEnabled new value of nodeAnalyzerEnabled +588 * @param opensslAnalyzerEnabled new value of opensslAnalyzerEnabled589 */ -590publicvoid setNodeAnalyzerEnabled(Boolean nodeAnalyzerEnabled) { -591this.nodeAnalyzerEnabled = nodeAnalyzerEnabled; +590publicvoid setOpensslAnalyzerEnabled(Boolean opensslAnalyzerEnabled) { +591this.opensslAnalyzerEnabled = opensslAnalyzerEnabled; 592 } 593/** -594 * Whether the ruby gemspec analyzer should be enabled. +594 * Whether or not the Node.js Analyzer is enabled.595 */ -596private Boolean rubygemsAnalyzerEnabled; +596private Boolean nodeAnalyzerEnabled; 597598/** -599 * Get the value of rubygemsAnalyzerEnabled. +599 * Get the value of nodeAnalyzerEnabled.600 * -601 * @return the value of rubygemsAnalyzerEnabled +601 * @return the value of nodeAnalyzerEnabled602 */ -603public Boolean isRubygemsAnalyzerEnabled() { -604return rubygemsAnalyzerEnabled; +603public Boolean isNodeAnalyzerEnabled() { +604return nodeAnalyzerEnabled; 605 } 606607/** -608 * Set the value of rubygemsAnalyzerEnabled. +608 * Set the value of nodeAnalyzerEnabled.609 * -610 * @param rubygemsAnalyzerEnabled new value of rubygemsAnalyzerEnabled +610 * @param nodeAnalyzerEnabled new value of nodeAnalyzerEnabled611 */ -612publicvoid setRubygemsAnalyzerEnabled(Boolean rubygemsAnalyzerEnabled) { -613this.rubygemsAnalyzerEnabled = rubygemsAnalyzerEnabled; +612publicvoid setNodeAnalyzerEnabled(Boolean nodeAnalyzerEnabled) { +613this.nodeAnalyzerEnabled = nodeAnalyzerEnabled; 614 } 615/** -616 * Whether the python package analyzer should be enabled. +616 * Whether the ruby gemspec analyzer should be enabled.617 */ -618private Boolean pyPackageAnalyzerEnabled; +618private Boolean rubygemsAnalyzerEnabled; 619620/** -621 * Get the value of pyPackageAnalyzerEnabled. +621 * Get the value of rubygemsAnalyzerEnabled.622 * -623 * @return the value of pyPackageAnalyzerEnabled +623 * @return the value of rubygemsAnalyzerEnabled624 */ -625public Boolean isPyPackageAnalyzerEnabled() { -626return pyPackageAnalyzerEnabled; +625public Boolean isRubygemsAnalyzerEnabled() { +626return rubygemsAnalyzerEnabled; 627 } 628629/** -630 * Set the value of pyPackageAnalyzerEnabled. +630 * Set the value of rubygemsAnalyzerEnabled.631 * -632 * @param pyPackageAnalyzerEnabled new value of pyPackageAnalyzerEnabled +632 * @param rubygemsAnalyzerEnabled new value of rubygemsAnalyzerEnabled633 */ -634publicvoid setPyPackageAnalyzerEnabled(Boolean pyPackageAnalyzerEnabled) { -635this.pyPackageAnalyzerEnabled = pyPackageAnalyzerEnabled; +634publicvoid setRubygemsAnalyzerEnabled(Boolean rubygemsAnalyzerEnabled) { +635this.rubygemsAnalyzerEnabled = rubygemsAnalyzerEnabled; 636 } -637 -638/** -639 * Whether the python distribution analyzer should be enabled. -640 */ -641private Boolean pyDistributionAnalyzerEnabled; -642 -643/** -644 * Get the value of pyDistributionAnalyzerEnabled. -645 * -646 * @return the value of pyDistributionAnalyzerEnabled -647 */ -648public Boolean isPyDistributionAnalyzerEnabled() { -649return pyDistributionAnalyzerEnabled; -650 } -651 -652/** -653 * Set the value of pyDistributionAnalyzerEnabled. -654 * -655 * @param pyDistributionAnalyzerEnabled new value of -656 * pyDistributionAnalyzerEnabled -657 */ -658publicvoid setPyDistributionAnalyzerEnabled(Boolean pyDistributionAnalyzerEnabled) { -659this.pyDistributionAnalyzerEnabled = pyDistributionAnalyzerEnabled; -660 } -661 -662/** -663 * Whether or not the central analyzer is enabled. -664 */ -665private Boolean centralAnalyzerEnabled; -666 -667/** -668 * Get the value of centralAnalyzerEnabled. -669 * -670 * @return the value of centralAnalyzerEnabled -671 */ -672public Boolean isCentralAnalyzerEnabled() { -673return centralAnalyzerEnabled; -674 } -675 -676/** -677 * Set the value of centralAnalyzerEnabled. -678 * -679 * @param centralAnalyzerEnabled new value of centralAnalyzerEnabled -680 */ -681publicvoid setCentralAnalyzerEnabled(Boolean centralAnalyzerEnabled) { -682this.centralAnalyzerEnabled = centralAnalyzerEnabled; -683 } -684 -685/** -686 * Whether or not the nexus analyzer is enabled. -687 */ -688private Boolean nexusAnalyzerEnabled; -689 -690/** -691 * Get the value of nexusAnalyzerEnabled. -692 * -693 * @return the value of nexusAnalyzerEnabled -694 */ -695public Boolean isNexusAnalyzerEnabled() { -696return nexusAnalyzerEnabled; -697 } -698 -699/** -700 * Set the value of nexusAnalyzerEnabled. -701 * -702 * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled -703 */ -704publicvoid setNexusAnalyzerEnabled(Boolean nexusAnalyzerEnabled) { -705this.nexusAnalyzerEnabled = nexusAnalyzerEnabled; -706 } -707 -708/** -709 * The URL of a Nexus server's REST API end point -710 * (http://domain/nexus/service/local). -711 */ -712private String nexusUrl; -713 -714/** -715 * Get the value of nexusUrl. -716 * -717 * @return the value of nexusUrl -718 */ -719public String getNexusUrl() { -720return nexusUrl; -721 } -722 -723/** -724 * Set the value of nexusUrl. -725 * -726 * @param nexusUrl new value of nexusUrl -727 */ -728publicvoid setNexusUrl(String nexusUrl) { -729this.nexusUrl = nexusUrl; -730 } -731/** -732 * Whether or not the defined proxy should be used when connecting to Nexus. +637/** +638 * Whether the python package analyzer should be enabled. +639 */ +640private Boolean pyPackageAnalyzerEnabled; +641 +642/** +643 * Get the value of pyPackageAnalyzerEnabled. +644 * +645 * @return the value of pyPackageAnalyzerEnabled +646 */ +647public Boolean isPyPackageAnalyzerEnabled() { +648return pyPackageAnalyzerEnabled; +649 } +650 +651/** +652 * Set the value of pyPackageAnalyzerEnabled. +653 * +654 * @param pyPackageAnalyzerEnabled new value of pyPackageAnalyzerEnabled +655 */ +656publicvoid setPyPackageAnalyzerEnabled(Boolean pyPackageAnalyzerEnabled) { +657this.pyPackageAnalyzerEnabled = pyPackageAnalyzerEnabled; +658 } +659 +660/** +661 * Whether the python distribution analyzer should be enabled. +662 */ +663private Boolean pyDistributionAnalyzerEnabled; +664 +665/** +666 * Get the value of pyDistributionAnalyzerEnabled. +667 * +668 * @return the value of pyDistributionAnalyzerEnabled +669 */ +670public Boolean isPyDistributionAnalyzerEnabled() { +671return pyDistributionAnalyzerEnabled; +672 } +673 +674/** +675 * Set the value of pyDistributionAnalyzerEnabled. +676 * +677 * @param pyDistributionAnalyzerEnabled new value of +678 * pyDistributionAnalyzerEnabled +679 */ +680publicvoid setPyDistributionAnalyzerEnabled(Boolean pyDistributionAnalyzerEnabled) { +681this.pyDistributionAnalyzerEnabled = pyDistributionAnalyzerEnabled; +682 } +683 +684/** +685 * Whether or not the central analyzer is enabled. +686 */ +687private Boolean centralAnalyzerEnabled; +688 +689/** +690 * Get the value of centralAnalyzerEnabled. +691 * +692 * @return the value of centralAnalyzerEnabled +693 */ +694public Boolean isCentralAnalyzerEnabled() { +695return centralAnalyzerEnabled; +696 } +697 +698/** +699 * Set the value of centralAnalyzerEnabled. +700 * +701 * @param centralAnalyzerEnabled new value of centralAnalyzerEnabled +702 */ +703publicvoid setCentralAnalyzerEnabled(Boolean centralAnalyzerEnabled) { +704this.centralAnalyzerEnabled = centralAnalyzerEnabled; +705 } +706 +707/** +708 * Whether or not the nexus analyzer is enabled. +709 */ +710private Boolean nexusAnalyzerEnabled; +711 +712/** +713 * Get the value of nexusAnalyzerEnabled. +714 * +715 * @return the value of nexusAnalyzerEnabled +716 */ +717public Boolean isNexusAnalyzerEnabled() { +718return nexusAnalyzerEnabled; +719 } +720 +721/** +722 * Set the value of nexusAnalyzerEnabled. +723 * +724 * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled +725 */ +726publicvoid setNexusAnalyzerEnabled(Boolean nexusAnalyzerEnabled) { +727this.nexusAnalyzerEnabled = nexusAnalyzerEnabled; +728 } +729 +730/** +731 * The URL of a Nexus server's REST API end point +732 * (http://domain/nexus/service/local).733 */ -734private Boolean nexusUsesProxy; +734private String nexusUrl; 735736/** -737 * Get the value of nexusUsesProxy. +737 * Get the value of nexusUrl.738 * -739 * @return the value of nexusUsesProxy +739 * @return the value of nexusUrl740 */ -741public Boolean isNexusUsesProxy() { -742return nexusUsesProxy; +741public String getNexusUrl() { +742return nexusUrl; 743 } 744745/** -746 * Set the value of nexusUsesProxy. +746 * Set the value of nexusUrl.747 * -748 * @param nexusUsesProxy new value of nexusUsesProxy +748 * @param nexusUrl new value of nexusUrl749 */ -750publicvoid setNexusUsesProxy(Boolean nexusUsesProxy) { -751this.nexusUsesProxy = nexusUsesProxy; +750publicvoid setNexusUrl(String nexusUrl) { +751this.nexusUrl = nexusUrl; 752 } -753 -754/** -755 * Additional ZIP File extensions to add analyze. This should be a -756 * comma-separated list of file extensions to treat like ZIP files. -757 */ -758private String zipExtensions; -759 -760/** -761 * Get the value of zipExtensions. -762 * -763 * @return the value of zipExtensions -764 */ -765public String getZipExtensions() { -766return zipExtensions; -767 } -768 -769/** -770 * Set the value of zipExtensions. -771 * -772 * @param zipExtensions new value of zipExtensions -773 */ -774publicvoid setZipExtensions(String zipExtensions) { -775this.zipExtensions = zipExtensions; -776 } -777 -778/** -779 * The path to Mono for .NET assembly analysis on non-windows systems. -780 */ -781private String pathToMono; -782 -783/** -784 * Get the value of pathToMono. -785 * -786 * @return the value of pathToMono -787 */ -788public String getPathToMono() { -789return pathToMono; -790 } -791 -792/** -793 * Set the value of pathToMono. -794 * -795 * @param pathToMono new value of pathToMono -796 */ -797publicvoid setPathToMono(String pathToMono) { -798this.pathToMono = pathToMono; -799 } -800 -801 @Override -802publicvoid execute() throws BuildException { -803 dealWithReferences(); -804 validateConfiguration(); -805 populateSettings(); -806 Engine engine = null; -807try { -808 engine = new Engine(Check.class.getClassLoader()); -809if (isUpdateOnly()) { -810 log("Deprecated 'UpdateOnly' property set; please use the UpdateTask instead", Project.MSG_WARN); -811try { -812 engine.doUpdates(); -813 } catch (UpdateException ex) { -814if (this.isFailOnError()) { -815thrownew BuildException(ex); -816 } -817 log(ex.getMessage(), Project.MSG_ERR); -818 } -819 } else { -820for (Resource resource : path) { -821final FileProvider provider = resource.as(FileProvider.class); -822if (provider != null) { -823final File file = provider.getFile(); -824if (file != null && file.exists()) { -825 engine.scan(file); -826 } -827 } -828 } -829 -830try { -831 engine.analyzeDependencies(); -832 } catch (ExceptionCollection ex) { -833if (this.isFailOnError()) { -834thrownew BuildException(ex); -835 } -836 } -837 DatabaseProperties prop = null; -838 CveDB cve = null; -839try { -840 cve = new CveDB(); -841 cve.open(); -842 prop = cve.getDatabaseProperties(); -843 } catch (DatabaseException ex) { -844 log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG); -845 } finally { -846if (cve != null) { -847 cve.close(); -848 } -849 } -850final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop); -851 reporter.generateReports(reportOutputDirectory, reportFormat); -852 -853if (this.failBuildOnCVSS <= 10) { -854 checkForFailure(engine.getDependencies()); -855 } -856if (this.showSummary) { -857 showSummary(engine.getDependencies()); +753/** +754 * Whether or not the defined proxy should be used when connecting to Nexus. +755 */ +756private Boolean nexusUsesProxy; +757 +758/** +759 * Get the value of nexusUsesProxy. +760 * +761 * @return the value of nexusUsesProxy +762 */ +763public Boolean isNexusUsesProxy() { +764return nexusUsesProxy; +765 } +766 +767/** +768 * Set the value of nexusUsesProxy. +769 * +770 * @param nexusUsesProxy new value of nexusUsesProxy +771 */ +772publicvoid setNexusUsesProxy(Boolean nexusUsesProxy) { +773this.nexusUsesProxy = nexusUsesProxy; +774 } +775 +776/** +777 * Additional ZIP File extensions to add analyze. This should be a +778 * comma-separated list of file extensions to treat like ZIP files. +779 */ +780private String zipExtensions; +781 +782/** +783 * Get the value of zipExtensions. +784 * +785 * @return the value of zipExtensions +786 */ +787public String getZipExtensions() { +788return zipExtensions; +789 } +790 +791/** +792 * Set the value of zipExtensions. +793 * +794 * @param zipExtensions new value of zipExtensions +795 */ +796publicvoid setZipExtensions(String zipExtensions) { +797this.zipExtensions = zipExtensions; +798 } +799 +800/** +801 * The path to Mono for .NET assembly analysis on non-windows systems. +802 */ +803private String pathToMono; +804 +805/** +806 * Get the value of pathToMono. +807 * +808 * @return the value of pathToMono +809 */ +810public String getPathToMono() { +811return pathToMono; +812 } +813 +814/** +815 * Set the value of pathToMono. +816 * +817 * @param pathToMono new value of pathToMono +818 */ +819publicvoid setPathToMono(String pathToMono) { +820this.pathToMono = pathToMono; +821 } +822 +823 @Override +824publicvoid execute() throws BuildException { +825 dealWithReferences(); +826 validateConfiguration(); +827 populateSettings(); +828 Engine engine = null; +829try { +830 engine = new Engine(Check.class.getClassLoader()); +831if (isUpdateOnly()) { +832 log("Deprecated 'UpdateOnly' property set; please use the UpdateTask instead", Project.MSG_WARN); +833try { +834 engine.doUpdates(); +835 } catch (UpdateException ex) { +836if (this.isFailOnError()) { +837thrownew BuildException(ex); +838 } +839 log(ex.getMessage(), Project.MSG_ERR); +840 } +841 } else { +842for (Resource resource : path) { +843final FileProvider provider = resource.as(FileProvider.class); +844if (provider != null) { +845final File file = provider.getFile(); +846if (file != null && file.exists()) { +847 engine.scan(file); +848 } +849 } +850 } +851 +852try { +853 engine.analyzeDependencies(); +854 } catch (ExceptionCollection ex) { +855if (this.isFailOnError()) { +856thrownew BuildException(ex); +857 } 858 } -859 } -860 } catch (DatabaseException ex) { -861final String msg = "Unable to connect to the dependency-check database; analysis has stopped"; -862if (this.isFailOnError()) { -863thrownew BuildException(msg, ex); -864 } -865 log(msg, ex, Project.MSG_ERR); -866 } catch (ReportException ex) { -867final String msg = "Unable to generate the dependency-check report"; -868if (this.isFailOnError()) { -869thrownew BuildException(msg, ex); -870 } -871 log(msg, ex, Project.MSG_ERR); -872 } finally { -873 Settings.cleanup(true); -874if (engine != null) { -875 engine.cleanup(); -876 } -877 } -878 } -879 -880/** -881 * Validate the configuration to ensure the parameters have been properly -882 * configured/initialized. -883 * -884 * @throws BuildException if the task was not configured correctly. -885 */ -886privatevoid validateConfiguration() throws BuildException { -887if (path == null) { -888thrownew BuildException("No project dependencies have been defined to analyze."); -889 } -890if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) { -891thrownew BuildException("Invalid configuration, failBuildOnCVSS must be between 0 and 11."); -892 } -893 } -894 -895/** -896 * Takes the properties supplied and updates the dependency-check settings. -897 * Additionally, this sets the system properties required to change the -898 * proxy server, port, and connection timeout. -899 * -900 * @throws BuildException thrown when an invalid setting is configured. -901 */ -902 @Override -903protectedvoid populateSettings() throws BuildException { -904super.populateSettings(); -905 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); -906 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); -907 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); -908 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); -909 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); -910 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); -911 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); -912 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); -913 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); -914 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); -915 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); -916 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); -917 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); -918 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); -919 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); -920 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); -921 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); -922 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); -923 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); -924 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); -925 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); -926 } -927 -928/** -929 * Checks to see if a vulnerability has been identified with a CVSS score -930 * that is above the threshold set in the configuration. -931 * -932 * @param dependencies the list of dependency objects -933 * @throws BuildException thrown if a CVSS score is found that is higher -934 * then the threshold set -935 */ -936privatevoid checkForFailure(List<Dependency> dependencies) throws BuildException { -937final StringBuilder ids = new StringBuilder(); -938for (Dependency d : dependencies) { -939for (Vulnerability v : d.getVulnerabilities()) { -940if (v.getCvssScore() >= failBuildOnCVSS) { -941if (ids.length() == 0) { -942 ids.append(v.getName()); -943 } else { -944 ids.append(", ").append(v.getName()); -945 } -946 } -947 } -948 } -949if (ids.length() > 0) { -950final String msg = String.format("%n%nDependency-Check Failure:%n" -951 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" -952 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); -953thrownew BuildException(msg); -954 } -955 } -956 -957/** -958 * Generates a warning message listing a summary of dependencies and their -959 * associated CPE and CVE entries. -960 * -961 * @param dependencies a list of dependency objects -962 */ -963privatevoid showSummary(List<Dependency> dependencies) { -964final StringBuilder summary = new StringBuilder(); -965for (Dependency d : dependencies) { -966boolean firstEntry = true; -967final StringBuilder ids = new StringBuilder(); -968for (Vulnerability v : d.getVulnerabilities()) { -969if (firstEntry) { -970 firstEntry = false; -971 } else { -972 ids.append(", "); -973 } -974 ids.append(v.getName()); -975 } -976if (ids.length() > 0) { -977 summary.append(d.getFileName()).append(" ("); -978 firstEntry = true; -979for (Identifier id : d.getIdentifiers()) { -980if (firstEntry) { -981 firstEntry = false; -982 } else { -983 summary.append(", "); -984 } -985 summary.append(id.getValue()); -986 } -987 summary.append(") : ").append(ids).append(NEW_LINE); -988 } -989 } -990if (summary.length() > 0) { -991final String msg = String.format("%n%n" -992 + "One or more dependencies were identified with known vulnerabilities:%n%n%s" -993 + "%n%nSee the dependency-check report for more details.%n%n", summary.toString()); -994 log(msg, Project.MSG_WARN); -995 } -996 } -997 -998/** -999 * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", -1000 * etc.. -1001 */ -1002publicstaticclassReportFormatsextends EnumeratedAttribute { -1003 -1004/** -1005 * Returns the list of values for the report format. -1006 * -1007 * @return the list of values for the report format -1008 */ -1009 @Override -1010public String[] getValues() { -1011int i = 0; -1012final Format[] formats = Format.values(); -1013final String[] values = new String[formats.length]; -1014for (Format format : formats) { -1015 values[i++] = format.name(); -1016 } -1017return values; +859 DatabaseProperties prop = null; +860 CveDB cve = null; +861try { +862 cve = new CveDB(); +863 cve.open(); +864 prop = cve.getDatabaseProperties(); +865 } catch (DatabaseException ex) { +866 log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG); +867 } finally { +868if (cve != null) { +869 cve.close(); +870 } +871 } +872final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop); +873 reporter.generateReports(reportOutputDirectory, reportFormat); +874 +875if (this.failBuildOnCVSS <= 10) { +876 checkForFailure(engine.getDependencies()); +877 } +878if (this.showSummary) { +879 showSummary(engine.getDependencies()); +880 } +881 } +882 } catch (DatabaseException ex) { +883final String msg = "Unable to connect to the dependency-check database; analysis has stopped"; +884if (this.isFailOnError()) { +885thrownew BuildException(msg, ex); +886 } +887 log(msg, ex, Project.MSG_ERR); +888 } catch (ReportException ex) { +889final String msg = "Unable to generate the dependency-check report"; +890if (this.isFailOnError()) { +891thrownew BuildException(msg, ex); +892 } +893 log(msg, ex, Project.MSG_ERR); +894 } finally { +895 Settings.cleanup(true); +896if (engine != null) { +897 engine.cleanup(); +898 } +899 } +900 } +901 +902/** +903 * Validate the configuration to ensure the parameters have been properly +904 * configured/initialized. +905 * +906 * @throws BuildException if the task was not configured correctly. +907 */ +908privatevoid validateConfiguration() throws BuildException { +909if (path == null) { +910thrownew BuildException("No project dependencies have been defined to analyze."); +911 } +912if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) { +913thrownew BuildException("Invalid configuration, failBuildOnCVSS must be between 0 and 11."); +914 } +915 } +916 +917/** +918 * Takes the properties supplied and updates the dependency-check settings. +919 * Additionally, this sets the system properties required to change the +920 * proxy server, port, and connection timeout. +921 * +922 * @throws BuildException thrown when an invalid setting is configured. +923 */ +924 @Override +925protectedvoid populateSettings() throws BuildException { +926super.populateSettings(); +927 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); +928 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); +929 Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile); +930 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); +931 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); +932 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); +933 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); +934 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); +935 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); +936 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); +937 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); +938 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); +939 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); +940 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); +941 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); +942 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); +943 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); +944 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); +945 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); +946 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); +947 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); +948 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); +949 } +950 +951/** +952 * Checks to see if a vulnerability has been identified with a CVSS score +953 * that is above the threshold set in the configuration. +954 * +955 * @param dependencies the list of dependency objects +956 * @throws BuildException thrown if a CVSS score is found that is higher +957 * then the threshold set +958 */ +959privatevoid checkForFailure(List<Dependency> dependencies) throws BuildException { +960final StringBuilder ids = new StringBuilder(); +961for (Dependency d : dependencies) { +962for (Vulnerability v : d.getVulnerabilities()) { +963if (v.getCvssScore() >= failBuildOnCVSS) { +964if (ids.length() == 0) { +965 ids.append(v.getName()); +966 } else { +967 ids.append(", ").append(v.getName()); +968 } +969 } +970 } +971 } +972if (ids.length() > 0) { +973final String msg = String.format("%n%nDependency-Check Failure:%n" +974 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" +975 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); +976thrownew BuildException(msg); +977 } +978 } +979 +980/** +981 * Generates a warning message listing a summary of dependencies and their +982 * associated CPE and CVE entries. +983 * +984 * @param dependencies a list of dependency objects +985 */ +986privatevoid showSummary(List<Dependency> dependencies) { +987final StringBuilder summary = new StringBuilder(); +988for (Dependency d : dependencies) { +989boolean firstEntry = true; +990final StringBuilder ids = new StringBuilder(); +991for (Vulnerability v : d.getVulnerabilities()) { +992if (firstEntry) { +993 firstEntry = false; +994 } else { +995 ids.append(", "); +996 } +997 ids.append(v.getName()); +998 } +999if (ids.length() > 0) { +1000 summary.append(d.getFileName()).append(" ("); +1001 firstEntry = true; +1002for (Identifier id : d.getIdentifiers()) { +1003if (firstEntry) { +1004 firstEntry = false; +1005 } else { +1006 summary.append(", "); +1007 } +1008 summary.append(id.getValue()); +1009 } +1010 summary.append(") : ").append(ids).append(NEW_LINE); +1011 } +1012 } +1013if (summary.length() > 0) { +1014final String msg = String.format("%n%n" +1015 + "One or more dependencies were identified with known vulnerabilities:%n%n%s" +1016 + "%n%nSee the dependency-check report for more details.%n%n", summary.toString()); +1017 log(msg, Project.MSG_WARN); 1018 } 1019 } -1020 } +1020 +1021/** +1022 * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", +1023 * etc.. +1024 */ +1025publicstaticclassReportFormatsextends EnumeratedAttribute { +1026 +1027/** +1028 * Returns the list of values for the report format. +1029 * +1030 * @return the list of values for the report format +1031 */ +1032 @Override +1033public String[] getValues() { +1034int i = 0; +1035final Format[] formats = Format.values(); +1036final String[] values = new String[formats.length]; +1037for (Format format : formats) { +1038 values[i++] = format.name(); +1039 } +1040return values; +1041 } +1042 } +1043 }
      diff --git a/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/package-frame.html b/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/package-frame.html index 683c19176..6d6c7c2fe 100644 --- a/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/package-frame.html +++ b/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check Ant Task 1.4.4 Reference Package org.owasp.dependencycheck.taskdefs diff --git a/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/package-summary.html b/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/package-summary.html index aa7ba8d8a..ba7404dc3 100644 --- a/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/package-summary.html +++ b/dependency-check-ant/xref/org/owasp/dependencycheck/taskdefs/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check Ant Task 1.4.4 Reference Package org.owasp.dependencycheck.taskdefs diff --git a/dependency-check-ant/xref/org/slf4j/impl/package-frame.html b/dependency-check-ant/xref/org/slf4j/impl/package-frame.html index 56f691028..a7b77f31a 100644 --- a/dependency-check-ant/xref/org/slf4j/impl/package-frame.html +++ b/dependency-check-ant/xref/org/slf4j/impl/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference Package org.slf4j.impl + Dependency-Check Ant Task 1.4.4 Reference Package org.slf4j.impl diff --git a/dependency-check-ant/xref/org/slf4j/impl/package-summary.html b/dependency-check-ant/xref/org/slf4j/impl/package-summary.html index 65fb0ceeb..720e5a0e7 100644 --- a/dependency-check-ant/xref/org/slf4j/impl/package-summary.html +++ b/dependency-check-ant/xref/org/slf4j/impl/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference Package org.slf4j.impl + Dependency-Check Ant Task 1.4.4 Reference Package org.slf4j.impl diff --git a/dependency-check-ant/xref/overview-frame.html b/dependency-check-ant/xref/overview-frame.html index 9e7c3a85a..246ef399c 100644 --- a/dependency-check-ant/xref/overview-frame.html +++ b/dependency-check-ant/xref/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference + Dependency-Check Ant Task 1.4.4 Reference diff --git a/dependency-check-ant/xref/overview-summary.html b/dependency-check-ant/xref/overview-summary.html index 6b8932af8..c1848b65e 100644 --- a/dependency-check-ant/xref/overview-summary.html +++ b/dependency-check-ant/xref/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Ant Task 1.4.3 Reference + Dependency-Check Ant Task 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Ant Task 1.4.3 Reference

      +

      Dependency-Check Ant Task 1.4.4 Reference

      diff --git a/dependency-check-cli/apidocs/allclasses-frame.html b/dependency-check-cli/apidocs/allclasses-frame.html index 62b36a1ed..e4ff86e25 100644 --- a/dependency-check-cli/apidocs/allclasses-frame.html +++ b/dependency-check-cli/apidocs/allclasses-frame.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Command Line 1.4.3 API) - +All Classes (Dependency-Check Command Line 1.4.4 API) + diff --git a/dependency-check-cli/apidocs/allclasses-noframe.html b/dependency-check-cli/apidocs/allclasses-noframe.html index f227c3a4a..775022a85 100644 --- a/dependency-check-cli/apidocs/allclasses-noframe.html +++ b/dependency-check-cli/apidocs/allclasses-noframe.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Command Line 1.4.3 API) - +All Classes (Dependency-Check Command Line 1.4.4 API) + diff --git a/dependency-check-cli/apidocs/constant-values.html b/dependency-check-cli/apidocs/constant-values.html index ab1e06e82..091db6d43 100644 --- a/dependency-check-cli/apidocs/constant-values.html +++ b/dependency-check-cli/apidocs/constant-values.html @@ -2,10 +2,10 @@ - + -Constant Field Values (Dependency-Check Command Line 1.4.3 API) - +Constant Field Values (Dependency-Check Command Line 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,13 +13,13 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-cli/apidocs/org/owasp/dependencycheck/package-summary.html b/dependency-check-cli/apidocs/org/owasp/dependencycheck/package-summary.html index 7cc622dd3..3da449cc7 100644 --- a/dependency-check-cli/apidocs/org/owasp/dependencycheck/package-summary.html +++ b/dependency-check-cli/apidocs/org/owasp/dependencycheck/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck (Dependency-Check Command Line 1.4.3 API) - +org.owasp.dependencycheck (Dependency-Check Command Line 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ - + diff --git a/dependency-check-cli/cobertura/frame-summary.html b/dependency-check-cli/cobertura/frame-summary.html index e944f6a2a..6d7faac29 100644 --- a/dependency-check-cli/cobertura/frame-summary.html +++ b/dependency-check-cli/cobertura/frame-summary.html @@ -16,8 +16,8 @@
      - - + +
      Package # Classes Line Coverage Branch Coverage Complexity
      All Packages4
      42%
      287/678
      18%
      56/306
      3.213
      org.owasp.dependencycheck4
      42%
      287/678
      18%
      56/306
      3.213
      All Packages4
      42%
      291/685
      18%
      56/306
      3.184
      org.owasp.dependencycheck4
      42%
      291/685
      18%
      56/306
      3.184
      - + diff --git a/dependency-check-cli/cobertura/org.owasp.dependencycheck.App.html b/dependency-check-cli/cobertura/org.owasp.dependencycheck.App.html index 104fe0adf..b1981e996 100644 --- a/dependency-check-cli/cobertura/org.owasp.dependencycheck.App.html +++ b/dependency-check-cli/cobertura/org.owasp.dependencycheck.App.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      App
      8%
      26/300
      8%
      10/118
      10
      App
      8%
      26/302
      8%
      10/118
      10
       
      @@ -60,711 +60,715 @@  21  
       import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
       22   -
       import java.io.File;
      +
       import ch.qos.logback.classic.spi.ILoggingEvent;
       23   -
       import java.io.FileNotFoundException;
      +
       import java.io.File;
       24   -
       import java.io.IOException;
      +
       import java.io.FileNotFoundException;
       25   -
       import java.util.ArrayList;
      +
       import java.io.IOException;
       26   -
       import java.util.HashSet;
      +
       import java.util.ArrayList;
       27   -
       import java.util.List;
      +
       import java.util.HashSet;
       28   -
       import java.util.Set;
      +
       import java.util.List;
       29   -
       import org.apache.commons.cli.ParseException;
      +
       import java.util.Set;
       30   -
       import org.owasp.dependencycheck.data.nvdcve.CveDB;
      +
       import org.apache.commons.cli.ParseException;
       31   -
       import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
      +
       import org.owasp.dependencycheck.data.nvdcve.CveDB;
       32   -
       import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
      +
       import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
       33   -
       import org.owasp.dependencycheck.dependency.Dependency;
      +
       import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
       34   -
       import org.apache.tools.ant.DirectoryScanner;
      +
       import org.owasp.dependencycheck.dependency.Dependency;
       35   -
       import org.owasp.dependencycheck.reporting.ReportGenerator;
      +
       import org.apache.tools.ant.DirectoryScanner;
       36   -
       import org.owasp.dependencycheck.utils.Settings;
      +
       import org.owasp.dependencycheck.reporting.ReportGenerator;
       37   -
       import org.slf4j.Logger;
      +
       import org.owasp.dependencycheck.utils.Settings;
       38   -
       import org.slf4j.LoggerFactory;
      +
       import org.slf4j.Logger;
       39   -
       import ch.qos.logback.core.FileAppender;
      +
       import org.slf4j.LoggerFactory;
       40   -
       import org.owasp.dependencycheck.data.update.exception.UpdateException;
      +
       import ch.qos.logback.core.FileAppender;
       41   -
       import org.owasp.dependencycheck.exception.ExceptionCollection;
      +
       import org.owasp.dependencycheck.data.update.exception.UpdateException;
       42   -
       import org.owasp.dependencycheck.exception.ReportException;
      +
       import org.owasp.dependencycheck.exception.ExceptionCollection;
       43   -
       import org.owasp.dependencycheck.utils.InvalidSettingException;
      +
       import org.owasp.dependencycheck.exception.ReportException;
       44   -
       import org.slf4j.impl.StaticLoggerBinder;
      +
       import org.owasp.dependencycheck.utils.InvalidSettingException;
       45   -
       
      +
       import org.slf4j.impl.StaticLoggerBinder;
       46   -
       /**
      +
       
       47   -
        * The command line interface for the DependencyCheck application.
      +
       /**
       48   -
        *
      +
        * The command line interface for the DependencyCheck application.
       49   -
        * @author Jeremy Long
      +
        *
       50   +
        * @author Jeremy Long
      +  51  
        */
      -  51  2
       public class App {
      -  52   -
       
      +  52  2
       public class App {
       53   -
           /**
      +
       
       54   -
            * The logger.
      +
           /**
       55   +
            * The logger.
      +  56  
            */
      -  56  1
           private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
      -  57   -
       
      +  57  1
           private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
       58   -
           /**
      +
       
       59   -
            * The main method for the application.
      +
           /**
       60   -
            *
      +
            * The main method for the application.
       61   -
            * @param args the command line arguments
      +
            *
       62   -
            */
      -  63   -
           public static void main(String[] args) {
      -  64  0
               int exitCode = 0;
      -  65   -
               try {
      -  66  0
                   Settings.initialize();
      -  67  0
                   final App app = new App();
      -  68  0
                   exitCode = app.run(args);
      -  69  0
                   LOGGER.debug("Exit code: " + exitCode);
      -  70   -
               } finally {
      -  71  0
                   Settings.cleanup(true);
      -  72  0
               }
      -  73  0
               System.exit(exitCode);
      -  74  0
           }
      -  75   -
       
      -  76   -
           /**
      -  77   -
            * Main CLI entry-point into the application.
      -  78   -
            *
      -  79  
            * @param args the command line arguments
      +  63   +
            */
      +  64   +
           public static void main(String[] args) {
      +  65  0
               int exitCode = 0;
      +  66   +
               try {
      +  67  0
                   Settings.initialize();
      +  68  0
                   final App app = new App();
      +  69  0
                   exitCode = app.run(args);
      +  70  0
                   LOGGER.debug("Exit code: " + exitCode);
      +  71   +
               } finally {
      +  72  0
                   Settings.cleanup(true);
      +  73  0
               }
      +  74  0
               System.exit(exitCode);
      +  75  0
           }
      +  76   +
       
      +  77   +
           /**
      +  78   +
            * Main CLI entry-point into the application.
      +  79   +
            *
       80   -
            * @return the exit code to return
      +
            * @param args the command line arguments
       81   -
            */
      +
            * @return the exit code to return
       82   +
            */
      +  83  
           public int run(String[] args) {
      -  83  0
               int exitCode = 0;
      -  84  0
               final CliParser cli = new CliParser();
      -  85   -
       
      +  84  0
               int exitCode = 0;
      +  85  0
               final CliParser cli = new CliParser();
       86   -
               try {
      -  87  0
                   cli.parse(args);
      -  88  0
               } catch (FileNotFoundException ex) {
      -  89  0
                   System.err.println(ex.getMessage());
      -  90  0
                   cli.printHelp();
      -  91  0
                   return -1;
      -  92  0
               } catch (ParseException ex) {
      -  93  0
                   System.err.println(ex.getMessage());
      -  94  0
                   cli.printHelp();
      -  95  0
                   return -2;
      -  96  0
               }
      -  97  
       
      -  98  0
               if (cli.getVerboseLog() != null) {
      -  99  0
                   prepareLogger(cli.getVerboseLog());
      -  100   -
               }
      +  87   +
               try {
      +  88  0
                   cli.parse(args);
      +  89  0
               } catch (FileNotFoundException ex) {
      +  90  0
                   System.err.println(ex.getMessage());
      +  91  0
                   cli.printHelp();
      +  92  0
                   return -1;
      +  93  0
               } catch (ParseException ex) {
      +  94  0
                   System.err.println(ex.getMessage());
      +  95  0
                   cli.printHelp();
      +  96  0
                   return -2;
      +  97  0
               }
      +  98   +
       
      +  99  0
               if (cli.getVerboseLog() != null) {
      +  100  0
                   prepareLogger(cli.getVerboseLog());
       101   +
               }
      +  102  
       
      -  102  0
               if (cli.isPurge()) {
      -  103  0
                   if (cli.getConnectionString() != null) {
      -  104  0
                       LOGGER.error("Unable to purge the database when using a non-default connection string");
      -  105  0
                       exitCode = -3;
      -  106   -
                   } else {
      +  103  0
               if (cli.isPurge()) {
      +  104  0
                   if (cli.getConnectionString() != null) {
      +  105  0
                       LOGGER.error("Unable to purge the database when using a non-default connection string");
      +  106  0
                       exitCode = -3;
       107   +
                   } else {
      +  108  
                       try {
      -  108  0
                           populateSettings(cli);
      -  109  0
                       } catch (InvalidSettingException ex) {
      -  110  0
                           LOGGER.error(ex.getMessage());
      -  111  0
                           LOGGER.debug("Error loading properties file", ex);
      -  112  0
                           exitCode = -4;
      -  113  0
                       }
      -  114   -
                       File db;
      +  109  0
                           populateSettings(cli);
      +  110  0
                       } catch (InvalidSettingException ex) {
      +  111  0
                           LOGGER.error(ex.getMessage());
      +  112  0
                           LOGGER.debug("Error loading properties file", ex);
      +  113  0
                           exitCode = -4;
      +  114  0
                       }
       115   +
                       File db;
      +  116  
                       try {
      -  116  0
                           db = new File(Settings.getDataDirectory(), "dc.h2.db");
      -  117  0
                           if (db.exists()) {
      -  118  0
                               if (db.delete()) {
      -  119  0
                                   LOGGER.info("Database file purged; local copy of the NVD has been removed");
      -  120   +  117  0
                           db = new File(Settings.getDataDirectory(), "dc.h2.db");
      +  118  0
                           if (db.exists()) {
      +  119  0
                               if (db.delete()) {
      +  120  0
                                   LOGGER.info("Database file purged; local copy of the NVD has been removed");
      +  121  
                               } else {
      -  121  0
                                   LOGGER.error("Unable to delete '{}'; please delete the file manually", db.getAbsolutePath());
      -  122  0
                                   exitCode = -5;
      -  123   -
                               }
      +  122  0
                                   LOGGER.error("Unable to delete '{}'; please delete the file manually", db.getAbsolutePath());
      +  123  0
                                   exitCode = -5;
       124   +
                               }
      +  125  
                           } else {
      -  125  0
                               LOGGER.error("Unable to purge database; the database file does not exists: {}", db.getAbsolutePath());
      -  126  0
                               exitCode = -6;
      -  127   +  126  0
                               LOGGER.error("Unable to purge database; the database file does not exists: {}", db.getAbsolutePath());
      +  127  0
                               exitCode = -6;
      +  128  
                           }
      -  128  0
                       } catch (IOException ex) {
      -  129  0
                           LOGGER.error("Unable to delete the database");
      -  130  0
                           exitCode = -7;
      -  131  0
                       }
      -  132   +  129  0
                       } catch (IOException ex) {
      +  130  0
                           LOGGER.error("Unable to delete the database");
      +  131  0
                           exitCode = -7;
      +  132  0
                       }
      +  133  
                   }
      -  133  0
               } else if (cli.isGetVersion()) {
      -  134  0
                   cli.printVersionInfo();
      -  135  0
               } else if (cli.isUpdateOnly()) {
      -  136   +  134  0
               } else if (cli.isGetVersion()) {
      +  135  0
                   cli.printVersionInfo();
      +  136  0
               } else if (cli.isUpdateOnly()) {
      +  137  
                   try {
      -  137  0
                       populateSettings(cli);
      -  138  0
                   } catch (InvalidSettingException ex) {
      -  139  0
                       LOGGER.error(ex.getMessage());
      -  140  0
                       LOGGER.debug("Error loading properties file", ex);
      -  141  0
                       exitCode = -4;
      -  142  0
                   }
      -  143   +  138  0
                       populateSettings(cli);
      +  139  0
                   } catch (InvalidSettingException ex) {
      +  140  0
                       LOGGER.error(ex.getMessage());
      +  141  0
                       LOGGER.debug("Error loading properties file", ex);
      +  142  0
                       exitCode = -4;
      +  143  0
                   }
      +  144  
                   try {
      -  144  0
                       runUpdateOnly();
      -  145  0
                   } catch (UpdateException ex) {
      -  146  0
                       LOGGER.error(ex.getMessage());
      -  147  0
                       exitCode = -8;
      -  148  0
                   } catch (DatabaseException ex) {
      -  149  0
                       LOGGER.error(ex.getMessage());
      -  150  0
                       exitCode = -9;
      -  151  0
                   }
      -  152  0
               } else if (cli.isRunScan()) {
      -  153   +  145  0
                       runUpdateOnly();
      +  146  0
                   } catch (UpdateException ex) {
      +  147  0
                       LOGGER.error(ex.getMessage());
      +  148  0
                       exitCode = -8;
      +  149  0
                   } catch (DatabaseException ex) {
      +  150  0
                       LOGGER.error(ex.getMessage());
      +  151  0
                       exitCode = -9;
      +  152  0
                   }
      +  153  0
               } else if (cli.isRunScan()) {
      +  154  
                   try {
      -  154  0
                       populateSettings(cli);
      -  155  0
                   } catch (InvalidSettingException ex) {
      -  156  0
                       LOGGER.error(ex.getMessage());
      -  157  0
                       LOGGER.debug("Error loading properties file", ex);
      -  158  0
                       exitCode = -4;
      -  159  0
                   }
      -  160   +  155  0
                       populateSettings(cli);
      +  156  0
                   } catch (InvalidSettingException ex) {
      +  157  0
                       LOGGER.error(ex.getMessage());
      +  158  0
                       LOGGER.debug("Error loading properties file", ex);
      +  159  0
                       exitCode = -4;
      +  160  0
                   }
      +  161  
                   try {
      -  161  0
                       final String[] scanFiles = cli.getScanFiles();
      -  162  0
                       if (scanFiles != null) {
      -  163  0
                           runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles,
      -  164  0
                                   cli.getExcludeList(), cli.getSymLinkDepth());
      -  165   +  162  0
                       final String[] scanFiles = cli.getScanFiles();
      +  163  0
                       if (scanFiles != null) {
      +  164  0
                           runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles,
      +  165  0
                                   cli.getExcludeList(), cli.getSymLinkDepth());
      +  166  
                       } else {
      -  166  0
                           LOGGER.error("No scan files configured");
      -  167   +  167  0
                           LOGGER.error("No scan files configured");
      +  168  
                       }
      -  168  0
                   } catch (InvalidScanPathException ex) {
      -  169  0
                       LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths");
      -  170  0
                       exitCode = -10;
      -  171  0
                   } catch (DatabaseException ex) {
      -  172  0
                       LOGGER.error(ex.getMessage());
      -  173  0
                       exitCode = -11;
      -  174  0
                   } catch (ReportException ex) {
      -  175  0
                       LOGGER.error(ex.getMessage());
      -  176  0
                       exitCode = -12;
      -  177  0
                   } catch (ExceptionCollection ex) {
      -  178  0
                       if (ex.isFatal()) {
      -  179  0
                           exitCode = -13;
      -  180  0
                           LOGGER.error("One or more fatal errors occured");
      -  181   +  169  0
                   } catch (InvalidScanPathException ex) {
      +  170  0
                       LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths");
      +  171  0
                       exitCode = -10;
      +  172  0
                   } catch (DatabaseException ex) {
      +  173  0
                       LOGGER.error(ex.getMessage());
      +  174  0
                       exitCode = -11;
      +  175  0
                   } catch (ReportException ex) {
      +  176  0
                       LOGGER.error(ex.getMessage());
      +  177  0
                       exitCode = -12;
      +  178  0
                   } catch (ExceptionCollection ex) {
      +  179  0
                       if (ex.isFatal()) {
      +  180  0
                           exitCode = -13;
      +  181  0
                           LOGGER.error("One or more fatal errors occurred");
      +  182  
                       } else {
      -  182  0
                           exitCode = -14;
      -  183   +  183  0
                           exitCode = -14;
      +  184  
                       }
      -  184  0
                       for (Throwable e : ex.getExceptions()) {
      -  185  0
                           LOGGER.error(e.getMessage());
      -  186  0
                       }
      -  187  0
                   }
      -  188   +  185  0
                       for (Throwable e : ex.getExceptions()) {
      +  186  0
                           LOGGER.error(e.getMessage());
      +  187  0
                       }
      +  188  0
                   }
      +  189  
               } else {
      -  189  0
                   cli.printHelp();
      -  190   +  190  0
                   cli.printHelp();
      +  191  
               }
      -  191  0
               return exitCode;
      -  192   -
           }
      +  192  0
               return exitCode;
       193   -
       
      +
           }
       194   -
           /**
      +
       
       195   -
            * Scans the specified directories and writes the dependency reports to the
      +
           /**
       196   -
            * reportDirectory.
      +
            * Scans the specified directories and writes the dependency reports to the
       197   -
            *
      +
            * reportDirectory.
       198   -
            * @param reportDirectory the path to the directory where the reports will
      +
            *
       199   -
            * be written
      +
            * @param reportDirectory the path to the directory where the reports will
       200   -
            * @param outputFormat the output format of the report
      +
            * be written
       201   -
            * @param applicationName the application name for the report
      +
            * @param outputFormat the output format of the report
       202   -
            * @param files the files/directories to scan
      +
            * @param applicationName the application name for the report
       203   -
            * @param excludes the patterns for files/directories to exclude
      +
            * @param files the files/directories to scan
       204   -
            * @param symLinkDepth the depth that symbolic links will be followed
      +
            * @param excludes the patterns for files/directories to exclude
       205   -
            *
      +
            * @param symLinkDepth the depth that symbolic links will be followed
       206   -
            * @throws InvalidScanPathException thrown if the path to scan starts with
      +
            *
       207   -
            * "//"
      +
            * @throws InvalidScanPathException thrown if the path to scan starts with
       208   -
            * @throws ReportException thrown when the report cannot be generated
      +
            * "//"
       209   -
            * @throws DatabaseException thrown when there is an error connecting to the
      +
            * @throws ReportException thrown when the report cannot be generated
       210   -
            * database
      +
            * @throws DatabaseException thrown when there is an error connecting to the
       211   -
            * @throws ExceptionCollection thrown when an exception occurs during
      +
            * database
       212   -
            * analysis; there may be multiple exceptions contained within the
      +
            * @throws ExceptionCollection thrown when an exception occurs during
       213   -
            * collection.
      +
            * analysis; there may be multiple exceptions contained within the
       214   -
            */
      +
            * collection.
       215   -
           private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
      +
            */
       216   +
           private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
      +  217  
                   String[] excludes, int symLinkDepth) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException {
      -  217  0
               Engine engine = null;
      -  218   +  218  0
               Engine engine = null;
      +  219  
               try {
      -  219  0
                   engine = new Engine();
      -  220  0
                   final List<String> antStylePaths = new ArrayList<String>();
      -  221  0
                   for (String file : files) {
      -  222  0
                       final String antPath = ensureCanonicalPath(file);
      -  223  0
                       antStylePaths.add(antPath);
      -  224   -
                   }
      +  220  0
                   engine = new Engine();
      +  221  0
                   final List<String> antStylePaths = new ArrayList<String>();
      +  222  0
                   for (String file : files) {
      +  223  0
                       final String antPath = ensureCanonicalPath(file);
      +  224  0
                       antStylePaths.add(antPath);
       225   +
                   }
      +  226  
       
      -  226  0
                   final Set<File> paths = new HashSet<File>();
      -  227  0
                   for (String file : antStylePaths) {
      -  228  0
                       LOGGER.debug("Scanning {}", file);
      -  229  0
                       final DirectoryScanner scanner = new DirectoryScanner();
      -  230  0
                       String include = file.replace('\\', '/');
      -  231   -
                       File baseDir;
      +  227  0
                   final Set<File> paths = new HashSet<File>();
      +  228  0
                   for (String file : antStylePaths) {
      +  229  0
                       LOGGER.debug("Scanning {}", file);
      +  230  0
                       final DirectoryScanner scanner = new DirectoryScanner();
      +  231  0
                       String include = file.replace('\\', '/');
       232   +
                       File baseDir;
      +  233  
       
      -  233  0
                       if (include.startsWith("//")) {
      -  234  0
                           throw new InvalidScanPathException("Unable to scan paths specified by //");
      -  235   +  234  0
                       if (include.startsWith("//")) {
      +  235  0
                           throw new InvalidScanPathException("Unable to scan paths specified by //");
      +  236  
                       } else {
      -  236  0
                           final int pos = getLastFileSeparator(include);
      -  237  0
                           final String tmpBase = include.substring(0, pos);
      -  238  0
                           final String tmpInclude = include.substring(pos + 1);
      -  239  0
                           if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0
      -  240  0
                                   || (new File(include)).isFile()) {
      -  241  0
                               baseDir = new File(tmpBase);
      -  242  0
                               include = tmpInclude;
      -  243   +  237  0
                           final int pos = getLastFileSeparator(include);
      +  238  0
                           final String tmpBase = include.substring(0, pos);
      +  239  0
                           final String tmpInclude = include.substring(pos + 1);
      +  240  0
                           if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0
      +  241  0
                                   || (new File(include)).isFile()) {
      +  242  0
                               baseDir = new File(tmpBase);
      +  243  0
                               include = tmpInclude;
      +  244  
                           } else {
      -  244  0
                               baseDir = new File(tmpBase, tmpInclude);
      -  245  0
                               include = "**/*";
      -  246   -
                           }
      +  245  0
                               baseDir = new File(tmpBase, tmpInclude);
      +  246  0
                               include = "**/*";
       247   -
                       }
      -  248  0
                       scanner.setBasedir(baseDir);
      -  249  0
                       final String[] includes = {include};
      -  250  0
                       scanner.setIncludes(includes);
      -  251  0
                       scanner.setMaxLevelsOfSymlinks(symLinkDepth);
      -  252  0
                       if (symLinkDepth <= 0) {
      -  253  0
                           scanner.setFollowSymlinks(false);
      -  254   -
                       }
      -  255  0
                       if (excludes != null && excludes.length > 0) {
      -  256  0
                           scanner.addExcludes(excludes);
      -  257   -
                       }
      -  258  0
                       scanner.scan();
      -  259  0
                       if (scanner.getIncludedFilesCount() > 0) {
      -  260  0
                           for (String s : scanner.getIncludedFiles()) {
      -  261  0
                               final File f = new File(baseDir, s);
      -  262  0
                               LOGGER.debug("Found file {}", f.toString());
      -  263  0
                               paths.add(f);
      -  264  
                           }
      +  248   +
                       }
      +  249  0
                       scanner.setBasedir(baseDir);
      +  250  0
                       final String[] includes = {include};
      +  251  0
                       scanner.setIncludes(includes);
      +  252  0
                       scanner.setMaxLevelsOfSymlinks(symLinkDepth);
      +  253  0
                       if (symLinkDepth <= 0) {
      +  254  0
                           scanner.setFollowSymlinks(false);
      +  255   +
                       }
      +  256  0
                       if (excludes != null && excludes.length > 0) {
      +  257  0
                           scanner.addExcludes(excludes);
      +  258   +
                       }
      +  259  0
                       scanner.scan();
      +  260  0
                       if (scanner.getIncludedFilesCount() > 0) {
      +  261  0
                           for (String s : scanner.getIncludedFiles()) {
      +  262  0
                               final File f = new File(baseDir, s);
      +  263  0
                               LOGGER.debug("Found file {}", f.toString());
      +  264  0
                               paths.add(f);
       265   +
                           }
      +  266  
                       }
      -  266  0
                   }
      -  267  0
                   engine.scan(paths);
      -  268   +  267  0
                   }
      +  268  0
                   engine.scan(paths);
      +  269  
       
      -  269  0
                   ExceptionCollection exCol = null;
      -  270   +  270  0
                   ExceptionCollection exCol = null;
      +  271  
                   try {
      -  271  0
                       engine.analyzeDependencies();
      -  272  0
                   } catch (ExceptionCollection ex) {
      -  273  0
                       if (ex.isFatal()) {
      -  274  0
                           throw ex;
      -  275   +  272  0
                       engine.analyzeDependencies();
      +  273  0
                   } catch (ExceptionCollection ex) {
      +  274  0
                       if (ex.isFatal()) {
      +  275  0
                           throw ex;
      +  276  
                       }
      -  276  0
                       exCol = ex;
      -  277  0
                   }
      -  278  0
                   final List<Dependency> dependencies = engine.getDependencies();
      -  279  0
                   DatabaseProperties prop = null;
      -  280  0
                   CveDB cve = null;
      -  281   +  277  0
                       exCol = ex;
      +  278  0
                   }
      +  279  0
                   final List<Dependency> dependencies = engine.getDependencies();
      +  280  0
                   DatabaseProperties prop = null;
      +  281  0
                   CveDB cve = null;
      +  282  
                   try {
      -  282  0
                       cve = new CveDB();
      -  283  0
                       cve.open();
      -  284  0
                       prop = cve.getDatabaseProperties();
      -  285   +  283  0
                       cve = new CveDB();
      +  284  0
                       cve.open();
      +  285  0
                       prop = cve.getDatabaseProperties();
      +  286  
                   } finally {
      -  286  0
                       if (cve != null) {
      -  287  0
                           cve.close();
      -  288   -
                       }
      +  287  0
                       if (cve != null) {
      +  288  0
                           cve.close();
       289   -
                   }
      -  290  0
                   final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
      -  291   -
                   try {
      -  292  0
                       report.generateReports(reportDirectory, outputFormat);
      -  293  0
                   } catch (ReportException ex) {
      -  294  0
                       if (exCol != null) {
      -  295  0
                           exCol.addException(ex);
      -  296  0
                           throw exCol;
      -  297   -
                       } else {
      -  298  0
                           throw ex;
      -  299  
                       }
      -  300  0
                   }
      -  301  0
                   if (exCol != null && exCol.getExceptions().size() > 0) {
      -  302  0
                       throw exCol;
      -  303   +  290  
                   }
      -  304   -
               } finally {
      -  305  0
                   if (engine != null) {
      -  306  0
                       engine.cleanup();
      -  307   -
                   }
      -  308   -
               }
      -  309   -
       
      -  310  0
           }
      -  311   -
       
      -  312   -
           /**
      -  313   -
            * Only executes the update phase of dependency-check.
      -  314   -
            *
      -  315   -
            * @throws UpdateException thrown if there is an error updating
      -  316   -
            * @throws DatabaseException thrown if a fatal error occurred and a
      -  317   -
            * connection to the database could not be established
      -  318   -
            */
      -  319   -
           private void runUpdateOnly() throws UpdateException, DatabaseException {
      -  320  0
               Engine engine = null;
      -  321   -
               try {
      -  322  0
                   engine = new Engine();
      -  323  0
                   engine.doUpdates();
      -  324   -
               } finally {
      -  325  0
                   if (engine != null) {
      -  326  0
                       engine.cleanup();
      -  327   -
                   }
      -  328   -
               }
      -  329  0
           }
      -  330   -
       
      -  331   -
           /**
      -  332   -
            * Updates the global Settings.
      -  333   -
            *
      -  334   -
            * @param cli a reference to the CLI Parser that contains the command line
      -  335   -
            * arguments used to set the corresponding settings in the core engine.
      -  336   -
            *
      -  337   -
            * @throws InvalidSettingException thrown when a user defined properties
      -  338   -
            * file is unable to be loaded.
      -  339   -
            */
      -  340   -
           private void populateSettings(CliParser cli) throws InvalidSettingException {
      -  341  0
               final boolean autoUpdate = cli.isAutoUpdate();
      -  342  0
               final String connectionTimeout = cli.getConnectionTimeout();
      -  343  0
               final String proxyServer = cli.getProxyServer();
      -  344  0
               final String proxyPort = cli.getProxyPort();
      -  345  0
               final String proxyUser = cli.getProxyUsername();
      -  346  0
               final String proxyPass = cli.getProxyPassword();
      -  347  0
               final String dataDirectory = cli.getDataDirectory();
      -  348  0
               final File propertiesFile = cli.getPropertiesFile();
      -  349  0
               final String suppressionFile = cli.getSuppressionFile();
      -  350  0
               final String nexusUrl = cli.getNexusUrl();
      -  351  0
               final String databaseDriverName = cli.getDatabaseDriverName();
      -  352  0
               final String databaseDriverPath = cli.getDatabaseDriverPath();
      -  353  0
               final String connectionString = cli.getConnectionString();
      -  354  0
               final String databaseUser = cli.getDatabaseUser();
      -  355  0
               final String databasePassword = cli.getDatabasePassword();
      -  356  0
               final String additionalZipExtensions = cli.getAdditionalZipExtensions();
      -  357  0
               final String pathToMono = cli.getPathToMono();
      -  358  0
               final String cveMod12 = cli.getModifiedCve12Url();
      -  359  0
               final String cveMod20 = cli.getModifiedCve20Url();
      -  360  0
               final String cveBase12 = cli.getBaseCve12Url();
      -  361  0
               final String cveBase20 = cli.getBaseCve20Url();
      -  362  0
               final Integer cveValidForHours = cli.getCveValidForHours();
      -  363  0
               final boolean experimentalEnabled = cli.isExperimentalEnabled();
      -  364   -
       
      -  365  0
               if (propertiesFile != null) {
      -  366   +  291  0
                   final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
      +  292  
                   try {
      -  367  0
                       Settings.mergeProperties(propertiesFile);
      -  368  0
                   } catch (FileNotFoundException ex) {
      -  369  0
                       throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex);
      -  370  0
                   } catch (IOException ex) {
      -  371  0
                       throw new InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex);
      -  372  0
                   }
      -  373   -
               }
      -  374   -
               // We have to wait until we've merged the properties before attempting to set whether we use
      -  375   -
               // the proxy for Nexus since it could be disabled in the properties, but not explicitly stated
      -  376   -
               // on the command line
      -  377  0
               final boolean nexusUsesProxy = cli.isNexusUsesProxy();
      -  378  0
               if (dataDirectory != null) {
      -  379  0
                   Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
      -  380  0
               } else if (System.getProperty("basedir") != null) {
      -  381  0
                   final File dataDir = new File(System.getProperty("basedir"), "data");
      -  382  0
                   Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
      -  383  0
               } else {
      -  384  0
                   final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath());
      -  385  0
                   final File base = jarPath.getParentFile();
      -  386  0
                   final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
      -  387  0
                   final File dataDir = new File(base, sub);
      -  388  0
                   Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
      -  389   -
               }
      -  390  0
               Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
      -  391  0
               Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer);
      -  392  0
               Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort);
      -  393  0
               Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser);
      -  394  0
               Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPass);
      -  395  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
      -  396  0
               Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
      -  397  0
               Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
      -  398   -
       
      -  399   -
               //File Type Analyzer Settings
      -  400  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled);
      -  401  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled());
      -  402  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled());
      -  403  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled());
      -  404  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !cli.isPythonPackageDisabled());
      -  405  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, !cli.isAutoconfDisabled());
      -  406  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, !cli.isCmakeDisabled());
      -  407  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !cli.isNuspecDisabled());
      -  408  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !cli.isAssemblyDisabled());
      -  409  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, !cli.isBundleAuditDisabled());
      -  410  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, !cli.isOpenSSLDisabled());
      -  411  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, !cli.isComposerDisabled());
      -  412  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, !cli.isNodeJsDisabled());
      -  413  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, !cli.isRubyGemspecDisabled());
      -  414  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !cli.isCentralDisabled());
      -  415  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !cli.isNexusDisabled());
      -  416   -
       
      -  417  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, cli.getPathToBundleAudit());
      -  418  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
      -  419  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
      -  420  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
      -  421  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
      -  422  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
      -  423  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
      -  424  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
      -  425  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
      -  426  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
      -  427  0
               if (cveBase12 != null && !cveBase12.isEmpty()) {
      -  428  0
                   Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveBase12);
      -  429  0
                   Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveBase20);
      -  430  0
                   Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveMod12);
      -  431  0
                   Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveMod20);
      -  432   -
               }
      -  433  0
           }
      -  434   -
       
      -  435   -
           /**
      -  436   -
            * Creates a file appender and adds it to logback.
      -  437   -
            *
      -  438   -
            * @param verboseLog the path to the verbose log file
      -  439   -
            */
      -  440   -
           private void prepareLogger(String verboseLog) {
      -  441  0
               final StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton();
      -  442  0
               final LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory();
      -  443   -
       
      -  444  0
               final PatternLayoutEncoder encoder = new PatternLayoutEncoder();
      -  445  0
               encoder.setPattern("%d %C:%L%n%-5level - %msg%n");
      -  446  0
               encoder.setContext(context);
      -  447  0
               encoder.start();
      -  448  0
               final FileAppender fa = new FileAppender();
      -  449  0
               fa.setAppend(true);
      -  450  0
               fa.setEncoder(encoder);
      -  451  0
               fa.setContext(context);
      -  452  0
               fa.setFile(verboseLog);
      -  453  0
               final File f = new File(verboseLog);
      -  454  0
               String name = f.getName();
      -  455  0
               final int i = name.lastIndexOf('.');
      -  456  0
               if (i > 1) {
      -  457  0
                   name = name.substring(0, i);
      -  458   -
               }
      -  459  0
               fa.setName(name);
      -  460  0
               fa.start();
      -  461  0
               final ch.qos.logback.classic.Logger rootLogger = context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
      -  462  0
               rootLogger.addAppender(fa);
      -  463  0
           }
      -  464   -
       
      -  465   -
           /**
      -  466   -
            * Takes a path and resolves it to be a canonical &amp; absolute path. The
      -  467   -
            * caveats are that this method will take an Ant style file selector path
      -  468   -
            * (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at
      -  469   -
            * least to the left of the first * or ?).
      -  470   -
            *
      -  471   -
            * @param path the path to canonicalize
      -  472   -
            * @return the canonical path
      -  473   -
            */
      -  474   -
           protected String ensureCanonicalPath(String path) {
      -  475   -
               String basePath;
      -  476  2
               String wildCards = null;
      -  477  2
               final String file = path.replace('\\', '/');
      -  478  2
               if (file.contains("*") || file.contains("?")) {
      -  479   -
       
      -  480  1
                   int pos = getLastFileSeparator(file);
      -  481  1
                   if (pos < 0) {
      -  482  0
                       return file;
      -  483   +  293  0
                       report.generateReports(reportDirectory, outputFormat);
      +  294  0
                   } catch (ReportException ex) {
      +  295  0
                       if (exCol != null) {
      +  296  0
                           exCol.addException(ex);
      +  297  0
                           throw exCol;
      +  298   +
                       } else {
      +  299  0
                           throw ex;
      +  300   +
                       }
      +  301  0
                   }
      +  302  0
                   if (exCol != null && exCol.getExceptions().size() > 0) {
      +  303  0
                       throw exCol;
      +  304  
                   }
      -  484  1
                   pos += 1;
      -  485  1
                   basePath = file.substring(0, pos);
      -  486  1
                   wildCards = file.substring(pos);
      -  487  1
               } else {
      -  488  1
                   basePath = file;
      -  489   +  305   +
               } finally {
      +  306  0
                   if (engine != null) {
      +  307  0
                       engine.cleanup();
      +  308   +
                   }
      +  309  
               }
      -  490   +  310  
       
      -  491  2
               File f = new File(basePath);
      -  492   +  311  0
           }
      +  312   +
       
      +  313   +
           /**
      +  314   +
            * Only executes the update phase of dependency-check.
      +  315   +
            *
      +  316   +
            * @throws UpdateException thrown if there is an error updating
      +  317   +
            * @throws DatabaseException thrown if a fatal error occurred and a
      +  318   +
            * connection to the database could not be established
      +  319   +
            */
      +  320   +
           private void runUpdateOnly() throws UpdateException, DatabaseException {
      +  321  0
               Engine engine = null;
      +  322  
               try {
      -  493  2
                   f = f.getCanonicalFile();
      -  494  2
                   if (wildCards != null) {
      -  495  1
                       f = new File(f, wildCards);
      -  496   +  323  0
                   engine = new Engine();
      +  324  0
                   engine.doUpdates();
      +  325   +
               } finally {
      +  326  0
                   if (engine != null) {
      +  327  0
                       engine.cleanup();
      +  328  
                   }
      -  497  0
               } catch (IOException ex) {
      -  498  0
                   LOGGER.warn("Invalid path '{}' was provided.", path);
      -  499  0
                   LOGGER.debug("Invalid path provided", ex);
      -  500  2
               }
      -  501  2
               return f.getAbsolutePath().replace('\\', '/');
      -  502   -
           }
      -  503   -
       
      -  504   -
           /**
      -  505   -
            * Returns the position of the last file separator.
      -  506   -
            *
      -  507   -
            * @param file a file path
      -  508   -
            * @return the position of the last file separator
      -  509   -
            */
      -  510   -
           private int getLastFileSeparator(String file) {
      -  511  1
               if (file.contains("*") || file.contains("?")) {
      -  512  1
                   int p1 = file.indexOf('*');
      -  513  1
                   int p2 = file.indexOf('?');
      -  514  1
                   p1 = p1 > 0 ? p1 : file.length();
      -  515  1
                   p2 = p2 > 0 ? p2 : file.length();
      -  516  1
                   int pos = p1 < p2 ? p1 : p2;
      -  517  1
                   pos = file.lastIndexOf('/', pos);
      -  518  1
                   return pos;
      -  519   -
               } else {
      -  520  0
                   return file.lastIndexOf('/');
      -  521   +  329  
               }
      -  522   +  330  0
           }
      +  331   +
       
      +  332   +
           /**
      +  333   +
            * Updates the global Settings.
      +  334   +
            *
      +  335   +
            * @param cli a reference to the CLI Parser that contains the command line
      +  336   +
            * arguments used to set the corresponding settings in the core engine.
      +  337   +
            *
      +  338   +
            * @throws InvalidSettingException thrown when a user defined properties
      +  339   +
            * file is unable to be loaded.
      +  340   +
            */
      +  341   +
           private void populateSettings(CliParser cli) throws InvalidSettingException {
      +  342  0
               final boolean autoUpdate = cli.isAutoUpdate();
      +  343  0
               final String connectionTimeout = cli.getConnectionTimeout();
      +  344  0
               final String proxyServer = cli.getProxyServer();
      +  345  0
               final String proxyPort = cli.getProxyPort();
      +  346  0
               final String proxyUser = cli.getProxyUsername();
      +  347  0
               final String proxyPass = cli.getProxyPassword();
      +  348  0
               final String dataDirectory = cli.getDataDirectory();
      +  349  0
               final File propertiesFile = cli.getPropertiesFile();
      +  350  0
               final String suppressionFile = cli.getSuppressionFile();
      +  351  0
               final String hintsFile = cli.getHintsFile();
      +  352  0
               final String nexusUrl = cli.getNexusUrl();
      +  353  0
               final String databaseDriverName = cli.getDatabaseDriverName();
      +  354  0
               final String databaseDriverPath = cli.getDatabaseDriverPath();
      +  355  0
               final String connectionString = cli.getConnectionString();
      +  356  0
               final String databaseUser = cli.getDatabaseUser();
      +  357  0
               final String databasePassword = cli.getDatabasePassword();
      +  358  0
               final String additionalZipExtensions = cli.getAdditionalZipExtensions();
      +  359  0
               final String pathToMono = cli.getPathToMono();
      +  360  0
               final String cveMod12 = cli.getModifiedCve12Url();
      +  361  0
               final String cveMod20 = cli.getModifiedCve20Url();
      +  362  0
               final String cveBase12 = cli.getBaseCve12Url();
      +  363  0
               final String cveBase20 = cli.getBaseCve20Url();
      +  364  0
               final Integer cveValidForHours = cli.getCveValidForHours();
      +  365  0
               final boolean experimentalEnabled = cli.isExperimentalEnabled();
      +  366   +
       
      +  367  0
               if (propertiesFile != null) {
      +  368   +
                   try {
      +  369  0
                       Settings.mergeProperties(propertiesFile);
      +  370  0
                   } catch (FileNotFoundException ex) {
      +  371  0
                       throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex);
      +  372  0
                   } catch (IOException ex) {
      +  373  0
                       throw new InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex);
      +  374  0
                   }
      +  375   +
               }
      +  376   +
               // We have to wait until we've merged the properties before attempting to set whether we use
      +  377   +
               // the proxy for Nexus since it could be disabled in the properties, but not explicitly stated
      +  378   +
               // on the command line
      +  379  0
               final boolean nexusUsesProxy = cli.isNexusUsesProxy();
      +  380  0
               if (dataDirectory != null) {
      +  381  0
                   Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
      +  382  0
               } else if (System.getProperty("basedir") != null) {
      +  383  0
                   final File dataDir = new File(System.getProperty("basedir"), "data");
      +  384  0
                   Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
      +  385  0
               } else {
      +  386  0
                   final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath());
      +  387  0
                   final File base = jarPath.getParentFile();
      +  388  0
                   final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
      +  389  0
                   final File dataDir = new File(base, sub);
      +  390  0
                   Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
      +  391   +
               }
      +  392  0
               Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
      +  393  0
               Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer);
      +  394  0
               Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort);
      +  395  0
               Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser);
      +  396  0
               Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPass);
      +  397  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
      +  398  0
               Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
      +  399  0
               Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile);
      +  400  0
               Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
      +  401   +
       
      +  402   +
               //File Type Analyzer Settings
      +  403  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled);
      +  404  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled());
      +  405  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled());
      +  406  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled());
      +  407  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !cli.isPythonPackageDisabled());
      +  408  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, !cli.isAutoconfDisabled());
      +  409  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, !cli.isCmakeDisabled());
      +  410  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !cli.isNuspecDisabled());
      +  411  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !cli.isAssemblyDisabled());
      +  412  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, !cli.isBundleAuditDisabled());
      +  413  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, !cli.isOpenSSLDisabled());
      +  414  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, !cli.isComposerDisabled());
      +  415  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, !cli.isNodeJsDisabled());
      +  416  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, !cli.isRubyGemspecDisabled());
      +  417  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !cli.isCentralDisabled());
      +  418  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !cli.isNexusDisabled());
      +  419   +
       
      +  420  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, cli.getPathToBundleAudit());
      +  421  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
      +  422  0
               Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
      +  423  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
      +  424  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
      +  425  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
      +  426  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
      +  427  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
      +  428  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
      +  429  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
      +  430  0
               if (cveBase12 != null && !cveBase12.isEmpty()) {
      +  431  0
                   Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveBase12);
      +  432  0
                   Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveBase20);
      +  433  0
                   Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveMod12);
      +  434  0
                   Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveMod20);
      +  435   +
               }
      +  436  0
           }
      +  437   +
       
      +  438   +
           /**
      +  439   +
            * Creates a file appender and adds it to logback.
      +  440   +
            *
      +  441   +
            * @param verboseLog the path to the verbose log file
      +  442   +
            */
      +  443   +
           private void prepareLogger(String verboseLog) {
      +  444  0
               final StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton();
      +  445  0
               final LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory();
      +  446   +
       
      +  447  0
               final PatternLayoutEncoder encoder = new PatternLayoutEncoder();
      +  448  0
               encoder.setPattern("%d %C:%L%n%-5level - %msg%n");
      +  449  0
               encoder.setContext(context);
      +  450  0
               encoder.start();
      +  451  0
               final FileAppender<ILoggingEvent> fa = new FileAppender<ILoggingEvent>();
      +  452  0
               fa.setAppend(true);
      +  453  0
               fa.setEncoder(encoder);
      +  454  0
               fa.setContext(context);
      +  455  0
               fa.setFile(verboseLog);
      +  456  0
               final File f = new File(verboseLog);
      +  457  0
               String name = f.getName();
      +  458  0
               final int i = name.lastIndexOf('.');
      +  459  0
               if (i > 1) {
      +  460  0
                   name = name.substring(0, i);
      +  461   +
               }
      +  462  0
               fa.setName(name);
      +  463  0
               fa.start();
      +  464  0
               final ch.qos.logback.classic.Logger rootLogger = context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
      +  465  0
               rootLogger.addAppender(fa);
      +  466  0
           }
      +  467   +
       
      +  468   +
           /**
      +  469   +
            * Takes a path and resolves it to be a canonical &amp; absolute path. The
      +  470   +
            * caveats are that this method will take an Ant style file selector path
      +  471   +
            * (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at
      +  472   +
            * least to the left of the first * or ?).
      +  473   +
            *
      +  474   +
            * @param path the path to canonicalize
      +  475   +
            * @return the canonical path
      +  476   +
            */
      +  477   +
           protected String ensureCanonicalPath(String path) {
      +  478   +
               String basePath;
      +  479  2
               String wildCards = null;
      +  480  2
               final String file = path.replace('\\', '/');
      +  481  2
               if (file.contains("*") || file.contains("?")) {
      +  482   +
       
      +  483  1
                   int pos = getLastFileSeparator(file);
      +  484  1
                   if (pos < 0) {
      +  485  0
                       return file;
      +  486   +
                   }
      +  487  1
                   pos += 1;
      +  488  1
                   basePath = file.substring(0, pos);
      +  489  1
                   wildCards = file.substring(pos);
      +  490  1
               } else {
      +  491  1
                   basePath = file;
      +  492   +
               }
      +  493   +
       
      +  494  2
               File f = new File(basePath);
      +  495   +
               try {
      +  496  2
                   f = f.getCanonicalFile();
      +  497  2
                   if (wildCards != null) {
      +  498  1
                       f = new File(f, wildCards);
      +  499   +
                   }
      +  500  0
               } catch (IOException ex) {
      +  501  0
                   LOGGER.warn("Invalid path '{}' was provided.", path);
      +  502  0
                   LOGGER.debug("Invalid path provided", ex);
      +  503  2
               }
      +  504  2
               return f.getAbsolutePath().replace('\\', '/');
      +  505  
           }
      -  523   +  506   +
       
      +  507   +
           /**
      +  508   +
            * Returns the position of the last file separator.
      +  509   +
            *
      +  510   +
            * @param file a file path
      +  511   +
            * @return the position of the last file separator
      +  512   +
            */
      +  513   +
           private int getLastFileSeparator(String file) {
      +  514  1
               if (file.contains("*") || file.contains("?")) {
      +  515  1
                   int p1 = file.indexOf('*');
      +  516  1
                   int p2 = file.indexOf('?');
      +  517  1
                   p1 = p1 > 0 ? p1 : file.length();
      +  518  1
                   p2 = p2 > 0 ? p2 : file.length();
      +  519  1
                   int pos = p1 < p2 ? p1 : p2;
      +  520  1
                   pos = file.lastIndexOf('/', pos);
      +  521  1
                   return pos;
      +  522   +
               } else {
      +  523  0
                   return file.lastIndexOf('/');
      +  524   +
               }
      +  525   +
           }
      +  526  
       }
      - + diff --git a/dependency-check-cli/cobertura/org.owasp.dependencycheck.CliParser.html b/dependency-check-cli/cobertura/org.owasp.dependencycheck.CliParser.html index aeb3abc8e..ad0859937 100644 --- a/dependency-check-cli/cobertura/org.owasp.dependencycheck.CliParser.html +++ b/dependency-check-cli/cobertura/org.owasp.dependencycheck.CliParser.html @@ -12,8 +12,8 @@
       
      - - + +
      Classes in this File Line Coverage Branch Coverage Complexity
      CliParser
      70%
      261/369
      24%
      46/188
      2.492
      CliParser$ARGUMENT
      0%
      0/1
      N/A
      2.492
      CliParser
      70%
      265/374
      24%
      46/188
      2.469
      CliParser$ARGUMENT
      0%
      0/1
      N/A
      2.469
       
      @@ -464,1978 +464,2011 @@  278  11
                       .build();
       279  
       
      -  280  11
               final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS)
      -  281  11
                       .desc("The number of hours to wait before checking for new updates from the NVD.")
      +  280  11
               final Option hintsFile = Option.builder().argName("file").hasArg().longOpt(ARGUMENT.HINTS_FILE)
      +  281  11
                       .desc("The file path to the hints XML file.")
       282  11
                       .build();
       283  
       
      -  284  11
               final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL)
      -  285  11
                       .desc("Enables the experimental analzers.")
      +  284  11
               final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS)
      +  285  11
                       .desc("The number of hours to wait before checking for new updates from the NVD.")
       286  11
                       .build();
       287  
       
      -  288   -
               //This is an option group because it can be specified more then once.
      -  289  11
               final OptionGroup og = new OptionGroup();
      -  290  11
               og.addOption(path);
      +  288  11
               final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL)
      +  289  11
                       .desc("Enables the experimental analzers.")
      +  290  11
                       .build();
       291  
       
      -  292  11
               final OptionGroup exog = new OptionGroup();
      -  293  11
               exog.addOption(excludes);
      -  294   +  292   +
               //This is an option group because it can be specified more then once.
      +  293  11
               final OptionGroup og = new OptionGroup();
      +  294  11
               og.addOption(path);
      +  295  
       
      -  295  11
               options.addOptionGroup(og)
      -  296  11
                       .addOptionGroup(exog)
      -  297  11
                       .addOption(projectName)
      -  298  11
                       .addOption(out)
      -  299  11
                       .addOption(outputFormat)
      -  300  11
                       .addOption(version)
      -  301  11
                       .addOption(help)
      -  302  11
                       .addOption(advancedHelp)
      -  303  11
                       .addOption(noUpdate)
      -  304  11
                       .addOption(symLinkDepth)
      -  305  11
                       .addOption(props)
      -  306  11
                       .addOption(verboseLog)
      -  307  11
                       .addOption(suppressionFile)
      -  308  11
                       .addOption(cveValidForHours)
      -  309  11
                       .addOption(experimentalEnabled);
      -  310  11
           }
      -  311   +  296  11
               final OptionGroup exog = new OptionGroup();
      +  297  11
               exog.addOption(excludes);
      +  298  
       
      -  312   -
           /**
      -  313   -
            * Adds the advanced command line options to the given options collection.
      -  314   -
            * These are split out for purposes of being able to display two different
      -  315   -
            * help messages.
      +  299  11
               options.addOptionGroup(og)
      +  300  11
                       .addOptionGroup(exog)
      +  301  11
                       .addOption(projectName)
      +  302  11
                       .addOption(out)
      +  303  11
                       .addOption(outputFormat)
      +  304  11
                       .addOption(version)
      +  305  11
                       .addOption(help)
      +  306  11
                       .addOption(advancedHelp)
      +  307  11
                       .addOption(noUpdate)
      +  308  11
                       .addOption(symLinkDepth)
      +  309  11
                       .addOption(props)
      +  310  11
                       .addOption(verboseLog)
      +  311  11
                       .addOption(suppressionFile)
      +  312  11
                       .addOption(hintsFile)
      +  313  11
                       .addOption(cveValidForHours)
      +  314  11
                       .addOption(experimentalEnabled);
      +  315  11
           }
       316   -
            *
      +
       
       317   -
            * @param options a collection of command line arguments
      +
           /**
       318   -
            * @throws IllegalArgumentException thrown if there is an exception
      +
            * Adds the advanced command line options to the given options collection.
       319   -
            */
      +
            * These are split out for purposes of being able to display two different
       320   -
           @SuppressWarnings("static-access")
      +
            * help messages.
       321   -
           private void addAdvancedOptions(final Options options) throws IllegalArgumentException {
      +
            *
       322   -
       
      -  323  9
               final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12)
      -  324  9
                       .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ")
      -  325  9
                       .build();
      +
            * @param options a collection of command line arguments
      +  323   +
            * @throws IllegalArgumentException thrown if there is an exception
      +  324   +
            */
      +  325   +
           @SuppressWarnings("static-access")
       326   +
           private void addAdvancedOptions(final Options options) throws IllegalArgumentException {
      +  327  
       
      -  327  9
               final Option cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20)
      -  328  9
                       .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.")
      -  329  9
                       .build();
      -  330   +  328  9
               final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12)
      +  329  9
                       .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ")
      +  330  9
                       .build();
      +  331  
       
      -  331  9
               final Option cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12)
      -  332  9
                       .desc("URL for the modified CVE 1.2.")
      -  333  9
                       .build();
      -  334   +  332  9
               final Option cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20)
      +  333  9
                       .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.")
      +  334  9
                       .build();
      +  335  
       
      -  335  9
               final Option cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20)
      -  336  9
                       .desc("URL for the modified CVE 2.0.")
      -  337  9
                       .build();
      -  338   +  336  9
               final Option cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12)
      +  337  9
                       .desc("URL for the modified CVE 1.2.")
      +  338  9
                       .build();
      +  339  
       
      -  339  9
               final Option updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY)
      -  340  9
                       .desc("Only update the local NVD data cache; no scan will be executed.").build();
      -  341   +  340  9
               final Option cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20)
      +  341  9
                       .desc("URL for the modified CVE 2.0.")
      +  342  9
                       .build();
      +  343  
       
      -  342  9
               final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY)
      -  343  9
                       .desc("The location of the H2 Database file. This option should generally not be set.")
      -  344  9
                       .build();
      -  345   +  344  9
               final Option updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY)
      +  345  9
                       .desc("Only update the local NVD data cache; no scan will be executed.").build();
      +  346  
       
      -  346  9
               final Option nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL)
      -  347  9
                       .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). "
      -  348  9
                               + "If not set the Nexus Analyzer will be disabled.").build();
      -  349   +  347  9
               final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY)
      +  348  9
                       .desc("The location of the H2 Database file. This option should generally not be set.")
      +  349  9
                       .build();
      +  350  
       
      -  350  9
               final Option nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY)
      -  351  9
                       .desc("Whether or not the configured proxy should be used when connecting to Nexus.")
      -  352  9
                       .build();
      -  353   +  351  9
               final Option nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL)
      +  352  9
                       .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). "
      +  353  9
                               + "If not set the Nexus Analyzer will be disabled.").build();
      +  354  
       
      -  354  9
               final Option additionalZipExtensions = Option.builder().argName("extensions").hasArg()
      -  355  9
                       .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS)
      -  356  9
                       .desc("A comma separated list of additional extensions to be scanned as ZIP files "
      -  357  9
                               + "(ZIP, EAR, WAR are already treated as zip files)").build();
      +  355  9
               final Option nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY)
      +  356  9
                       .desc("Whether or not the configured proxy should be used when connecting to Nexus.")
      +  357  9
                       .build();
       358  
       
      -  359  9
               final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO)
      -  360  9
                       .desc("The path to Mono for .NET Assembly analysis on non-windows systems.")
      -  361  9
                       .build();
      -  362   +  359  9
               final Option additionalZipExtensions = Option.builder().argName("extensions").hasArg()
      +  360  9
                       .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS)
      +  361  9
                       .desc("A comma separated list of additional extensions to be scanned as ZIP files "
      +  362  9
                               + "(ZIP, EAR, WAR are already treated as zip files)").build();
      +  363  
       
      -  363  9
               final Option pathToBundleAudit = Option.builder().argName("path").hasArg()
      -  364  9
                       .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT)
      -  365  9
                       .desc("The path to bundle-audit for Gem bundle analysis.").build();
      -  366   +  364  9
               final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO)
      +  365  9
                       .desc("The path to Mono for .NET Assembly analysis on non-windows systems.")
      +  366  9
                       .build();
      +  367  
       
      -  367  9
               final Option connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg()
      -  368  9
                       .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.")
      -  369  9
                       .build();
      -  370   +  368  9
               final Option pathToBundleAudit = Option.builder().argName("path").hasArg()
      +  369  9
                       .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT)
      +  370  9
                       .desc("The path to bundle-audit for Gem bundle analysis.").build();
      +  371  
       
      -  371  9
               final Option proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER)
      -  372  9
                       .desc("The proxy server to use when downloading resources.").build();
      -  373   +  372  9
               final Option connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg()
      +  373  9
                       .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.")
      +  374  9
                       .build();
      +  375  
       
      -  374  9
               final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT)
      -  375  9
                       .desc("The proxy port to use when downloading resources.").build();
      -  376   +  376  9
               final Option proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER)
      +  377  9
                       .desc("The proxy server to use when downloading resources.").build();
      +  378  
       
      -  377  9
               final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME)
      -  378  9
                       .desc("The proxy username to use when downloading resources.").build();
      -  379   +  379  9
               final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT)
      +  380  9
                       .desc("The proxy port to use when downloading resources.").build();
      +  381  
       
      -  380  9
               final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD)
      -  381  9
                       .desc("The proxy password to use when downloading resources.").build();
      -  382   +  382  9
               final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME)
      +  383  9
                       .desc("The proxy username to use when downloading resources.").build();
      +  384  
       
      -  383  9
               final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING)
      -  384  9
                       .desc("The connection string to the database.").build();
      -  385   +  385  9
               final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD)
      +  386  9
                       .desc("The proxy password to use when downloading resources.").build();
      +  387  
       
      -  386  9
               final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME)
      -  387  9
                       .desc("The username used to connect to the database.").build();
      -  388   +  388  9
               final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING)
      +  389  9
                       .desc("The connection string to the database.").build();
      +  390  
       
      -  389  9
               final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD)
      -  390  9
                       .desc("The password for connecting to the database.").build();
      -  391   +  391  9
               final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME)
      +  392  9
                       .desc("The username used to connect to the database.").build();
      +  393  
       
      -  392  9
               final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER)
      -  393  9
                       .desc("The database driver name.").build();
      -  394   +  394  9
               final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD)
      +  395  9
                       .desc("The password for connecting to the database.").build();
      +  396  
       
      -  395  9
               final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH)
      -  396  9
                       .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.")
      -  397  9
                       .build();
      -  398   +  397  9
               final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER)
      +  398  9
                       .desc("The database driver name.").build();
      +  399  
       
      -  399  9
               final Option disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR)
      -  400  9
                       .desc("Disable the Jar Analyzer.").build();
      -  401   +  400  9
               final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH)
      +  401  9
                       .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.")
      +  402  9
                       .build();
      +  403  
       
      -  402  9
               final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE)
      -  403  9
                       .desc("Disable the Archive Analyzer.").build();
      -  404   +  404  9
               final Option disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR)
      +  405  9
                       .desc("Disable the Jar Analyzer.").build();
      +  406  
       
      -  405  9
               final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC)
      -  406  9
                       .desc("Disable the Nuspec Analyzer.").build();
      -  407   +  407  9
               final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE)
      +  408  9
                       .desc("Disable the Archive Analyzer.").build();
      +  409  
       
      -  408  9
               final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY)
      -  409  9
                       .desc("Disable the .NET Assembly Analyzer.").build();
      -  410   +  410  9
               final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC)
      +  411  9
                       .desc("Disable the Nuspec Analyzer.").build();
      +  412  
       
      -  411  9
               final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST)
      -  412  9
                       .desc("Disable the Python Distribution Analyzer.").build();
      -  413   +  413  9
               final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY)
      +  414  9
                       .desc("Disable the .NET Assembly Analyzer.").build();
      +  415  
       
      -  414  9
               final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG)
      -  415  9
                       .desc("Disable the Python Package Analyzer.").build();
      -  416   +  416  9
               final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST)
      +  417  9
                       .desc("Disable the Python Distribution Analyzer.").build();
      +  418  
       
      -  417  9
               final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER)
      -  418  9
                       .desc("Disable the PHP Composer Analyzer.").build();
      -  419   +  419  9
               final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG)
      +  420  9
                       .desc("Disable the Python Package Analyzer.").build();
      +  421  
       
      -  420  9
               final Option disableAutoconfAnalyzer = Option.builder()
      -  421  9
                       .longOpt(ARGUMENT.DISABLE_AUTOCONF)
      -  422  9
                       .desc("Disable the Autoconf Analyzer.").build();
      -  423   +  422  9
               final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER)
      +  423  9
                       .desc("Disable the PHP Composer Analyzer.").build();
      +  424  
       
      -  424  9
               final Option disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL)
      -  425  9
                       .desc("Disable the OpenSSL Analyzer.").build();
      -  426  9
               final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE)
      -  427  9
                       .desc("Disable the Cmake Analyzer.").build();
      +  425  9
               final Option disableAutoconfAnalyzer = Option.builder()
      +  426  9
                       .longOpt(ARGUMENT.DISABLE_AUTOCONF)
      +  427  9
                       .desc("Disable the Autoconf Analyzer.").build();
       428  
       
      -  429  9
               final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL)
      -  430  9
                       .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable "
      -  431  9
                               + "the Nexus Analyzer.").build();
      -  432   +  429  9
               final Option disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL)
      +  430  9
                       .desc("Disable the OpenSSL Analyzer.").build();
      +  431  9
               final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE)
      +  432  9
                       .desc("Disable the Cmake Analyzer.").build();
      +  433  
       
      -  433  9
               final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS)
      -  434  9
                       .desc("Disable the Nexus Analyzer.").build();
      -  435   +  434  9
               final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL)
      +  435  9
                       .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable "
      +  436  9
                               + "the Nexus Analyzer.").build();
      +  437  
       
      -  436  9
               final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD)
      -  437  9
                       .desc("Purges the local NVD data cache")
      -  438  9
                       .build();
      -  439   +  438  9
               final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS)
      +  439  9
                       .desc("Disable the Nexus Analyzer.").build();
      +  440  
       
      -  440  9
               options.addOption(updateOnly)
      -  441  9
                       .addOption(cve12Base)
      -  442  9
                       .addOption(cve20Base)
      -  443  9
                       .addOption(cve12Modified)
      -  444  9
                       .addOption(cve20Modified)
      -  445  9
                       .addOption(proxyPort)
      -  446  9
                       .addOption(proxyServer)
      -  447  9
                       .addOption(proxyUsername)
      -  448  9
                       .addOption(proxyPassword)
      -  449  9
                       .addOption(connectionTimeout)
      -  450  9
                       .addOption(connectionString)
      -  451  9
                       .addOption(dbUser)
      -  452  9
                       .addOption(data)
      -  453  9
                       .addOption(dbPassword)
      -  454  9
                       .addOption(dbDriver)
      -  455  9
                       .addOption(dbDriverPath)
      -  456  9
                       .addOption(disableJarAnalyzer)
      -  457  9
                       .addOption(disableArchiveAnalyzer)
      -  458  9
                       .addOption(disableAssemblyAnalyzer)
      -  459  9
                       .addOption(pathToBundleAudit)
      -  460  9
                       .addOption(disablePythonDistributionAnalyzer)
      -  461  9
                       .addOption(disableCmakeAnalyzer)
      -  462  9
                       .addOption(disablePythonPackageAnalyzer)
      -  463  18
                       .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS)
      -  464  9
                               .desc("Disable the Ruby Gemspec Analyzer.").build())
      -  465  18
                       .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT)
      -  466  9
                               .desc("Disable the Ruby Bundler-Audit Analyzer.").build())
      -  467  9
                       .addOption(disableAutoconfAnalyzer)
      -  468  9
                       .addOption(disableComposerAnalyzer)
      -  469  9
                       .addOption(disableOpenSSLAnalyzer)
      -  470  9
                       .addOption(disableNuspecAnalyzer)
      -  471  9
                       .addOption(disableCentralAnalyzer)
      -  472  9
                       .addOption(disableNexusAnalyzer)
      -  473  18
                       .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS)
      -  474  9
                               .desc("Disable the Node.js Package Analyzer.").build())
      -  475  9
                       .addOption(nexusUrl)
      -  476  9
                       .addOption(nexusUsesProxy)
      -  477  9
                       .addOption(additionalZipExtensions)
      -  478  9
                       .addOption(pathToMono)
      -  479  9
                       .addOption(pathToBundleAudit)
      -  480  9
                       .addOption(purge);
      -  481  9
           }
      -  482   +  441  9
               final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD)
      +  442  9
                       .desc("Purges the local NVD data cache")
      +  443  9
                       .build();
      +  444  
       
      -  483   -
           /**
      -  484   -
            * Adds the deprecated command line options to the given options collection.
      -  485   -
            * These are split out for purposes of not including them in the help
      -  486   -
            * message. We need to add the deprecated options so as not to break
      +  445  9
               options.addOption(updateOnly)
      +  446  9
                       .addOption(cve12Base)
      +  447  9
                       .addOption(cve20Base)
      +  448  9
                       .addOption(cve12Modified)
      +  449  9
                       .addOption(cve20Modified)
      +  450  9
                       .addOption(proxyPort)
      +  451  9
                       .addOption(proxyServer)
      +  452  9
                       .addOption(proxyUsername)
      +  453  9
                       .addOption(proxyPassword)
      +  454  9
                       .addOption(connectionTimeout)
      +  455  9
                       .addOption(connectionString)
      +  456  9
                       .addOption(dbUser)
      +  457  9
                       .addOption(data)
      +  458  9
                       .addOption(dbPassword)
      +  459  9
                       .addOption(dbDriver)
      +  460  9
                       .addOption(dbDriverPath)
      +  461  9
                       .addOption(disableJarAnalyzer)
      +  462  9
                       .addOption(disableArchiveAnalyzer)
      +  463  9
                       .addOption(disableAssemblyAnalyzer)
      +  464  9
                       .addOption(pathToBundleAudit)
      +  465  9
                       .addOption(disablePythonDistributionAnalyzer)
      +  466  9
                       .addOption(disableCmakeAnalyzer)
      +  467  9
                       .addOption(disablePythonPackageAnalyzer)
      +  468  18
                       .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS)
      +  469  9
                               .desc("Disable the Ruby Gemspec Analyzer.").build())
      +  470  18
                       .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT)
      +  471  9
                               .desc("Disable the Ruby Bundler-Audit Analyzer.").build())
      +  472  9
                       .addOption(disableAutoconfAnalyzer)
      +  473  9
                       .addOption(disableComposerAnalyzer)
      +  474  9
                       .addOption(disableOpenSSLAnalyzer)
      +  475  9
                       .addOption(disableNuspecAnalyzer)
      +  476  9
                       .addOption(disableCentralAnalyzer)
      +  477  9
                       .addOption(disableNexusAnalyzer)
      +  478  18
                       .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS)
      +  479  9
                               .desc("Disable the Node.js Package Analyzer.").build())
      +  480  9
                       .addOption(nexusUrl)
      +  481  9
                       .addOption(nexusUsesProxy)
      +  482  9
                       .addOption(additionalZipExtensions)
      +  483  9
                       .addOption(pathToMono)
      +  484  9
                       .addOption(pathToBundleAudit)
      +  485  9
                       .addOption(purge);
      +  486  9
           }
       487   -
            * existing scripts.
      +
       
       488   -
            *
      +
           /**
       489   -
            * @param options a collection of command line arguments
      +
            * Adds the deprecated command line options to the given options collection.
       490   -
            * @throws IllegalArgumentException thrown if there is an exception
      +
            * These are split out for purposes of not including them in the help
       491   -
            */
      +
            * message. We need to add the deprecated options so as not to break
       492   -
           @SuppressWarnings({"static-access", "deprecation"})
      +
            * existing scripts.
       493   -
           private void addDeprecatedOptions(final Options options) throws IllegalArgumentException {
      +
            *
       494   +
            * @param options a collection of command line arguments
      +  495   +
            * @throws IllegalArgumentException thrown if there is an exception
      +  496   +
            */
      +  497   +
           @SuppressWarnings({"static-access", "deprecation"})
      +  498   +
           private void addDeprecatedOptions(final Options options) throws IllegalArgumentException {
      +  499  
       
      -  495  9
               final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL)
      -  496  9
                       .desc("The proxy url argument is deprecated, use proxyserver instead.")
      -  497  9
                       .build();
      -  498  9
               final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME)
      -  499  9
                       .desc("The name of the project being scanned.")
      -  500  9
                       .build();
      -  501   -
       
      -  502  9
               options.addOption(proxyServer);
      -  503  9
               options.addOption(appName);
      -  504  9
           }
      -  505   -
       
      +  500  9
               final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL)
      +  501  9
                       .desc("The proxy url argument is deprecated, use proxyserver instead.")
      +  502  9
                       .build();
      +  503  9
               final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME)
      +  504  9
                       .desc("The name of the project being scanned.")
      +  505  9
                       .build();
       506   -
           /**
      -  507   -
            * Determines if the 'version' command line argument was passed in.
      -  508   -
            *
      -  509   -
            * @return whether or not the 'version' command line argument was passed in
      +
       
      +  507  9
               options.addOption(proxyServer);
      +  508  9
               options.addOption(appName);
      +  509  9
           }
       510   -
            */
      +
       
       511   -
           public boolean isGetVersion() {
      -  512  7
               return (line != null) && line.hasOption(ARGUMENT.VERSION);
      +
           /**
      +  512   +
            * Determines if the 'version' command line argument was passed in.
       513   -
           }
      +
            *
       514   -
       
      +
            * @return whether or not the 'version' command line argument was passed in
       515   -
           /**
      +
            */
       516   -
            * Determines if the 'help' command line argument was passed in.
      -  517   -
            *
      +
           public boolean isGetVersion() {
      +  517  7
               return (line != null) && line.hasOption(ARGUMENT.VERSION);
       518   -
            * @return whether or not the 'help' command line argument was passed in
      +
           }
       519   -
            */
      +
       
       520   -
           public boolean isGetHelp() {
      -  521  7
               return (line != null) && line.hasOption(ARGUMENT.HELP);
      +
           /**
      +  521   +
            * Determines if the 'help' command line argument was passed in.
       522   -
           }
      +
            *
       523   -
       
      +
            * @return whether or not the 'help' command line argument was passed in
       524   -
           /**
      +
            */
       525   -
            * Determines if the 'scan' command line argument was passed in.
      -  526   -
            *
      +
           public boolean isGetHelp() {
      +  526  7
               return (line != null) && line.hasOption(ARGUMENT.HELP);
       527   -
            * @return whether or not the 'scan' command line argument was passed in
      +
           }
       528   -
            */
      +
       
       529   -
           public boolean isRunScan() {
      -  530  21
               return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN);
      +
           /**
      +  530   +
            * Determines if the 'scan' command line argument was passed in.
       531   -
           }
      +
            *
       532   -
       
      +
            * @return whether or not the 'scan' command line argument was passed in
       533   -
           /**
      +
            */
       534   -
            * Returns the symbolic link depth (how deeply symbolic links will be
      -  535   -
            * followed).
      +
           public boolean isRunScan() {
      +  535  21
               return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN);
       536   -
            *
      +
           }
       537   -
            * @return the symbolic link depth
      +
       
       538   -
            */
      +
           /**
       539   -
           public int getSymLinkDepth() {
      -  540  0
               int value = 0;
      +
            * Returns the symbolic link depth (how deeply symbolic links will be
      +  540   +
            * followed).
       541   +
            *
      +  542   +
            * @return the symbolic link depth
      +  543   +
            */
      +  544   +
           public int getSymLinkDepth() {
      +  545  0
               int value = 0;
      +  546  
               try {
      -  542  0
                   value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0"));
      -  543  0
                   if (value < 0) {
      -  544  0
                       value = 0;
      -  545   -
                   }
      -  546  0
               } catch (NumberFormatException ex) {
      -  547  0
                   LOGGER.debug("Symbolic link was not a number");
      -  548  0
               }
      -  549  0
               return value;
      +  547  0
                   value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0"));
      +  548  0
                   if (value < 0) {
      +  549  0
                       value = 0;
       550   -
           }
      -  551   -
       
      -  552   -
           /**
      -  553   -
            * Returns true if the disableJar command line argument was specified.
      -  554   -
            *
      +
                   }
      +  551  0
               } catch (NumberFormatException ex) {
      +  552  0
                   LOGGER.debug("Symbolic link was not a number");
      +  553  0
               }
      +  554  0
               return value;
       555   -
            * @return true if the disableJar command line argument was specified;
      +
           }
       556   -
            * otherwise false
      +
       
       557   -
            */
      +
           /**
       558   -
           public boolean isJarDisabled() {
      -  559  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
      +
            * Returns true if the disableJar command line argument was specified.
      +  559   +
            *
       560   -
           }
      +
            * @return true if the disableJar command line argument was specified;
       561   -
       
      +
            * otherwise false
       562   -
           /**
      +
            */
       563   -
            * Returns true if the disableArchive command line argument was specified.
      -  564   -
            *
      +
           public boolean isJarDisabled() {
      +  564  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
       565   -
            * @return true if the disableArchive command line argument was specified;
      +
           }
       566   -
            * otherwise false
      +
       
       567   -
            */
      +
           /**
       568   -
           public boolean isArchiveDisabled() {
      -  569  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
      +
            * Returns true if the disableArchive command line argument was specified.
      +  569   +
            *
       570   -
           }
      +
            * @return true if the disableArchive command line argument was specified;
       571   -
       
      +
            * otherwise false
       572   -
           /**
      +
            */
       573   -
            * Returns true if the disableNuspec command line argument was specified.
      -  574   -
            *
      +
           public boolean isArchiveDisabled() {
      +  574  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
       575   -
            * @return true if the disableNuspec command line argument was specified;
      +
           }
       576   -
            * otherwise false
      +
       
       577   -
            */
      +
           /**
       578   -
           public boolean isNuspecDisabled() {
      -  579  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
      +
            * Returns true if the disableNuspec command line argument was specified.
      +  579   +
            *
       580   -
           }
      +
            * @return true if the disableNuspec command line argument was specified;
       581   -
       
      +
            * otherwise false
       582   -
           /**
      +
            */
       583   -
            * Returns true if the disableAssembly command line argument was specified.
      -  584   -
            *
      +
           public boolean isNuspecDisabled() {
      +  584  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
       585   -
            * @return true if the disableAssembly command line argument was specified;
      +
           }
       586   -
            * otherwise false
      +
       
       587   -
            */
      +
           /**
       588   -
           public boolean isAssemblyDisabled() {
      -  589  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
      +
            * Returns true if the disableAssembly command line argument was specified.
      +  589   +
            *
       590   -
           }
      +
            * @return true if the disableAssembly command line argument was specified;
       591   -
       
      +
            * otherwise false
       592   -
           /**
      +
            */
       593   -
            * Returns true if the disableBundleAudit command line argument was
      -  594   -
            * specified.
      +
           public boolean isAssemblyDisabled() {
      +  594  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
       595   -
            *
      +
           }
       596   -
            * @return true if the disableBundleAudit command line argument was
      +
       
       597   -
            * specified; otherwise false
      +
           /**
       598   -
            */
      +
            * Returns true if the disableBundleAudit command line argument was
       599   -
           public boolean isBundleAuditDisabled() {
      -  600  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT);
      +
            * specified.
      +  600   +
            *
       601   -
           }
      +
            * @return true if the disableBundleAudit command line argument was
       602   -
       
      +
            * specified; otherwise false
       603   -
           /**
      +
            */
       604   -
            * Returns true if the disablePyDist command line argument was specified.
      -  605   -
            *
      +
           public boolean isBundleAuditDisabled() {
      +  605  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT);
       606   -
            * @return true if the disablePyDist command line argument was specified;
      +
           }
       607   -
            * otherwise false
      +
       
       608   -
            */
      +
           /**
       609   -
           public boolean isPythonDistributionDisabled() {
      -  610  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
      +
            * Returns true if the disablePyDist command line argument was specified.
      +  610   +
            *
       611   -
           }
      +
            * @return true if the disablePyDist command line argument was specified;
       612   -
       
      +
            * otherwise false
       613   -
           /**
      +
            */
       614   -
            * Returns true if the disablePyPkg command line argument was specified.
      -  615   -
            *
      +
           public boolean isPythonDistributionDisabled() {
      +  615  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
       616   -
            * @return true if the disablePyPkg command line argument was specified;
      +
           }
       617   -
            * otherwise false
      +
       
       618   -
            */
      +
           /**
       619   -
           public boolean isPythonPackageDisabled() {
      -  620  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
      +
            * Returns true if the disablePyPkg command line argument was specified.
      +  620   +
            *
       621   -
           }
      +
            * @return true if the disablePyPkg command line argument was specified;
       622   -
       
      +
            * otherwise false
       623   -
           /**
      +
            */
       624   -
            * Returns whether the Ruby gemspec analyzer is disabled.
      -  625   -
            *
      +
           public boolean isPythonPackageDisabled() {
      +  625  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
       626   -
            * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line
      +
           }
       627   -
            * argument was specified; otherwise false
      +
       
       628   -
            */
      +
           /**
       629   -
           public boolean isRubyGemspecDisabled() {
      -  630  0
               return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS);
      +
            * Returns whether the Ruby gemspec analyzer is disabled.
      +  630   +
            *
       631   -
           }
      +
            * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line
       632   -
       
      +
            * argument was specified; otherwise false
       633   -
           /**
      +
            */
       634   -
            * Returns true if the disableCmake command line argument was specified.
      -  635   -
            *
      +
           public boolean isRubyGemspecDisabled() {
      +  635  0
               return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS);
       636   -
            * @return true if the disableCmake command line argument was specified;
      +
           }
       637   -
            * otherwise false
      +
       
       638   -
            */
      +
           /**
       639   -
           public boolean isCmakeDisabled() {
      -  640  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE);
      +
            * Returns true if the disableCmake command line argument was specified.
      +  640   +
            *
       641   -
           }
      +
            * @return true if the disableCmake command line argument was specified;
       642   -
       
      +
            * otherwise false
       643   -
           /**
      +
            */
       644   -
            * Returns true if the disableAutoconf command line argument was specified.
      -  645   -
            *
      +
           public boolean isCmakeDisabled() {
      +  645  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE);
       646   -
            * @return true if the disableAutoconf command line argument was specified;
      +
           }
       647   -
            * otherwise false
      +
       
       648   -
            */
      +
           /**
       649   -
           public boolean isAutoconfDisabled() {
      -  650  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
      +
            * Returns true if the disableAutoconf command line argument was specified.
      +  650   +
            *
       651   -
           }
      +
            * @return true if the disableAutoconf command line argument was specified;
       652   -
       
      +
            * otherwise false
       653   -
           /**
      +
            */
       654   -
            * Returns true if the disableComposer command line argument was specified.
      -  655   -
            *
      +
           public boolean isAutoconfDisabled() {
      +  655  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
       656   -
            * @return true if the disableComposer command line argument was specified;
      +
           }
       657   -
            * otherwise false
      +
       
       658   -
            */
      +
           /**
       659   -
           public boolean isComposerDisabled() {
      -  660  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER);
      +
            * Returns true if the disableComposer command line argument was specified.
      +  660   +
            *
       661   -
           }
      +
            * @return true if the disableComposer command line argument was specified;
       662   -
       
      +
            * otherwise false
       663   -
           /**
      +
            */
       664   -
            * Returns true if the disableNexus command line argument was specified.
      -  665   -
            *
      +
           public boolean isComposerDisabled() {
      +  665  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER);
       666   -
            * @return true if the disableNexus command line argument was specified;
      +
           }
       667   -
            * otherwise false
      +
       
       668   -
            */
      +
           /**
       669   -
           public boolean isNexusDisabled() {
      -  670  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
      +
            * Returns true if the disableNexus command line argument was specified.
      +  670   +
            *
       671   -
           }
      +
            * @return true if the disableNexus command line argument was specified;
       672   -
       
      +
            * otherwise false
       673   -
           /**
      +
            */
       674   -
            * Returns true if the disableOpenSSL command line argument was specified.
      -  675   -
            *
      +
           public boolean isNexusDisabled() {
      +  675  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
       676   -
            * @return true if the disableOpenSSL command line argument was specified;
      +
           }
       677   -
            * otherwise false
      +
       
       678   -
            */
      +
           /**
       679   -
           public boolean isOpenSSLDisabled() {
      -  680  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL);
      +
            * Returns true if the disableOpenSSL command line argument was specified.
      +  680   +
            *
       681   -
           }
      +
            * @return true if the disableOpenSSL command line argument was specified;
       682   -
       
      +
            * otherwise false
       683   -
           /**
      +
            */
       684   -
            * Returns true if the disableNodeJS command line argument was specified.
      -  685   -
            *
      +
           public boolean isOpenSSLDisabled() {
      +  685  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL);
       686   -
            * @return true if the disableNodeJS command line argument was specified;
      +
           }
       687   -
            * otherwise false
      +
       
       688   -
            */
      +
           /**
       689   -
           public boolean isNodeJsDisabled() {
      -  690  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS);
      +
            * Returns true if the disableNodeJS command line argument was specified.
      +  690   +
            *
       691   -
           }
      +
            * @return true if the disableNodeJS command line argument was specified;
       692   -
       
      -  693   -
           /**
      -  694   -
            * Returns true if the disableCentral command line argument was specified.
      -  695   -
            *
      -  696   -
            * @return true if the disableCentral command line argument was specified;
      -  697  
            * otherwise false
      +  693   +
            */
      +  694   +
           public boolean isNodeJsDisabled() {
      +  695  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS);
      +  696   +
           }
      +  697   +
       
       698   -
            */
      +
           /**
       699   -
           public boolean isCentralDisabled() {
      -  700  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
      +
            * Returns true if the disableCentral command line argument was specified.
      +  700   +
            *
       701   -
           }
      +
            * @return true if the disableCentral command line argument was specified;
       702   -
       
      +
            * otherwise false
       703   -
           /**
      +
            */
       704   -
            * Returns the url to the nexus server if one was specified.
      -  705   -
            *
      +
           public boolean isCentralDisabled() {
      +  705  0
               return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
       706   -
            * @return the url to the nexus server; if none was specified this will
      +
           }
       707   -
            * return null;
      +
       
       708   -
            */
      +
           /**
       709   -
           public String getNexusUrl() {
      -  710  0
               if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) {
      -  711  0
                   return null;
      +
            * Returns the url to the nexus server if one was specified.
      +  710   +
            *
      +  711   +
            * @return the url to the nexus server; if none was specified this will
       712   -
               } else {
      -  713  0
                   return line.getOptionValue(ARGUMENT.NEXUS_URL);
      +
            * return null;
      +  713   +
            */
       714   -
               }
      -  715   -
           }
      -  716   -
       
      +
           public String getNexusUrl() {
      +  715  0
               if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) {
      +  716  0
                   return null;
       717   -
           /**
      -  718   -
            * Returns true if the Nexus Analyzer should use the configured proxy to
      -  719   -
            * connect to Nexus; otherwise false is returned.
      -  720   -
            *
      -  721   -
            * @return true if the Nexus Analyzer should use the configured proxy to
      -  722   -
            * connect to Nexus; otherwise false
      -  723   -
            */
      -  724   -
           public boolean isNexusUsesProxy() {
      -  725   -
               // If they didn't specify whether Nexus needs to use the proxy, we should
      -  726   -
               // still honor the property if it's set.
      -  727  0
               if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) {
      -  728   -
                   try {
      -  729  0
                       return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
      -  730  0
                   } catch (InvalidSettingException ise) {
      -  731  0
                       return true;
      -  732   -
                   }
      -  733  
               } else {
      -  734  0
                   return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY));
      -  735   +  718  0
                   return line.getOptionValue(ARGUMENT.NEXUS_URL);
      +  719  
               }
      -  736   +  720  
           }
      +  721   +
       
      +  722   +
           /**
      +  723   +
            * Returns true if the Nexus Analyzer should use the configured proxy to
      +  724   +
            * connect to Nexus; otherwise false is returned.
      +  725   +
            *
      +  726   +
            * @return true if the Nexus Analyzer should use the configured proxy to
      +  727   +
            * connect to Nexus; otherwise false
      +  728   +
            */
      +  729   +
           public boolean isNexusUsesProxy() {
      +  730   +
               // If they didn't specify whether Nexus needs to use the proxy, we should
      +  731   +
               // still honor the property if it's set.
      +  732  0
               if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) {
      +  733   +
                   try {
      +  734  0
                       return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
      +  735  0
                   } catch (InvalidSettingException ise) {
      +  736  0
                       return true;
       737   -
       
      -  738   -
           /**
      -  739   -
            * Displays the command line help message to the standard output.
      -  740   -
            */
      -  741   -
           public void printHelp() {
      -  742  2
               final HelpFormatter formatter = new HelpFormatter();
      -  743  2
               final Options options = new Options();
      -  744  2
               addStandardOptions(options);
      -  745  2
               if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) {
      -  746  0
                   addAdvancedOptions(options);
      -  747   -
               }
      -  748  4
               final String helpMsg = String.format("%n%s"
      -  749   -
                       + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
      -  750   -
                       + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
      -  751  2
                       Settings.getString("application.name", "DependencyCheck"),
      -  752  2
                       Settings.getString("application.name", "DependencyCheck"));
      -  753   -
       
      -  754  2
               formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
      -  755   -
                       helpMsg,
      -  756   -
                       options,
      -  757   -
                       "",
      -  758   -
                       true);
      -  759  2
           }
      -  760   -
       
      -  761   -
           /**
      -  762   -
            * Retrieves the file command line parameter(s) specified for the 'scan'
      -  763   -
            * argument.
      -  764   -
            *
      -  765   -
            * @return the file paths specified on the command line for scan
      -  766   -
            */
      -  767   -
           public String[] getScanFiles() {
      -  768  3
               return line.getOptionValues(ARGUMENT.SCAN);
      -  769   -
           }
      -  770   -
       
      -  771   -
           /**
      -  772   -
            * Retrieves the list of excluded file patterns specified by the 'exclude'
      -  773   -
            * argument.
      -  774   -
            *
      -  775   -
            * @return the excluded file patterns
      -  776   -
            */
      -  777   -
           public String[] getExcludeList() {
      -  778  0
               return line.getOptionValues(ARGUMENT.EXCLUDE);
      -  779   -
           }
      -  780   -
       
      -  781   -
           /**
      -  782   -
            * Returns the directory to write the reports to specified on the command
      -  783   -
            * line.
      -  784   -
            *
      -  785   -
            * @return the path to the reports directory.
      -  786   -
            */
      -  787   -
           public String getReportDirectory() {
      -  788  1
               return line.getOptionValue(ARGUMENT.OUT, ".");
      -  789   -
           }
      -  790   -
       
      -  791   -
           /**
      -  792   -
            * Returns the path to Mono for .NET Assembly analysis on non-windows
      -  793   -
            * systems.
      -  794   -
            *
      -  795   -
            * @return the path to Mono
      -  796   -
            */
      -  797   -
           public String getPathToMono() {
      -  798  1
               return line.getOptionValue(ARGUMENT.PATH_TO_MONO);
      -  799   -
           }
      -  800   -
       
      -  801   -
           /**
      -  802   -
            * Returns the path to bundle-audit for Ruby bundle analysis.
      -  803   -
            *
      -  804   -
            * @return the path to Mono
      -  805   -
            */
      -  806   -
           public String getPathToBundleAudit() {
      -  807  0
               return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT);
      -  808   -
           }
      -  809   -
       
      -  810   -
           /**
      -  811   -
            * Returns the output format specified on the command line. Defaults to HTML
      -  812   -
            * if no format was specified.
      -  813   -
            *
      -  814   -
            * @return the output format name.
      -  815   -
            */
      -  816   -
           public String getReportFormat() {
      -  817  1
               return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML");
      -  818   -
           }
      -  819   -
       
      -  820   -
           /**
      -  821   -
            * Returns the application name specified on the command line.
      -  822   -
            *
      -  823   -
            * @return the application name.
      -  824   -
            */
      -  825   -
           public String getProjectName() {
      -  826  0
               final String appName = line.getOptionValue(ARGUMENT.APP_NAME);
      -  827  0
               String name = line.getOptionValue(ARGUMENT.PROJECT);
      -  828  0
               if (name == null && appName != null) {
      -  829  0
                   name = appName;
      -  830  0
                   LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead.");
      -  831   -
               }
      -  832  0
               return name;
      -  833   -
           }
      -  834   -
       
      -  835   -
           /**
      -  836   -
            * Returns the base URL for the CVE 1.2 XMl file.
      -  837   -
            *
      -  838   -
            * @return the URL to the CVE 1.2 XML file.
      -  839   -
            */
      -  840   -
           public String getBaseCve12Url() {
      -  841  1
               return line.getOptionValue(ARGUMENT.CVE_BASE_12);
      -  842   -
           }
      -  843   -
       
      -  844   -
           /**
      -  845   -
            * Returns the base URL for the CVE 2.0 XMl file.
      -  846   -
            *
      -  847   -
            * @return the URL to the CVE 2.0 XML file.
      -  848   -
            */
      -  849   -
           public String getBaseCve20Url() {
      -  850  1
               return line.getOptionValue(ARGUMENT.CVE_BASE_20);
      -  851   -
           }
      -  852   -
       
      -  853   -
           /**
      -  854   -
            * Returns the URL for the modified CVE 1.2 XMl file.
      -  855   -
            *
      -  856   -
            * @return the URL to the modified CVE 1.2 XML file.
      -  857   -
            */
      -  858   -
           public String getModifiedCve12Url() {
      -  859  1
               return line.getOptionValue(ARGUMENT.CVE_MOD_12);
      -  860   -
           }
      -  861   -
       
      -  862   -
           /**
      -  863   -
            * Returns the URL for the modified CVE 2.0 XMl file.
      -  864   -
            *
      -  865   -
            * @return the URL to the modified CVE 2.0 XML file.
      -  866   -
            */
      -  867   -
           public String getModifiedCve20Url() {
      -  868  1
               return line.getOptionValue(ARGUMENT.CVE_MOD_20);
      -  869   -
           }
      -  870   -
       
      -  871   -
           /**
      -  872   -
            * Returns the connection timeout.
      -  873   -
            *
      -  874   -
            * @return the connection timeout
      -  875   -
            */
      -  876   -
           public String getConnectionTimeout() {
      -  877  0
               return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT);
      -  878   -
           }
      -  879   -
       
      -  880   -
           /**
      -  881   -
            * Returns the proxy server.
      -  882   -
            *
      -  883   -
            * @return the proxy server
      -  884   -
            */
      -  885   -
           @SuppressWarnings("deprecation")
      -  886   -
           public String getProxyServer() {
      -  887   -
       
      -  888  0
               String server = line.getOptionValue(ARGUMENT.PROXY_SERVER);
      -  889  0
               if (server == null) {
      -  890  0
                   server = line.getOptionValue(ARGUMENT.PROXY_URL);
      -  891  0
                   if (server != null) {
      -  892  0
                       LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead");
      -  893  
                   }
      -  894   +  738   +
               } else {
      +  739  0
                   return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY));
      +  740  
               }
      -  895  0
               return server;
      -  896   +  741  
           }
      -  897   +  742  
       
      +  743   +
           /**
      +  744   +
            * Displays the command line help message to the standard output.
      +  745   +
            */
      +  746   +
           public void printHelp() {
      +  747  2
               final HelpFormatter formatter = new HelpFormatter();
      +  748  2
               final Options options = new Options();
      +  749  2
               addStandardOptions(options);
      +  750  2
               if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) {
      +  751  0
                   addAdvancedOptions(options);
      +  752   +
               }
      +  753  4
               final String helpMsg = String.format("%n%s"
      +  754   +
                       + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
      +  755   +
                       + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
      +  756  2
                       Settings.getString("application.name", "DependencyCheck"),
      +  757  2
                       Settings.getString("application.name", "DependencyCheck"));
      +  758   +
       
      +  759  2
               formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
      +  760   +
                       helpMsg,
      +  761   +
                       options,
      +  762   +
                       "",
      +  763   +
                       true);
      +  764  2
           }
      +  765   +
       
      +  766   +
           /**
      +  767   +
            * Retrieves the file command line parameter(s) specified for the 'scan'
      +  768   +
            * argument.
      +  769   +
            *
      +  770   +
            * @return the file paths specified on the command line for scan
      +  771   +
            */
      +  772   +
           public String[] getScanFiles() {
      +  773  3
               return line.getOptionValues(ARGUMENT.SCAN);
      +  774   +
           }
      +  775   +
       
      +  776   +
           /**
      +  777   +
            * Retrieves the list of excluded file patterns specified by the 'exclude'
      +  778   +
            * argument.
      +  779   +
            *
      +  780   +
            * @return the excluded file patterns
      +  781   +
            */
      +  782   +
           public String[] getExcludeList() {
      +  783  0
               return line.getOptionValues(ARGUMENT.EXCLUDE);
      +  784   +
           }
      +  785   +
       
      +  786   +
           /**
      +  787   +
            * Returns the directory to write the reports to specified on the command
      +  788   +
            * line.
      +  789   +
            *
      +  790   +
            * @return the path to the reports directory.
      +  791   +
            */
      +  792   +
           public String getReportDirectory() {
      +  793  1
               return line.getOptionValue(ARGUMENT.OUT, ".");
      +  794   +
           }
      +  795   +
       
      +  796   +
           /**
      +  797   +
            * Returns the path to Mono for .NET Assembly analysis on non-windows
      +  798   +
            * systems.
      +  799   +
            *
      +  800   +
            * @return the path to Mono
      +  801   +
            */
      +  802   +
           public String getPathToMono() {
      +  803  1
               return line.getOptionValue(ARGUMENT.PATH_TO_MONO);
      +  804   +
           }
      +  805   +
       
      +  806   +
           /**
      +  807   +
            * Returns the path to bundle-audit for Ruby bundle analysis.
      +  808   +
            *
      +  809   +
            * @return the path to Mono
      +  810   +
            */
      +  811   +
           public String getPathToBundleAudit() {
      +  812  0
               return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT);
      +  813   +
           }
      +  814   +
       
      +  815   +
           /**
      +  816   +
            * Returns the output format specified on the command line. Defaults to HTML
      +  817   +
            * if no format was specified.
      +  818   +
            *
      +  819   +
            * @return the output format name.
      +  820   +
            */
      +  821   +
           public String getReportFormat() {
      +  822  1
               return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML");
      +  823   +
           }
      +  824   +
       
      +  825   +
           /**
      +  826   +
            * Returns the application name specified on the command line.
      +  827   +
            *
      +  828   +
            * @return the application name.
      +  829   +
            */
      +  830   +
           public String getProjectName() {
      +  831  0
               final String appName = line.getOptionValue(ARGUMENT.APP_NAME);
      +  832  0
               String name = line.getOptionValue(ARGUMENT.PROJECT);
      +  833  0
               if (name == null && appName != null) {
      +  834  0
                   name = appName;
      +  835  0
                   LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead.");
      +  836   +
               }
      +  837  0
               return name;
      +  838   +
           }
      +  839   +
       
      +  840   +
           /**
      +  841   +
            * Returns the base URL for the CVE 1.2 XMl file.
      +  842   +
            *
      +  843   +
            * @return the URL to the CVE 1.2 XML file.
      +  844   +
            */
      +  845   +
           public String getBaseCve12Url() {
      +  846  1
               return line.getOptionValue(ARGUMENT.CVE_BASE_12);
      +  847   +
           }
      +  848   +
       
      +  849   +
           /**
      +  850   +
            * Returns the base URL for the CVE 2.0 XMl file.
      +  851   +
            *
      +  852   +
            * @return the URL to the CVE 2.0 XML file.
      +  853   +
            */
      +  854   +
           public String getBaseCve20Url() {
      +  855  1
               return line.getOptionValue(ARGUMENT.CVE_BASE_20);
      +  856   +
           }
      +  857   +
       
      +  858   +
           /**
      +  859   +
            * Returns the URL for the modified CVE 1.2 XMl file.
      +  860   +
            *
      +  861   +
            * @return the URL to the modified CVE 1.2 XML file.
      +  862   +
            */
      +  863   +
           public String getModifiedCve12Url() {
      +  864  1
               return line.getOptionValue(ARGUMENT.CVE_MOD_12);
      +  865   +
           }
      +  866   +
       
      +  867   +
           /**
      +  868   +
            * Returns the URL for the modified CVE 2.0 XMl file.
      +  869   +
            *
      +  870   +
            * @return the URL to the modified CVE 2.0 XML file.
      +  871   +
            */
      +  872   +
           public String getModifiedCve20Url() {
      +  873  1
               return line.getOptionValue(ARGUMENT.CVE_MOD_20);
      +  874   +
           }
      +  875   +
       
      +  876   +
           /**
      +  877   +
            * Returns the connection timeout.
      +  878   +
            *
      +  879   +
            * @return the connection timeout
      +  880   +
            */
      +  881   +
           public String getConnectionTimeout() {
      +  882  0
               return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT);
      +  883   +
           }
      +  884   +
       
      +  885   +
           /**
      +  886   +
            * Returns the proxy server.
      +  887   +
            *
      +  888   +
            * @return the proxy server
      +  889   +
            */
      +  890   +
           @SuppressWarnings("deprecation")
      +  891   +
           public String getProxyServer() {
      +  892   +
       
      +  893  0
               String server = line.getOptionValue(ARGUMENT.PROXY_SERVER);
      +  894  0
               if (server == null) {
      +  895  0
                   server = line.getOptionValue(ARGUMENT.PROXY_URL);
      +  896  0
                   if (server != null) {
      +  897  0
                       LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead");
       898   -
           /**
      +
                   }
       899   -
            * Returns the proxy port.
      -  900   -
            *
      -  901   -
            * @return the proxy port
      -  902   -
            */
      -  903   -
           public String getProxyPort() {
      -  904  0
               return line.getOptionValue(ARGUMENT.PROXY_PORT);
      -  905   -
           }
      -  906   -
       
      -  907   -
           /**
      -  908   -
            * Returns the proxy username.
      -  909   -
            *
      -  910   -
            * @return the proxy username
      -  911   -
            */
      -  912   -
           public String getProxyUsername() {
      -  913  0
               return line.getOptionValue(ARGUMENT.PROXY_USERNAME);
      -  914   -
           }
      -  915   -
       
      -  916   -
           /**
      -  917   -
            * Returns the proxy password.
      -  918   -
            *
      -  919   -
            * @return the proxy password
      -  920   -
            */
      -  921   -
           public String getProxyPassword() {
      -  922  0
               return line.getOptionValue(ARGUMENT.PROXY_PASSWORD);
      -  923   -
           }
      -  924   -
       
      -  925   -
           /**
      -  926   -
            * Get the value of dataDirectory.
      -  927   -
            *
      -  928   -
            * @return the value of dataDirectory
      -  929   -
            */
      -  930   -
           public String getDataDirectory() {
      -  931  0
               return line.getOptionValue(ARGUMENT.DATA_DIRECTORY);
      -  932   -
           }
      -  933   -
       
      -  934   -
           /**
      -  935   -
            * Returns the properties file specified on the command line.
      -  936   -
            *
      -  937   -
            * @return the properties file specified on the command line
      -  938   -
            */
      -  939   -
           public File getPropertiesFile() {
      -  940  0
               final String path = line.getOptionValue(ARGUMENT.PROP);
      -  941  0
               if (path != null) {
      -  942  0
                   return new File(path);
      -  943  
               }
      -  944  0
               return null;
      -  945   +  900  0
               return server;
      +  901  
           }
      -  946   +  902  
       
      -  947   +  903  
           /**
      +  904   +
            * Returns the proxy port.
      +  905   +
            *
      +  906   +
            * @return the proxy port
      +  907   +
            */
      +  908   +
           public String getProxyPort() {
      +  909  0
               return line.getOptionValue(ARGUMENT.PROXY_PORT);
      +  910   +
           }
      +  911   +
       
      +  912   +
           /**
      +  913   +
            * Returns the proxy username.
      +  914   +
            *
      +  915   +
            * @return the proxy username
      +  916   +
            */
      +  917   +
           public String getProxyUsername() {
      +  918  0
               return line.getOptionValue(ARGUMENT.PROXY_USERNAME);
      +  919   +
           }
      +  920   +
       
      +  921   +
           /**
      +  922   +
            * Returns the proxy password.
      +  923   +
            *
      +  924   +
            * @return the proxy password
      +  925   +
            */
      +  926   +
           public String getProxyPassword() {
      +  927  0
               return line.getOptionValue(ARGUMENT.PROXY_PASSWORD);
      +  928   +
           }
      +  929   +
       
      +  930   +
           /**
      +  931   +
            * Get the value of dataDirectory.
      +  932   +
            *
      +  933   +
            * @return the value of dataDirectory
      +  934   +
            */
      +  935   +
           public String getDataDirectory() {
      +  936  0
               return line.getOptionValue(ARGUMENT.DATA_DIRECTORY);
      +  937   +
           }
      +  938   +
       
      +  939   +
           /**
      +  940   +
            * Returns the properties file specified on the command line.
      +  941   +
            *
      +  942   +
            * @return the properties file specified on the command line
      +  943   +
            */
      +  944   +
           public File getPropertiesFile() {
      +  945  0
               final String path = line.getOptionValue(ARGUMENT.PROP);
      +  946  0
               if (path != null) {
      +  947  0
                   return new File(path);
       948   -
            * Returns the path to the verbose log file.
      -  949   -
            *
      +
               }
      +  949  0
               return null;
       950   -
            * @return the path to the verbose log file
      +
           }
       951   -
            */
      +
       
       952   -
           public String getVerboseLog() {
      -  953  0
               return line.getOptionValue(ARGUMENT.VERBOSE_LOG);
      +
           /**
      +  953   +
            * Returns the path to the verbose log file.
       954   -
           }
      +
            *
       955   -
       
      +
            * @return the path to the verbose log file
       956   -
           /**
      +
            */
       957   -
            * Returns the path to the suppression file.
      -  958   -
            *
      +
           public String getVerboseLog() {
      +  958  0
               return line.getOptionValue(ARGUMENT.VERBOSE_LOG);
       959   -
            * @return the path to the suppression file
      -  960   -
            */
      -  961   -
           public String getSuppressionFile() {
      -  962  0
               return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE);
      -  963  
           }
      -  964   +  960  
       
      -  965   +  961  
           /**
      -  966   -
            * <p>
      -  967   -
            * Prints the manifest information to standard output.</p>
      -  968   -
            * <ul><li>Implementation-Title: ${pom.name}</li>
      -  969   -
            * <li>Implementation-Version: ${pom.version}</li></ul>
      -  970   -
            */
      -  971   -
           public void printVersionInfo() {
      -  972  2
               final String version = String.format("%s version %s",
      -  973  1
                       Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"),
      -  974  1
                       Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
      -  975  1
               System.out.println(version);
      -  976  1
           }
      -  977   -
       
      -  978   -
           /**
      -  979   -
            * Checks if the auto update feature has been disabled. If it has been
      -  980   -
            * disabled via the command line this will return false.
      -  981   +  962   +
            * Returns the path to the suppression file.
      +  963  
            *
      +  964   +
            * @return the path to the suppression file
      +  965   +
            */
      +  966   +
           public String getSuppressionFile() {
      +  967  0
               return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE);
      +  968   +
           }
      +  969   +
       
      +  970   +
           /**
      +  971   +
            * Returns the path to the hints file.
      +  972   +
            *
      +  973   +
            * @return the path to the hints file
      +  974   +
            */
      +  975   +
           public String getHintsFile() {
      +  976  0
               return line.getOptionValue(ARGUMENT.HINTS_FILE);
      +  977   +
           }
      +  978   +
       
      +  979   +
           /**
      +  980   +
            * <p>
      +  981   +
            * Prints the manifest information to standard output.</p>
       982   -
            * @return <code>true</code> if auto-update is allowed; otherwise
      +
            * <ul><li>Implementation-Title: ${pom.name}</li>
       983   -
            * <code>false</code>
      +
            * <li>Implementation-Version: ${pom.version}</li></ul>
       984  
            */
       985   -
           public boolean isAutoUpdate() {
      -  986  0
               return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
      -  987   -
           }
      -  988   -
       
      -  989   -
           /**
      -  990   -
            * Checks if the update only flag has been set.
      +
           public void printVersionInfo() {
      +  986  2
               final String version = String.format("%s version %s",
      +  987  1
                       Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"),
      +  988  1
                       Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
      +  989  1
               System.out.println(version);
      +  990  1
           }
       991   -
            *
      +
       
       992   -
            * @return <code>true</code> if the update only flag has been set; otherwise
      +
           /**
       993   -
            * <code>false</code>.
      +
            * Checks if the auto update feature has been disabled. If it has been
       994   -
            */
      +
            * disabled via the command line this will return false.
       995   -
           public boolean isUpdateOnly() {
      -  996  7
               return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY);
      +
            *
      +  996   +
            * @return <code>true</code> if auto-update is allowed; otherwise
       997   -
           }
      +
            * <code>false</code>
       998   -
       
      +
            */
       999   -
           /**
      -  1000   -
            * Checks if the purge NVD flag has been set.
      +
           public boolean isAutoUpdate() {
      +  1000  0
               return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
       1001   -
            *
      +
           }
       1002   -
            * @return <code>true</code> if the purge nvd flag has been set; otherwise
      +
       
       1003   -
            * <code>false</code>.
      +
           /**
       1004   -
            */
      +
            * Checks if the update only flag has been set.
       1005   -
           public boolean isPurge() {
      -  1006  0
               return line != null && line.hasOption(ARGUMENT.PURGE_NVD);
      +
            *
      +  1006   +
            * @return <code>true</code> if the update only flag has been set; otherwise
       1007   -
           }
      +
            * <code>false</code>.
       1008   -
       
      +
            */
       1009   -
           /**
      -  1010   -
            * Returns the database driver name if specified; otherwise null is
      +
           public boolean isUpdateOnly() {
      +  1010  7
               return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY);
       1011   -
            * returned.
      +
           }
       1012   -
            *
      +
       
       1013   -
            * @return the database driver name if specified; otherwise null is returned
      +
           /**
       1014   -
            */
      +
            * Checks if the purge NVD flag has been set.
       1015   -
           public String getDatabaseDriverName() {
      -  1016  0
               return line.getOptionValue(ARGUMENT.DB_DRIVER);
      +
            *
      +  1016   +
            * @return <code>true</code> if the purge nvd flag has been set; otherwise
       1017   -
           }
      +
            * <code>false</code>.
       1018   -
       
      +
            */
       1019   -
           /**
      -  1020   -
            * Returns the database driver path if specified; otherwise null is
      +
           public boolean isPurge() {
      +  1020  0
               return line != null && line.hasOption(ARGUMENT.PURGE_NVD);
       1021   -
            * returned.
      +
           }
       1022   -
            *
      +
       
       1023   -
            * @return the database driver name if specified; otherwise null is returned
      +
           /**
       1024   -
            */
      +
            * Returns the database driver name if specified; otherwise null is
       1025   -
           public String getDatabaseDriverPath() {
      -  1026  0
               return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH);
      +
            * returned.
      +  1026   +
            *
       1027   -
           }
      +
            * @return the database driver name if specified; otherwise null is returned
       1028   -
       
      +
            */
       1029   -
           /**
      -  1030   -
            * Returns the database connection string if specified; otherwise null is
      +
           public String getDatabaseDriverName() {
      +  1030  0
               return line.getOptionValue(ARGUMENT.DB_DRIVER);
       1031   -
            * returned.
      +
           }
       1032   -
            *
      +
       
       1033   -
            * @return the database connection string if specified; otherwise null is
      +
           /**
       1034   -
            * returned
      +
            * Returns the database driver path if specified; otherwise null is
       1035   -
            */
      +
            * returned.
       1036   -
           public String getConnectionString() {
      -  1037  0
               return line.getOptionValue(ARGUMENT.CONNECTION_STRING);
      +
            *
      +  1037   +
            * @return the database driver name if specified; otherwise null is returned
       1038   -
           }
      +
            */
       1039   -
       
      -  1040   -
           /**
      +
           public String getDatabaseDriverPath() {
      +  1040  0
               return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH);
       1041   -
            * Returns the database database user name if specified; otherwise null is
      +
           }
       1042   -
            * returned.
      +
       
       1043   -
            *
      +
           /**
       1044   -
            * @return the database database user name if specified; otherwise null is
      +
            * Returns the database connection string if specified; otherwise null is
       1045   -
            * returned
      +
            * returned.
       1046   -
            */
      +
            *
       1047   -
           public String getDatabaseUser() {
      -  1048  0
               return line.getOptionValue(ARGUMENT.DB_NAME);
      -  1049   -
           }
      -  1050   -
       
      -  1051   -
           /**
      -  1052   -
            * Returns the database database password if specified; otherwise null is
      -  1053   -
            * returned.
      -  1054   -
            *
      -  1055   -
            * @return the database database password if specified; otherwise null is
      -  1056   +
            * @return the database connection string if specified; otherwise null is
      +  1048  
            * returned
      -  1057   +  1049  
            */
      -  1058   -
           public String getDatabasePassword() {
      -  1059  0
               return line.getOptionValue(ARGUMENT.DB_PASSWORD);
      -  1060   +  1050   +
           public String getConnectionString() {
      +  1051  0
               return line.getOptionValue(ARGUMENT.CONNECTION_STRING);
      +  1052  
           }
      -  1061   +  1053  
       
      -  1062   +  1054  
           /**
      -  1063   -
            * Returns the additional Extensions if specified; otherwise null is
      -  1064   +  1055   +
            * Returns the database database user name if specified; otherwise null is
      +  1056  
            * returned.
      +  1057   +
            *
      +  1058   +
            * @return the database database user name if specified; otherwise null is
      +  1059   +
            * returned
      +  1060   +
            */
      +  1061   +
           public String getDatabaseUser() {
      +  1062  0
               return line.getOptionValue(ARGUMENT.DB_NAME);
      +  1063   +
           }
      +  1064   +
       
       1065   -
            *
      +
           /**
       1066   -
            * @return the additional Extensions; otherwise null is returned
      +
            * Returns the database database password if specified; otherwise null is
       1067   -
            */
      +
            * returned.
       1068   -
           public String getAdditionalZipExtensions() {
      -  1069  0
               return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS);
      +
            *
      +  1069   +
            * @return the database database password if specified; otherwise null is
       1070   -
           }
      +
            * returned
       1071   -
       
      +
            */
       1072   -
           /**
      -  1073   -
            * Get the value of cveValidForHours.
      +
           public String getDatabasePassword() {
      +  1073  0
               return line.getOptionValue(ARGUMENT.DB_PASSWORD);
       1074   -
            *
      +
           }
       1075   -
            * @return the value of cveValidForHours
      +
       
       1076   -
            */
      +
           /**
       1077   -
           public Integer getCveValidForHours() {
      -  1078  0
               final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS);
      -  1079  0
               if (v != null) {
      -  1080  0
                   return Integer.parseInt(v);
      -  1081   -
               }
      -  1082  0
               return null;
      -  1083   -
           }
      -  1084   -
       
      -  1085   -
           /**
      -  1086   -
            * Returns true if the experimental analyzers are enabled.
      -  1087   +
            * Returns the additional Extensions if specified; otherwise null is
      +  1078   +
            * returned.
      +  1079  
            *
      -  1088   -
            * @return true if the experimental analyzers are enabled; otherwise false
      -  1089   +  1080   +
            * @return the additional Extensions; otherwise null is returned
      +  1081  
            */
      -  1090   -
           public boolean isExperimentalEnabled() {
      -  1091  0
               return line.hasOption(ARGUMENT.EXPERIMENTAL);
      -  1092   +  1082   +
           public String getAdditionalZipExtensions() {
      +  1083  0
               return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS);
      +  1084  
           }
      -  1093   +  1085  
       
      -  1094   +  1086  
           /**
      -  1095   -
            * A collection of static final strings that represent the possible command
      -  1096   -
            * line arguments.
      -  1097   +  1087   +
            * Get the value of cveValidForHours.
      +  1088   +
            *
      +  1089   +
            * @return the value of cveValidForHours
      +  1090  
            */
      -  1098  0
           public static class ARGUMENT {
      -  1099   +  1091   +
           public Integer getCveValidForHours() {
      +  1092  0
               final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS);
      +  1093  0
               if (v != null) {
      +  1094  0
                   return Integer.parseInt(v);
      +  1095   +
               }
      +  1096  0
               return null;
      +  1097   +
           }
      +  1098  
       
      +  1099   +
           /**
       1100   -
               /**
      +
            * Returns true if the experimental analyzers are enabled.
       1101   -
                * The long CLI argument name specifying the directory/file to scan.
      +
            *
       1102   -
                */
      +
            * @return true if the experimental analyzers are enabled; otherwise false
       1103   -
               public static final String SCAN = "scan";
      +
            */
       1104   -
               /**
      -  1105   -
                * The short CLI argument name specifying the directory/file to scan.
      +
           public boolean isExperimentalEnabled() {
      +  1105  0
               return line.hasOption(ARGUMENT.EXPERIMENTAL);
       1106   -
                */
      +
           }
       1107   -
               public static final String SCAN_SHORT = "s";
      +
       
       1108   -
               /**
      +
           /**
       1109   -
                * The long CLI argument name specifying that the CPE/CVE/etc. data
      +
            * A collection of static final strings that represent the possible command
       1110   -
                * should not be automatically updated.
      +
            * line arguments.
       1111   -
                */
      -  1112   -
               public static final String DISABLE_AUTO_UPDATE = "noupdate";
      +
            */
      +  1112  0
           public static class ARGUMENT {
       1113   -
               /**
      +
       
       1114   -
                * The short CLI argument name specifying that the CPE/CVE/etc. data
      +
               /**
       1115   -
                * should not be automatically updated.
      +
                * The long CLI argument name specifying the directory/file to scan.
       1116  
                */
       1117   -
               public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
      +
               public static final String SCAN = "scan";
       1118  
               /**
       1119   -
                * The long CLI argument name specifying that only the update phase
      +
                * The short CLI argument name specifying the directory/file to scan.
       1120   -
                * should be executed; no scan should be run.
      +
                */
       1121   -
                */
      +
               public static final String SCAN_SHORT = "s";
       1122   -
               public static final String UPDATE_ONLY = "updateonly";
      +
               /**
       1123   -
               /**
      +
                * The long CLI argument name specifying that the CPE/CVE/etc. data
       1124   -
                * The long CLI argument name specifying that only the update phase
      +
                * should not be automatically updated.
       1125   -
                * should be executed; no scan should be run.
      +
                */
       1126   -
                */
      +
               public static final String DISABLE_AUTO_UPDATE = "noupdate";
       1127   -
               public static final String PURGE_NVD = "purge";
      +
               /**
       1128   -
               /**
      +
                * The short CLI argument name specifying that the CPE/CVE/etc. data
       1129   -
                * The long CLI argument name specifying the directory to write the
      +
                * should not be automatically updated.
       1130   -
                * reports to.
      +
                */
       1131   -
                */
      +
               public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
       1132   -
               public static final String OUT = "out";
      +
               /**
       1133   -
               /**
      +
                * The long CLI argument name specifying that only the update phase
       1134   -
                * The short CLI argument name specifying the directory to write the
      +
                * should be executed; no scan should be run.
       1135   -
                * reports to.
      +
                */
       1136   -
                */
      +
               public static final String UPDATE_ONLY = "updateonly";
       1137   -
               public static final String OUT_SHORT = "o";
      +
               /**
       1138   -
               /**
      +
                * The long CLI argument name specifying that only the update phase
       1139   -
                * The long CLI argument name specifying the output format to write the
      +
                * should be executed; no scan should be run.
       1140   -
                * reports to.
      +
                */
       1141   -
                */
      +
               public static final String PURGE_NVD = "purge";
       1142   -
               public static final String OUTPUT_FORMAT = "format";
      +
               /**
       1143   -
               /**
      +
                * The long CLI argument name specifying the directory to write the
       1144   -
                * The short CLI argument name specifying the output format to write the
      -  1145  
                * reports to.
      +  1145   +
                */
       1146   -
                */
      +
               public static final String OUT = "out";
       1147   -
               public static final String OUTPUT_FORMAT_SHORT = "f";
      +
               /**
       1148   -
               /**
      +
                * The short CLI argument name specifying the directory to write the
       1149   -
                * The long CLI argument name specifying the name of the project to be
      +
                * reports to.
       1150   -
                * scanned.
      +
                */
       1151   -
                */
      +
               public static final String OUT_SHORT = "o";
       1152   -
               public static final String PROJECT = "project";
      +
               /**
       1153   -
               /**
      +
                * The long CLI argument name specifying the output format to write the
       1154   -
                * The long CLI argument name specifying the name of the application to
      +
                * reports to.
       1155   -
                * be scanned.
      +
                */
       1156   -
                *
      +
               public static final String OUTPUT_FORMAT = "format";
       1157   -
                * @deprecated project should be used instead
      +
               /**
       1158   -
                */
      +
                * The short CLI argument name specifying the output format to write the
       1159   -
               @Deprecated
      +
                * reports to.
       1160   -
               public static final String APP_NAME = "app";
      +
                */
       1161   -
               /**
      +
               public static final String OUTPUT_FORMAT_SHORT = "f";
       1162   -
                * The short CLI argument name specifying the name of the application to
      +
               /**
       1163   -
                * be scanned.
      +
                * The long CLI argument name specifying the name of the project to be
       1164   -
                *
      +
                * scanned.
       1165   -
                * @deprecated project should be used instead
      +
                */
       1166   -
                */
      +
               public static final String PROJECT = "project";
       1167   -
               @Deprecated
      +
               /**
       1168   -
               public static final String APP_NAME_SHORT = "a";
      +
                * The long CLI argument name specifying the name of the application to
       1169   -
               /**
      +
                * be scanned.
       1170   -
                * The long CLI argument name asking for help.
      -  1171   -
                */
      -  1172   -
               public static final String HELP = "help";
      -  1173   -
               /**
      -  1174   -
                * The long CLI argument name asking for advanced help.
      -  1175   -
                */
      -  1176   -
               public static final String ADVANCED_HELP = "advancedHelp";
      -  1177   -
               /**
      -  1178   -
                * The short CLI argument name asking for help.
      -  1179   -
                */
      -  1180   -
               public static final String HELP_SHORT = "h";
      -  1181   -
               /**
      -  1182   -
                * The long CLI argument name asking for the version.
      -  1183   -
                */
      -  1184   -
               public static final String VERSION_SHORT = "v";
      -  1185   -
               /**
      -  1186   -
                * The short CLI argument name asking for the version.
      -  1187   -
                */
      -  1188   -
               public static final String VERSION = "version";
      -  1189   -
               /**
      -  1190   -
                * The CLI argument name indicating the proxy port.
      -  1191   -
                */
      -  1192   -
               public static final String PROXY_PORT = "proxyport";
      -  1193   -
               /**
      -  1194   -
                * The CLI argument name indicating the proxy server.
      -  1195   -
                */
      -  1196   -
               public static final String PROXY_SERVER = "proxyserver";
      -  1197   -
               /**
      -  1198   -
                * The CLI argument name indicating the proxy url.
      -  1199  
                *
      +  1171   +
                * @deprecated project should be used instead
      +  1172   +
                */
      +  1173   +
               @Deprecated
      +  1174   +
               public static final String APP_NAME = "app";
      +  1175   +
               /**
      +  1176   +
                * The short CLI argument name specifying the name of the application to
      +  1177   +
                * be scanned.
      +  1178   +
                *
      +  1179   +
                * @deprecated project should be used instead
      +  1180   +
                */
      +  1181   +
               @Deprecated
      +  1182   +
               public static final String APP_NAME_SHORT = "a";
      +  1183   +
               /**
      +  1184   +
                * The long CLI argument name asking for help.
      +  1185   +
                */
      +  1186   +
               public static final String HELP = "help";
      +  1187   +
               /**
      +  1188   +
                * The long CLI argument name asking for advanced help.
      +  1189   +
                */
      +  1190   +
               public static final String ADVANCED_HELP = "advancedHelp";
      +  1191   +
               /**
      +  1192   +
                * The short CLI argument name asking for help.
      +  1193   +
                */
      +  1194   +
               public static final String HELP_SHORT = "h";
      +  1195   +
               /**
      +  1196   +
                * The long CLI argument name asking for the version.
      +  1197   +
                */
      +  1198   +
               public static final String VERSION_SHORT = "v";
      +  1199   +
               /**
       1200   -
                * @deprecated use {@link #PROXY_SERVER} instead
      +
                * The short CLI argument name asking for the version.
       1201  
                */
       1202   -
               @Deprecated
      +
               public static final String VERSION = "version";
       1203   -
               public static final String PROXY_URL = "proxyurl";
      +
               /**
       1204   -
               /**
      +
                * The CLI argument name indicating the proxy port.
       1205   -
                * The CLI argument name indicating the proxy username.
      +
                */
       1206   -
                */
      +
               public static final String PROXY_PORT = "proxyport";
       1207   -
               public static final String PROXY_USERNAME = "proxyuser";
      +
               /**
       1208   -
               /**
      +
                * The CLI argument name indicating the proxy server.
       1209   -
                * The CLI argument name indicating the proxy password.
      +
                */
       1210   -
                */
      +
               public static final String PROXY_SERVER = "proxyserver";
       1211   -
               public static final String PROXY_PASSWORD = "proxypass";
      +
               /**
       1212   -
               /**
      +
                * The CLI argument name indicating the proxy url.
       1213   -
                * The short CLI argument name indicating the connection timeout.
      +
                *
       1214   -
                */
      +
                * @deprecated use {@link #PROXY_SERVER} instead
       1215   -
               public static final String CONNECTION_TIMEOUT_SHORT = "c";
      +
                */
       1216   -
               /**
      +
               @Deprecated
       1217   -
                * The CLI argument name indicating the connection timeout.
      +
               public static final String PROXY_URL = "proxyurl";
       1218   -
                */
      +
               /**
       1219   -
               public static final String CONNECTION_TIMEOUT = "connectiontimeout";
      +
                * The CLI argument name indicating the proxy username.
       1220   -
               /**
      -  1221   -
                * The short CLI argument name for setting the location of an additional
      -  1222   -
                * properties file.
      -  1223  
                */
      -  1224   -
               public static final String PROP_SHORT = "P";
      -  1225   +  1221   +
               public static final String PROXY_USERNAME = "proxyuser";
      +  1222  
               /**
      +  1223   +
                * The CLI argument name indicating the proxy password.
      +  1224   +
                */
      +  1225   +
               public static final String PROXY_PASSWORD = "proxypass";
       1226   -
                * The CLI argument name for setting the location of an additional
      +
               /**
       1227   -
                * properties file.
      +
                * The short CLI argument name indicating the connection timeout.
       1228  
                */
       1229   -
               public static final String PROP = "propertyfile";
      +
               public static final String CONNECTION_TIMEOUT_SHORT = "c";
       1230  
               /**
       1231   -
                * The CLI argument name for setting the location of the data directory.
      +
                * The CLI argument name indicating the connection timeout.
       1232  
                */
       1233   -
               public static final String DATA_DIRECTORY = "data";
      +
               public static final String CONNECTION_TIMEOUT = "connectiontimeout";
       1234  
               /**
       1235   -
                * The CLI argument name for setting the URL for the CVE Data Files.
      +
                * The short CLI argument name for setting the location of an additional
       1236   -
                */
      +
                * properties file.
       1237   -
               public static final String CVE_MOD_12 = "cveUrl12Modified";
      +
                */
       1238   -
               /**
      +
               public static final String PROP_SHORT = "P";
       1239   -
                * The CLI argument name for setting the URL for the CVE Data Files.
      +
               /**
       1240   -
                */
      +
                * The CLI argument name for setting the location of an additional
       1241   -
               public static final String CVE_MOD_20 = "cveUrl20Modified";
      +
                * properties file.
       1242   -
               /**
      +
                */
       1243   -
                * The CLI argument name for setting the URL for the CVE Data Files.
      +
               public static final String PROP = "propertyfile";
       1244   -
                */
      +
               /**
       1245   -
               public static final String CVE_BASE_12 = "cveUrl12Base";
      -  1246   -
               /**
      -  1247   -
                * The CLI argument name for setting the URL for the CVE Data Files.
      -  1248   -
                */
      -  1249   -
               public static final String CVE_BASE_20 = "cveUrl20Base";
      -  1250   -
               /**
      -  1251   -
                * The short CLI argument name for setting the location of the data
      -  1252   -
                * directory.
      -  1253   -
                */
      -  1254   -
               public static final String DATA_DIRECTORY_SHORT = "d";
      -  1255   -
               /**
      -  1256  
                * The CLI argument name for setting the location of the data directory.
      -  1257   +  1246  
                */
      -  1258   -
               public static final String VERBOSE_LOG = "log";
      -  1259   +  1247   +
               public static final String DATA_DIRECTORY = "data";
      +  1248  
               /**
      +  1249   +
                * The CLI argument name for setting the URL for the CVE Data Files.
      +  1250   +
                */
      +  1251   +
               public static final String CVE_MOD_12 = "cveUrl12Modified";
      +  1252   +
               /**
      +  1253   +
                * The CLI argument name for setting the URL for the CVE Data Files.
      +  1254   +
                */
      +  1255   +
               public static final String CVE_MOD_20 = "cveUrl20Modified";
      +  1256   +
               /**
      +  1257   +
                * The CLI argument name for setting the URL for the CVE Data Files.
      +  1258   +
                */
      +  1259   +
               public static final String CVE_BASE_12 = "cveUrl12Base";
       1260   -
                * The short CLI argument name for setting the location of the data
      +
               /**
       1261   -
                * directory.
      +
                * The CLI argument name for setting the URL for the CVE Data Files.
       1262  
                */
       1263   -
               public static final String VERBOSE_LOG_SHORT = "l";
      +
               public static final String CVE_BASE_20 = "cveUrl20Base";
       1264   -
       
      +
               /**
       1265   -
               /**
      +
                * The short CLI argument name for setting the location of the data
       1266   -
                * The CLI argument name for setting the depth of symbolic links that
      +
                * directory.
       1267   -
                * will be followed.
      +
                */
       1268   -
                */
      +
               public static final String DATA_DIRECTORY_SHORT = "d";
       1269   -
               public static final String SYM_LINK_DEPTH = "symLink";
      +
               /**
       1270   -
               /**
      +
                * The CLI argument name for setting the location of the data directory.
       1271   -
                * The CLI argument name for setting the location of the suppression
      +
                */
       1272   -
                * file.
      +
               public static final String VERBOSE_LOG = "log";
       1273   -
                */
      +
               /**
       1274   -
               public static final String SUPPRESSION_FILE = "suppression";
      +
                * The short CLI argument name for setting the location of the data
       1275   -
               /**
      +
                * directory.
       1276   -
                * The CLI argument name for setting the location of the suppression
      -  1277   -
                * file.
      -  1278  
                */
      +  1277   +
               public static final String VERBOSE_LOG_SHORT = "l";
      +  1278   +
       
       1279   -
               public static final String CVE_VALID_FOR_HOURS = "cveValidForHours";
      -  1280  
               /**
      +  1280   +
                * The CLI argument name for setting the depth of symbolic links that
       1281   -
                * Disables the Jar Analyzer.
      +
                * will be followed.
       1282  
                */
       1283   -
               public static final String DISABLE_JAR = "disableJar";
      +
               public static final String SYM_LINK_DEPTH = "symLink";
       1284  
               /**
       1285   -
                * Disables the Archive Analyzer.
      +
                * The CLI argument name for setting the location of the suppression
       1286   -
                */
      +
                * file.
       1287   -
               public static final String DISABLE_ARCHIVE = "disableArchive";
      +
                */
       1288   -
               /**
      +
               public static final String SUPPRESSION_FILE = "suppression";
       1289   -
                * Disables the Python Distribution Analyzer.
      +
               /**
       1290   -
                */
      +
                * The CLI argument name for setting the location of the hint
       1291   -
               public static final String DISABLE_PY_DIST = "disablePyDist";
      +
                * file.
       1292   -
               /**
      +
                */
       1293   -
                * Disables the Python Package Analyzer.
      +
               public static final String HINTS_FILE = "hints";
       1294   -
                */
      +
               /**
       1295   -
               public static final String DISABLE_PY_PKG = "disablePyPkg";
      +
                * The CLI argument name for setting the number of hours to wait before
       1296   -
               /**
      +
                * checking for new updates from the NVD.
       1297   -
                * Disables the Python Package Analyzer.
      +
                */
       1298   -
                */
      +
               public static final String CVE_VALID_FOR_HOURS = "cveValidForHours";
       1299   -
               public static final String DISABLE_COMPOSER = "disableComposer";
      +
               /**
       1300   -
               /**
      +
                * Disables the Jar Analyzer.
       1301   -
                * Disables the Ruby Gemspec Analyzer.
      +
                */
       1302   -
                */
      +
               public static final String DISABLE_JAR = "disableJar";
       1303   -
               public static final String DISABLE_RUBYGEMS = "disableRubygems";
      +
               /**
       1304   -
               /**
      +
                * Disables the Archive Analyzer.
       1305   -
                * Disables the Autoconf Analyzer.
      +
                */
       1306   -
                */
      +
               public static final String DISABLE_ARCHIVE = "disableArchive";
       1307   -
               public static final String DISABLE_AUTOCONF = "disableAutoconf";
      +
               /**
       1308   -
               /**
      +
                * Disables the Python Distribution Analyzer.
       1309   -
                * Disables the Cmake Analyzer.
      +
                */
       1310   -
                */
      +
               public static final String DISABLE_PY_DIST = "disablePyDist";
       1311   -
               public static final String DISABLE_CMAKE = "disableCmake";
      +
               /**
       1312   -
               /**
      +
                * Disables the Python Package Analyzer.
       1313   -
                * Disables the Assembly Analyzer.
      +
                */
       1314   -
                */
      +
               public static final String DISABLE_PY_PKG = "disablePyPkg";
       1315   -
               public static final String DISABLE_ASSEMBLY = "disableAssembly";
      +
               /**
       1316   -
               /**
      +
                * Disables the Python Package Analyzer.
       1317   -
                * Disables the Ruby Bundler Audit Analyzer.
      +
                */
       1318   -
                */
      +
               public static final String DISABLE_COMPOSER = "disableComposer";
       1319   -
               public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit";
      +
               /**
       1320   -
               /**
      +
                * Disables the Ruby Gemspec Analyzer.
       1321   -
                * Disables the Nuspec Analyzer.
      +
                */
       1322   -
                */
      +
               public static final String DISABLE_RUBYGEMS = "disableRubygems";
       1323   -
               public static final String DISABLE_NUSPEC = "disableNuspec";
      +
               /**
       1324   -
               /**
      +
                * Disables the Autoconf Analyzer.
       1325   -
                * Disables the Central Analyzer.
      +
                */
       1326   -
                */
      +
               public static final String DISABLE_AUTOCONF = "disableAutoconf";
       1327   -
               public static final String DISABLE_CENTRAL = "disableCentral";
      +
               /**
       1328   -
               /**
      +
                * Disables the Cmake Analyzer.
       1329   -
                * Disables the Nexus Analyzer.
      +
                */
       1330   -
                */
      +
               public static final String DISABLE_CMAKE = "disableCmake";
       1331   -
               public static final String DISABLE_NEXUS = "disableNexus";
      +
               /**
       1332   -
               /**
      +
                * Disables the Assembly Analyzer.
       1333   -
                * Disables the OpenSSL Analyzer.
      +
                */
       1334   -
                */
      +
               public static final String DISABLE_ASSEMBLY = "disableAssembly";
       1335   -
               public static final String DISABLE_OPENSSL = "disableOpenSSL";
      +
               /**
       1336   -
               /**
      +
                * Disables the Ruby Bundler Audit Analyzer.
       1337   -
                * Disables the Node.js Package Analyzer.
      +
                */
       1338   -
                */
      +
               public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit";
       1339   -
               public static final String DISABLE_NODE_JS = "disableNodeJS";
      +
               /**
       1340   -
               /**
      +
                * Disables the Nuspec Analyzer.
       1341   -
                * The URL of the nexus server.
      +
                */
       1342   -
                */
      +
               public static final String DISABLE_NUSPEC = "disableNuspec";
       1343   -
               public static final String NEXUS_URL = "nexus";
      +
               /**
       1344   -
               /**
      +
                * Disables the Central Analyzer.
       1345   -
                * Whether or not the defined proxy should be used when connecting to
      +
                */
       1346   -
                * Nexus.
      +
               public static final String DISABLE_CENTRAL = "disableCentral";
       1347   -
                */
      +
               /**
       1348   -
               public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
      +
                * Disables the Nexus Analyzer.
       1349   -
               /**
      +
                */
       1350   -
                * The CLI argument name for setting the connection string.
      +
               public static final String DISABLE_NEXUS = "disableNexus";
       1351   -
                */
      +
               /**
       1352   -
               public static final String CONNECTION_STRING = "connectionString";
      +
                * Disables the OpenSSL Analyzer.
       1353   -
               /**
      +
                */
       1354   -
                * The CLI argument name for setting the database user name.
      +
               public static final String DISABLE_OPENSSL = "disableOpenSSL";
       1355   -
                */
      +
               /**
       1356   -
               public static final String DB_NAME = "dbUser";
      +
                * Disables the Node.js Package Analyzer.
       1357   -
               /**
      +
                */
       1358   -
                * The CLI argument name for setting the database password.
      +
               public static final String DISABLE_NODE_JS = "disableNodeJS";
       1359   -
                */
      +
               /**
       1360   -
               public static final String DB_PASSWORD = "dbPassword";
      +
                * The URL of the nexus server.
       1361   -
               /**
      +
                */
       1362   -
                * The CLI argument name for setting the database driver name.
      +
               public static final String NEXUS_URL = "nexus";
       1363   -
                */
      +
               /**
       1364   -
               public static final String DB_DRIVER = "dbDriverName";
      +
                * Whether or not the defined proxy should be used when connecting to
       1365   -
               /**
      +
                * Nexus.
       1366   -
                * The CLI argument name for setting the path to the database driver; in
      +
                */
       1367   -
                * case it is not on the class path.
      +
               public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
       1368   -
                */
      +
               /**
       1369   -
               public static final String DB_DRIVER_PATH = "dbDriverPath";
      +
                * The CLI argument name for setting the connection string.
       1370   -
               /**
      +
                */
       1371   -
                * The CLI argument name for setting the path to mono for .NET Assembly
      +
               public static final String CONNECTION_STRING = "connectionString";
       1372   -
                * analysis on non-windows systems.
      +
               /**
       1373   -
                */
      +
                * The CLI argument name for setting the database user name.
       1374   -
               public static final String PATH_TO_MONO = "mono";
      +
                */
       1375   -
               /**
      +
               public static final String DB_NAME = "dbUser";
       1376   -
                * The CLI argument name for setting extra extensions.
      +
               /**
       1377   -
                */
      +
                * The CLI argument name for setting the database password.
       1378   -
               public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
      +
                */
       1379   -
               /**
      +
               public static final String DB_PASSWORD = "dbPassword";
       1380   -
                * Exclude path argument.
      +
               /**
       1381   -
                */
      +
                * The CLI argument name for setting the database driver name.
       1382   -
               public static final String EXCLUDE = "exclude";
      +
                */
       1383   -
               /**
      +
               public static final String DB_DRIVER = "dbDriverName";
       1384   -
                * The CLI argument name for setting the path to bundle-audit for Ruby
      -  1385   -
                * bundle analysis.
      -  1386   -
                */
      -  1387   -
               public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit";
      -  1388  
               /**
      -  1389   -
                * The CLI argument to enable the experimental analyzers.
      -  1390   +  1385   +
                * The CLI argument name for setting the path to the database driver; in
      +  1386   +
                * case it is not on the class path.
      +  1387  
                */
      +  1388   +
               public static final String DB_DRIVER_PATH = "dbDriverPath";
      +  1389   +
               /**
      +  1390   +
                * The CLI argument name for setting the path to mono for .NET Assembly
       1391   -
               private static final String EXPERIMENTAL = "enableExperimental";
      +
                * analysis on non-windows systems.
       1392   -
           }
      +
                */
       1393   +
               public static final String PATH_TO_MONO = "mono";
      +  1394   +
               /**
      +  1395   +
                * The CLI argument name for setting extra extensions.
      +  1396   +
                */
      +  1397   +
               public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
      +  1398   +
               /**
      +  1399   +
                * Exclude path argument.
      +  1400   +
                */
      +  1401   +
               public static final String EXCLUDE = "exclude";
      +  1402   +
               /**
      +  1403   +
                * The CLI argument name for setting the path to bundle-audit for Ruby
      +  1404   +
                * bundle analysis.
      +  1405   +
                */
      +  1406   +
               public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit";
      +  1407   +
               /**
      +  1408   +
                * The CLI argument to enable the experimental analyzers.
      +  1409   +
                */
      +  1410   +
               private static final String EXPERIMENTAL = "enableExperimental";
      +  1411   +
           }
      +  1412  
       }
      - + diff --git a/dependency-check-cli/cobertura/org.owasp.dependencycheck.InvalidScanPathException.html b/dependency-check-cli/cobertura/org.owasp.dependencycheck.InvalidScanPathException.html index d75eb61ba..7e29d9767 100644 --- a/dependency-check-cli/cobertura/org.owasp.dependencycheck.InvalidScanPathException.html +++ b/dependency-check-cli/cobertura/org.owasp.dependencycheck.InvalidScanPathException.html @@ -143,6 +143,6 @@
       }
      - + diff --git a/dependency-check-cli/dependency-analysis.html b/dependency-check-cli/dependency-analysis.html index 7d10f91b3..0d3374bb5 100644 --- a/dependency-check-cli/dependency-analysis.html +++ b/dependency-check-cli/dependency-analysis.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Dependencies Report @@ -52,7 +52,7 @@ @@ -254,7 +254,7 @@ org.owasp dependency-check-core -1.4.3 +1.4.4 compile jar @@ -262,7 +262,7 @@ org.owasp dependency-check-utils -1.4.3 +1.4.4 compile jar diff --git a/dependency-check-cli/dependency-updates-report.html b/dependency-check-cli/dependency-updates-report.html index e5a3cac24..76ab4485f 100644 --- a/dependency-check-cli/dependency-updates-report.html +++ b/dependency-check-cli/dependency-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Dependency Updates Report @@ -52,7 +52,7 @@ @@ -237,7 +237,7 @@ # of dependencies using the latest version available -23 +24 # of dependencies where the next version available is smaller than an incremental version update @@ -245,7 +245,7 @@ # of dependencies where the next version available is an incremental version update -1 +0 # of dependencies where the next version available is a minor version update @@ -318,15 +318,15 @@ 1.4.177 - + com.sun.mail mailapi -1.5.5 +1.5.6 jar -1.5.6 + @@ -522,16 +522,16 @@ - + org.apache.maven.plugin-tools maven-plugin-annotations -3.4 +3.5 jar -3.5 + @@ -606,7 +606,7 @@ 1.25 - + org.jsoup jsoup 1.9.2 @@ -615,7 +615,7 @@ jar - +1.10.1 @@ -684,7 +684,7 @@ org.owasp dependency-check-core -1.4.3 +1.4.4 compile jar @@ -696,7 +696,7 @@ org.owasp dependency-check-utils -1.4.3 +1.4.4 compile jar @@ -817,13 +817,13 @@ jar Newer versions -1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192 Latest Minor +1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192
      1.4.193 Latest Minor

      com.sun.mail:mailapi

      - + @@ -832,7 +832,7 @@ - + @@ -841,10 +841,7 @@ - - - -
      Status There is at least one newer incremental version available. Incremental updates are typically passive.
       No newer versions available.
      Group Id com.sun.mail
      mailapi
      Current Version1.5.5
      1.5.6
      Scope
      Typejar
      Newer versions1.5.6 Next Incremental
      +jar

      commons-cli:commons-cli

      @@ -1042,7 +1039,7 @@ -
      jar
      Newer versions3.4 Next Minor
      +3.4 Next Minor
      3.5 Latest Minor

      org.apache.lucene:lucene-analyzers-common

      @@ -1069,7 +1066,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-core

      @@ -1096,7 +1093,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-queryparser

      @@ -1123,7 +1120,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-test-framework

      @@ -1150,7 +1147,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.maven:maven-core

      @@ -1252,7 +1249,7 @@
      - + @@ -1261,7 +1258,7 @@ - + @@ -1270,10 +1267,7 @@ - - - -
      Status There is at least one newer minor version available. Minor updates are sometimes passive.
       No newer versions available.
      Group Id org.apache.maven.plugin-tools
      maven-plugin-annotations
      Current Version3.4
      3.5
      Scope
      Typejar
      Newer versions3.5 Next Minor
      +jar

      org.apache.maven.reporting:maven-reporting-api

      @@ -1423,13 +1417,13 @@ -
      jar
      Newer versions1.25 Next Minor
      1.26
      1.27 Latest Minor
      +1.25 Next Minor
      1.26
      1.27
      1.28
      1.29 Latest Minor

      org.jsoup:jsoup

      - + @@ -1447,7 +1441,10 @@ -
      Status No newer versions available.
       There is at least one newer minor version available. Minor updates are sometimes passive.
      Group Id org.jsoup
      Typejar
      +jar + +Newer versions +1.10.1 Next Minor

      org.owasp:dependency-check-core

      @@ -1462,7 +1459,7 @@ - + @@ -1486,7 +1483,7 @@ - + diff --git a/dependency-check-cli/findbugs.html b/dependency-check-cli/findbugs.html index 3edbb5812..441c163c3 100644 --- a/dependency-check-cli/findbugs.html +++ b/dependency-check-cli/findbugs.html @@ -1,13 +1,13 @@ - + dependency-check-cli – FindBugs Bug Detector Report @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/index.html b/dependency-check-cli/index.html index 17fe20d5e..68150f74a 100644 --- a/dependency-check-cli/index.html +++ b/dependency-check-cli/index.html @@ -1,13 +1,13 @@ - + dependency-check-cli – About @@ -52,7 +52,7 @@ @@ -147,11 +147,7 @@

      About

      OWASP dependency-check-cli is an command line tool that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the scanned project dependencies. The tool will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.

      Installation & Usage

      -

      Download the dependency-check command line tool here. Extract the zip file to a location on your computer and put the ‘bin’ directory into the path environment variable. On *nix systems you will likely need to make the shell script executable:

      - -
      -
      $ chmod +777 dependency-check.sh
      -
      +

      Download the dependency-check command line tool here. Extract the zip file to a location on your computer and put the ‘bin’ directory into the path environment variable.

      Homebrew

      diff --git a/dependency-check-cli/integration.html b/dependency-check-cli/integration.html index 1a9efc9db..a8bbb71f2 100644 --- a/dependency-check-cli/integration.html +++ b/dependency-check-cli/integration.html @@ -1,13 +1,13 @@ - + dependency-check-cli – CI Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/issue-tracking.html b/dependency-check-cli/issue-tracking.html index e09b4be67..7b48aa4c5 100644 --- a/dependency-check-cli/issue-tracking.html +++ b/dependency-check-cli/issue-tracking.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Issue Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/license.html b/dependency-check-cli/license.html index fb81d4032..8476813e5 100644 --- a/dependency-check-cli/license.html +++ b/dependency-check-cli/license.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Project Licenses @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/mail-lists.html b/dependency-check-cli/mail-lists.html index a90d72d99..df485263e 100644 --- a/dependency-check-cli/mail-lists.html +++ b/dependency-check-cli/mail-lists.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Project Mailing Lists @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/plugin-updates-report.html b/dependency-check-cli/plugin-updates-report.html index dffdbb034..004147a26 100644 --- a/dependency-check-cli/plugin-updates-report.html +++ b/dependency-check-cli/plugin-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Plugin Updates Report @@ -52,7 +52,7 @@ @@ -405,7 +405,7 @@
      - + @@ -686,7 +686,7 @@ -
      dependency-check-core
      Current Version1.4.3
      1.4.4
      Scope compile
      dependency-check-utils
      Current Version1.4.3
      1.4.4
      Scope compile
      org.apache.maven.plugins maven-resources-plugin3.0.03.0.1 maven-resources-plugin
      Current Version3.0.0
      +3.0.1

      Plugin org.apache.maven.plugins:maven-site-plugin

      diff --git a/dependency-check-cli/pmd.html b/dependency-check-cli/pmd.html index 598e407ce..958df7951 100644 --- a/dependency-check-cli/pmd.html +++ b/dependency-check-cli/pmd.html @@ -1,13 +1,13 @@ - + dependency-check-cli – PMD Results @@ -52,7 +52,7 @@ @@ -243,7 +243,7 @@ -
      Line
      Useless parentheses.240
      +241

      org/owasp/dependencycheck/CliParser.java

      @@ -261,58 +261,58 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + -
      199
      Useless parentheses.512
      517
      Useless parentheses.521
      526
      Useless parentheses.530
      535
      Useless parentheses.559
      564
      Useless parentheses.569
      574
      Useless parentheses.579
      584
      Useless parentheses.589
      594
      Useless parentheses.600
      605
      Useless parentheses.610
      615
      Useless parentheses.620
      625
      Useless parentheses.630
      635
      Useless parentheses.640
      645
      Useless parentheses.650
      655
      Useless parentheses.660
      665
      Useless parentheses.670
      675
      Useless parentheses.680
      685
      Useless parentheses.690
      695
      Useless parentheses.700
      +705 diff --git a/dependency-check-cli/project-info.html b/dependency-check-cli/project-info.html index 531445810..081afd0bf 100644 --- a/dependency-check-cli/project-info.html +++ b/dependency-check-cli/project-info.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Project Information @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/project-reports.html b/dependency-check-cli/project-reports.html index 6896d439d..607c8bd75 100644 --- a/dependency-check-cli/project-reports.html +++ b/dependency-check-cli/project-reports.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Generated Reports @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/project-summary.html b/dependency-check-cli/project-summary.html index 95f1b3520..270319ee4 100644 --- a/dependency-check-cli/project-summary.html +++ b/dependency-check-cli/project-summary.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Project Summary @@ -52,7 +52,7 @@ @@ -238,7 +238,7 @@ dependency-check-cli Version -1.4.3 +1.4.4 Type jar diff --git a/dependency-check-cli/source-repository.html b/dependency-check-cli/source-repository.html index cdeb0e72e..b1cb52576 100644 --- a/dependency-check-cli/source-repository.html +++ b/dependency-check-cli/source-repository.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Source Code Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/surefire-report.html b/dependency-check-cli/surefire-report.html index f530e711e..5b267aa6a 100644 --- a/dependency-check-cli/surefire-report.html +++ b/dependency-check-cli/surefire-report.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Surefire Report @@ -52,7 +52,7 @@ @@ -266,7 +266,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.371
      +0.352

      Note: failures are anticipated and checked for with assertions while errors are unanticipated.


      Package List

      @@ -287,7 +287,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.371
      +0.352

      Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.

      org.owasp.dependencycheck

      @@ -309,7 +309,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.336 +0.32 CliParserTest @@ -318,7 +318,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.035

      +0.032

      Test Cases

      [Summary] [Package List] [Test Cases]

      @@ -328,11 +328,11 @@ function toggleDisplay(elementId) { testEnsureCanonicalPath2 -0.255 +0.248 testEnsureCanonicalPath -0
      +0.001

      CliParserTest

      @@ -343,7 +343,7 @@ function toggleDisplay(elementId) { - + @@ -363,7 +363,7 @@ function toggleDisplay(elementId) { - + @@ -371,7 +371,7 @@ function toggleDisplay(elementId) { -
      testParse_printVersionInfo0
      0.001
      testParse_help
      testParse_version0.001
      0
      testParse_scan_unknownFile
      testParse_scan_withFileExists0.002

      +0.001
      diff --git a/dependency-check-cli/taglist.html b/dependency-check-cli/taglist.html index d9d68c67a..b9fd719fe 100644 --- a/dependency-check-cli/taglist.html +++ b/dependency-check-cli/taglist.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Tag List report @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/team-list.html b/dependency-check-cli/team-list.html index 9a5ba503b..045e22ad0 100644 --- a/dependency-check-cli/team-list.html +++ b/dependency-check-cli/team-list.html @@ -1,13 +1,13 @@ - + dependency-check-cli – Project Team @@ -52,7 +52,7 @@ diff --git a/dependency-check-cli/xref-test/index.html b/dependency-check-cli/xref-test/index.html index e557c4b07..bd34bfb98 100644 --- a/dependency-check-cli/xref-test/index.html +++ b/dependency-check-cli/xref-test/index.html @@ -4,7 +4,7 @@ - Dependency-Check Command Line 1.4.3 Reference + Dependency-Check Command Line 1.4.4 Reference diff --git a/dependency-check-cli/xref-test/org/owasp/dependencycheck/package-frame.html b/dependency-check-cli/xref-test/org/owasp/dependencycheck/package-frame.html index 41c25114f..cd4a2577f 100644 --- a/dependency-check-cli/xref-test/org/owasp/dependencycheck/package-frame.html +++ b/dependency-check-cli/xref-test/org/owasp/dependencycheck/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Command Line 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check Command Line 1.4.4 Reference Package org.owasp.dependencycheck diff --git a/dependency-check-cli/xref-test/org/owasp/dependencycheck/package-summary.html b/dependency-check-cli/xref-test/org/owasp/dependencycheck/package-summary.html index 8fbdc2037..c8d6215be 100644 --- a/dependency-check-cli/xref-test/org/owasp/dependencycheck/package-summary.html +++ b/dependency-check-cli/xref-test/org/owasp/dependencycheck/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Command Line 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check Command Line 1.4.4 Reference Package org.owasp.dependencycheck diff --git a/dependency-check-cli/xref-test/overview-frame.html b/dependency-check-cli/xref-test/overview-frame.html index 8dccbdb4d..8afc9d35e 100644 --- a/dependency-check-cli/xref-test/overview-frame.html +++ b/dependency-check-cli/xref-test/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Command Line 1.4.3 Reference + Dependency-Check Command Line 1.4.4 Reference diff --git a/dependency-check-cli/xref-test/overview-summary.html b/dependency-check-cli/xref-test/overview-summary.html index d03aa3af5..a0404678c 100644 --- a/dependency-check-cli/xref-test/overview-summary.html +++ b/dependency-check-cli/xref-test/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Command Line 1.4.3 Reference + Dependency-Check Command Line 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Command Line 1.4.3 Reference

      +

      Dependency-Check Command Line 1.4.4 Reference

      diff --git a/dependency-check-cli/xref/index.html b/dependency-check-cli/xref/index.html index e557c4b07..bd34bfb98 100644 --- a/dependency-check-cli/xref/index.html +++ b/dependency-check-cli/xref/index.html @@ -4,7 +4,7 @@ - Dependency-Check Command Line 1.4.3 Reference + Dependency-Check Command Line 1.4.4 Reference diff --git a/dependency-check-cli/xref/org/owasp/dependencycheck/App.html b/dependency-check-cli/xref/org/owasp/dependencycheck/App.html index 722b6b5df..1e7bcad66 100644 --- a/dependency-check-cli/xref/org/owasp/dependencycheck/App.html +++ b/dependency-check-cli/xref/org/owasp/dependencycheck/App.html @@ -27,508 +27,511 @@ 1920import ch.qos.logback.classic.LoggerContext; 21import ch.qos.logback.classic.encoder.PatternLayoutEncoder; -22import java.io.File; -23import java.io.FileNotFoundException; -24import java.io.IOException; -25import java.util.ArrayList; -26import java.util.HashSet; -27import java.util.List; -28import java.util.Set; -29import org.apache.commons.cli.ParseException; -30import org.owasp.dependencycheck.data.nvdcve.CveDB; -31import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -32import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; -33import org.owasp.dependencycheck.dependency.Dependency; -34import org.apache.tools.ant.DirectoryScanner; -35import org.owasp.dependencycheck.reporting.ReportGenerator; -36import org.owasp.dependencycheck.utils.Settings; -37import org.slf4j.Logger; -38import org.slf4j.LoggerFactory; -39import ch.qos.logback.core.FileAppender; -40import org.owasp.dependencycheck.data.update.exception.UpdateException; -41import org.owasp.dependencycheck.exception.ExceptionCollection; -42import org.owasp.dependencycheck.exception.ReportException; -43import org.owasp.dependencycheck.utils.InvalidSettingException; -44import org.slf4j.impl.StaticLoggerBinder; -45 -46/** -47 * The command line interface for the DependencyCheck application. -48 * -49 * @author Jeremy Long -50 */ -51publicclassApp { -52 -53/** -54 * The logger. -55 */ -56privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(App.class); -57 -58/** -59 * The main method for the application. -60 * -61 * @param args the command line arguments -62 */ -63publicstaticvoid main(String[] args) { -64int exitCode = 0; -65try { -66 Settings.initialize(); -67finalApp app = newApp(); -68 exitCode = app.run(args); -69 LOGGER.debug("Exit code: " + exitCode); -70 } finally { -71 Settings.cleanup(true); -72 } -73 System.exit(exitCode); -74 } -75 -76/** -77 * Main CLI entry-point into the application. -78 * -79 * @param args the command line arguments -80 * @return the exit code to return -81 */ -82publicint run(String[] args) { -83int exitCode = 0; -84finalCliParser cli = newCliParser(); -85 -86try { -87 cli.parse(args); -88 } catch (FileNotFoundException ex) { -89 System.err.println(ex.getMessage()); -90 cli.printHelp(); -91return -1; -92 } catch (ParseException ex) { -93 System.err.println(ex.getMessage()); -94 cli.printHelp(); -95return -2; -96 } -97 -98if (cli.getVerboseLog() != null) { -99 prepareLogger(cli.getVerboseLog()); -100 } -101 -102if (cli.isPurge()) { -103if (cli.getConnectionString() != null) { -104 LOGGER.error("Unable to purge the database when using a non-default connection string"); -105 exitCode = -3; -106 } else { -107try { -108 populateSettings(cli); -109 } catch (InvalidSettingException ex) { -110 LOGGER.error(ex.getMessage()); -111 LOGGER.debug("Error loading properties file", ex); -112 exitCode = -4; -113 } -114 File db; -115try { -116 db = new File(Settings.getDataDirectory(), "dc.h2.db"); -117if (db.exists()) { -118if (db.delete()) { -119 LOGGER.info("Database file purged; local copy of the NVD has been removed"); -120 } else { -121 LOGGER.error("Unable to delete '{}'; please delete the file manually", db.getAbsolutePath()); -122 exitCode = -5; -123 } -124 } else { -125 LOGGER.error("Unable to purge database; the database file does not exists: {}", db.getAbsolutePath()); -126 exitCode = -6; -127 } -128 } catch (IOException ex) { -129 LOGGER.error("Unable to delete the database"); -130 exitCode = -7; -131 } -132 } -133 } elseif (cli.isGetVersion()) { -134 cli.printVersionInfo(); -135 } elseif (cli.isUpdateOnly()) { -136try { -137 populateSettings(cli); -138 } catch (InvalidSettingException ex) { -139 LOGGER.error(ex.getMessage()); -140 LOGGER.debug("Error loading properties file", ex); -141 exitCode = -4; -142 } -143try { -144 runUpdateOnly(); -145 } catch (UpdateException ex) { -146 LOGGER.error(ex.getMessage()); -147 exitCode = -8; -148 } catch (DatabaseException ex) { -149 LOGGER.error(ex.getMessage()); -150 exitCode = -9; -151 } -152 } elseif (cli.isRunScan()) { -153try { -154 populateSettings(cli); -155 } catch (InvalidSettingException ex) { -156 LOGGER.error(ex.getMessage()); -157 LOGGER.debug("Error loading properties file", ex); -158 exitCode = -4; -159 } -160try { -161final String[] scanFiles = cli.getScanFiles(); -162if (scanFiles != null) { -163 runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles, -164 cli.getExcludeList(), cli.getSymLinkDepth()); -165 } else { -166 LOGGER.error("No scan files configured"); -167 } -168 } catch (InvalidScanPathException ex) { -169 LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths"); -170 exitCode = -10; -171 } catch (DatabaseException ex) { -172 LOGGER.error(ex.getMessage()); -173 exitCode = -11; -174 } catch (ReportException ex) { -175 LOGGER.error(ex.getMessage()); -176 exitCode = -12; -177 } catch (ExceptionCollection ex) { -178if (ex.isFatal()) { -179 exitCode = -13; -180 LOGGER.error("One or more fatal errors occured"); -181 } else { -182 exitCode = -14; -183 } -184for (Throwable e : ex.getExceptions()) { -185 LOGGER.error(e.getMessage()); -186 } -187 } -188 } else { -189 cli.printHelp(); -190 } -191return exitCode; -192 } -193 -194/** -195 * Scans the specified directories and writes the dependency reports to the -196 * reportDirectory. -197 * -198 * @param reportDirectory the path to the directory where the reports will -199 * be written -200 * @param outputFormat the output format of the report -201 * @param applicationName the application name for the report -202 * @param files the files/directories to scan -203 * @param excludes the patterns for files/directories to exclude -204 * @param symLinkDepth the depth that symbolic links will be followed -205 * -206 * @throws InvalidScanPathException thrown if the path to scan starts with -207 * "//" -208 * @throws ReportException thrown when the report cannot be generated -209 * @throws DatabaseException thrown when there is an error connecting to the -210 * database -211 * @throws ExceptionCollection thrown when an exception occurs during -212 * analysis; there may be multiple exceptions contained within the -213 * collection. -214 */ -215privatevoid runScan(String reportDirectory, String outputFormat, String applicationName, String[] files, -216 String[] excludes, int symLinkDepth) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException { -217 Engine engine = null; -218try { -219 engine = new Engine(); -220final List<String> antStylePaths = new ArrayList<String>(); -221for (String file : files) { -222final String antPath = ensureCanonicalPath(file); -223 antStylePaths.add(antPath); -224 } -225 -226final Set<File> paths = new HashSet<File>(); -227for (String file : antStylePaths) { -228 LOGGER.debug("Scanning {}", file); -229final DirectoryScanner scanner = new DirectoryScanner(); -230 String include = file.replace('\\', '/'); -231 File baseDir; -232 -233if (include.startsWith("//")) { -234thrownewInvalidScanPathException("Unable to scan paths specified by //"); -235 } else { -236finalint pos = getLastFileSeparator(include); -237final String tmpBase = include.substring(0, pos); -238final String tmpInclude = include.substring(pos + 1); -239if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0 -240 || (new File(include)).isFile()) { -241 baseDir = new File(tmpBase); -242 include = tmpInclude; -243 } else { -244 baseDir = new File(tmpBase, tmpInclude); -245 include = "**/*"; -246 } -247 } -248 scanner.setBasedir(baseDir); -249final String[] includes = {include}; -250 scanner.setIncludes(includes); -251 scanner.setMaxLevelsOfSymlinks(symLinkDepth); -252if (symLinkDepth <= 0) { -253 scanner.setFollowSymlinks(false); -254 } -255if (excludes != null && excludes.length > 0) { -256 scanner.addExcludes(excludes); -257 } -258 scanner.scan(); -259if (scanner.getIncludedFilesCount() > 0) { -260for (String s : scanner.getIncludedFiles()) { -261final File f = new File(baseDir, s); -262 LOGGER.debug("Found file {}", f.toString()); -263 paths.add(f); -264 } -265 } -266 } -267 engine.scan(paths); -268 -269 ExceptionCollection exCol = null; -270try { -271 engine.analyzeDependencies(); -272 } catch (ExceptionCollection ex) { -273if (ex.isFatal()) { -274throw ex; -275 } -276 exCol = ex; -277 } -278final List<Dependency> dependencies = engine.getDependencies(); -279 DatabaseProperties prop = null; -280 CveDB cve = null; -281try { -282 cve = new CveDB(); -283 cve.open(); -284 prop = cve.getDatabaseProperties(); -285 } finally { -286if (cve != null) { -287 cve.close(); -288 } -289 } -290final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop); -291try { -292 report.generateReports(reportDirectory, outputFormat); -293 } catch (ReportException ex) { -294if (exCol != null) { -295 exCol.addException(ex); -296throw exCol; -297 } else { -298throw ex; -299 } -300 } -301if (exCol != null && exCol.getExceptions().size() > 0) { -302throw exCol; -303 } -304 } finally { -305if (engine != null) { -306 engine.cleanup(); -307 } -308 } -309 -310 } -311 -312/** -313 * Only executes the update phase of dependency-check. -314 * -315 * @throws UpdateException thrown if there is an error updating -316 * @throws DatabaseException thrown if a fatal error occurred and a -317 * connection to the database could not be established -318 */ -319privatevoid runUpdateOnly() throws UpdateException, DatabaseException { -320 Engine engine = null; -321try { -322 engine = new Engine(); -323 engine.doUpdates(); -324 } finally { -325if (engine != null) { -326 engine.cleanup(); -327 } -328 } -329 } -330 -331/** -332 * Updates the global Settings. -333 * -334 * @param cli a reference to the CLI Parser that contains the command line -335 * arguments used to set the corresponding settings in the core engine. -336 * -337 * @throws InvalidSettingException thrown when a user defined properties -338 * file is unable to be loaded. -339 */ -340privatevoid populateSettings(CliParser cli) throws InvalidSettingException { -341finalboolean autoUpdate = cli.isAutoUpdate(); -342final String connectionTimeout = cli.getConnectionTimeout(); -343final String proxyServer = cli.getProxyServer(); -344final String proxyPort = cli.getProxyPort(); -345final String proxyUser = cli.getProxyUsername(); -346final String proxyPass = cli.getProxyPassword(); -347final String dataDirectory = cli.getDataDirectory(); -348final File propertiesFile = cli.getPropertiesFile(); -349final String suppressionFile = cli.getSuppressionFile(); -350final String nexusUrl = cli.getNexusUrl(); -351final String databaseDriverName = cli.getDatabaseDriverName(); -352final String databaseDriverPath = cli.getDatabaseDriverPath(); -353final String connectionString = cli.getConnectionString(); -354final String databaseUser = cli.getDatabaseUser(); -355final String databasePassword = cli.getDatabasePassword(); -356final String additionalZipExtensions = cli.getAdditionalZipExtensions(); -357final String pathToMono = cli.getPathToMono(); -358final String cveMod12 = cli.getModifiedCve12Url(); -359final String cveMod20 = cli.getModifiedCve20Url(); -360final String cveBase12 = cli.getBaseCve12Url(); -361final String cveBase20 = cli.getBaseCve20Url(); -362final Integer cveValidForHours = cli.getCveValidForHours(); -363finalboolean experimentalEnabled = cli.isExperimentalEnabled(); -364 -365if (propertiesFile != null) { -366try { -367 Settings.mergeProperties(propertiesFile); -368 } catch (FileNotFoundException ex) { -369thrownew InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex); -370 } catch (IOException ex) { -371thrownew InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex); -372 } -373 } -374// We have to wait until we've merged the properties before attempting to set whether we use -375// the proxy for Nexus since it could be disabled in the properties, but not explicitly stated -376// on the command line -377finalboolean nexusUsesProxy = cli.isNexusUsesProxy(); -378if (dataDirectory != null) { -379 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory); -380 } elseif (System.getProperty("basedir") != null) { -381final File dataDir = new File(System.getProperty("basedir"), "data"); -382 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); -383 } else { -384final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath()); -385final File base = jarPath.getParentFile(); -386final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY); -387final File dataDir = new File(base, sub); -388 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); -389 } -390 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); -391 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer); -392 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort); -393 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser); -394 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPass); -395 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); -396 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); -397 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); -398 -399//File Type Analyzer Settings -400 Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled); -401 Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled()); -402 Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled()); -403 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled()); -404 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !cli.isPythonPackageDisabled()); -405 Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, !cli.isAutoconfDisabled()); -406 Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, !cli.isCmakeDisabled()); -407 Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !cli.isNuspecDisabled()); -408 Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !cli.isAssemblyDisabled()); -409 Settings.setBoolean(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, !cli.isBundleAuditDisabled()); -410 Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, !cli.isOpenSSLDisabled()); -411 Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, !cli.isComposerDisabled()); -412 Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, !cli.isNodeJsDisabled()); -413 Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, !cli.isRubyGemspecDisabled()); -414 Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !cli.isCentralDisabled()); -415 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !cli.isNexusDisabled()); -416 -417 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, cli.getPathToBundleAudit()); -418 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); -419 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); -420 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); -421 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); -422 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); -423 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); -424 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); -425 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions); -426 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); -427if (cveBase12 != null && !cveBase12.isEmpty()) { -428 Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveBase12); -429 Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveBase20); -430 Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveMod12); -431 Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveMod20); -432 } -433 } -434 -435/** -436 * Creates a file appender and adds it to logback. -437 * -438 * @param verboseLog the path to the verbose log file -439 */ -440privatevoid prepareLogger(String verboseLog) { -441final StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton(); -442final LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory(); -443 -444final PatternLayoutEncoder encoder = new PatternLayoutEncoder(); -445 encoder.setPattern("%d %C:%L%n%-5level - %msg%n"); -446 encoder.setContext(context); -447 encoder.start(); -448final FileAppender fa = new FileAppender(); -449 fa.setAppend(true); -450 fa.setEncoder(encoder); -451 fa.setContext(context); -452 fa.setFile(verboseLog); -453final File f = new File(verboseLog); -454 String name = f.getName(); -455finalint i = name.lastIndexOf('.'); -456if (i > 1) { -457 name = name.substring(0, i); -458 } -459 fa.setName(name); -460 fa.start(); -461final ch.qos.logback.classic.Logger rootLogger = context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); -462 rootLogger.addAppender(fa); -463 } -464 -465/** -466 * Takes a path and resolves it to be a canonical &amp; absolute path. The -467 * caveats are that this method will take an Ant style file selector path -468 * (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at -469 * least to the left of the first * or ?). -470 * -471 * @param path the path to canonicalize -472 * @return the canonical path -473 */ -474protected String ensureCanonicalPath(String path) { -475 String basePath; -476 String wildCards = null; -477final String file = path.replace('\\', '/'); -478if (file.contains("*") || file.contains("?")) { -479 -480int pos = getLastFileSeparator(file); -481if (pos < 0) { -482return file; -483 } -484 pos += 1; -485 basePath = file.substring(0, pos); -486 wildCards = file.substring(pos); -487 } else { -488 basePath = file; -489 } -490 -491 File f = new File(basePath); -492try { -493 f = f.getCanonicalFile(); -494if (wildCards != null) { -495 f = new File(f, wildCards); -496 } -497 } catch (IOException ex) { -498 LOGGER.warn("Invalid path '{}' was provided.", path); -499 LOGGER.debug("Invalid path provided", ex); -500 } -501return f.getAbsolutePath().replace('\\', '/'); -502 } -503 -504/** -505 * Returns the position of the last file separator. -506 * -507 * @param file a file path -508 * @return the position of the last file separator -509 */ -510privateint getLastFileSeparator(String file) { -511if (file.contains("*") || file.contains("?")) { -512int p1 = file.indexOf('*'); -513int p2 = file.indexOf('?'); -514 p1 = p1 > 0 ? p1 : file.length(); -515 p2 = p2 > 0 ? p2 : file.length(); -516int pos = p1 < p2 ? p1 : p2; -517 pos = file.lastIndexOf('/', pos); -518return pos; -519 } else { -520return file.lastIndexOf('/'); -521 } -522 } -523 } +22import ch.qos.logback.classic.spi.ILoggingEvent; +23import java.io.File; +24import java.io.FileNotFoundException; +25import java.io.IOException; +26import java.util.ArrayList; +27import java.util.HashSet; +28import java.util.List; +29import java.util.Set; +30import org.apache.commons.cli.ParseException; +31import org.owasp.dependencycheck.data.nvdcve.CveDB; +32import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +33import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; +34import org.owasp.dependencycheck.dependency.Dependency; +35import org.apache.tools.ant.DirectoryScanner; +36import org.owasp.dependencycheck.reporting.ReportGenerator; +37import org.owasp.dependencycheck.utils.Settings; +38import org.slf4j.Logger; +39import org.slf4j.LoggerFactory; +40import ch.qos.logback.core.FileAppender; +41import org.owasp.dependencycheck.data.update.exception.UpdateException; +42import org.owasp.dependencycheck.exception.ExceptionCollection; +43import org.owasp.dependencycheck.exception.ReportException; +44import org.owasp.dependencycheck.utils.InvalidSettingException; +45import org.slf4j.impl.StaticLoggerBinder; +46 +47/** +48 * The command line interface for the DependencyCheck application. +49 * +50 * @author Jeremy Long +51 */ +52publicclassApp { +53 +54/** +55 * The logger. +56 */ +57privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(App.class); +58 +59/** +60 * The main method for the application. +61 * +62 * @param args the command line arguments +63 */ +64publicstaticvoid main(String[] args) { +65int exitCode = 0; +66try { +67 Settings.initialize(); +68finalApp app = newApp(); +69 exitCode = app.run(args); +70 LOGGER.debug("Exit code: " + exitCode); +71 } finally { +72 Settings.cleanup(true); +73 } +74 System.exit(exitCode); +75 } +76 +77/** +78 * Main CLI entry-point into the application. +79 * +80 * @param args the command line arguments +81 * @return the exit code to return +82 */ +83publicint run(String[] args) { +84int exitCode = 0; +85finalCliParser cli = newCliParser(); +86 +87try { +88 cli.parse(args); +89 } catch (FileNotFoundException ex) { +90 System.err.println(ex.getMessage()); +91 cli.printHelp(); +92return -1; +93 } catch (ParseException ex) { +94 System.err.println(ex.getMessage()); +95 cli.printHelp(); +96return -2; +97 } +98 +99if (cli.getVerboseLog() != null) { +100 prepareLogger(cli.getVerboseLog()); +101 } +102 +103if (cli.isPurge()) { +104if (cli.getConnectionString() != null) { +105 LOGGER.error("Unable to purge the database when using a non-default connection string"); +106 exitCode = -3; +107 } else { +108try { +109 populateSettings(cli); +110 } catch (InvalidSettingException ex) { +111 LOGGER.error(ex.getMessage()); +112 LOGGER.debug("Error loading properties file", ex); +113 exitCode = -4; +114 } +115 File db; +116try { +117 db = new File(Settings.getDataDirectory(), "dc.h2.db"); +118if (db.exists()) { +119if (db.delete()) { +120 LOGGER.info("Database file purged; local copy of the NVD has been removed"); +121 } else { +122 LOGGER.error("Unable to delete '{}'; please delete the file manually", db.getAbsolutePath()); +123 exitCode = -5; +124 } +125 } else { +126 LOGGER.error("Unable to purge database; the database file does not exists: {}", db.getAbsolutePath()); +127 exitCode = -6; +128 } +129 } catch (IOException ex) { +130 LOGGER.error("Unable to delete the database"); +131 exitCode = -7; +132 } +133 } +134 } elseif (cli.isGetVersion()) { +135 cli.printVersionInfo(); +136 } elseif (cli.isUpdateOnly()) { +137try { +138 populateSettings(cli); +139 } catch (InvalidSettingException ex) { +140 LOGGER.error(ex.getMessage()); +141 LOGGER.debug("Error loading properties file", ex); +142 exitCode = -4; +143 } +144try { +145 runUpdateOnly(); +146 } catch (UpdateException ex) { +147 LOGGER.error(ex.getMessage()); +148 exitCode = -8; +149 } catch (DatabaseException ex) { +150 LOGGER.error(ex.getMessage()); +151 exitCode = -9; +152 } +153 } elseif (cli.isRunScan()) { +154try { +155 populateSettings(cli); +156 } catch (InvalidSettingException ex) { +157 LOGGER.error(ex.getMessage()); +158 LOGGER.debug("Error loading properties file", ex); +159 exitCode = -4; +160 } +161try { +162final String[] scanFiles = cli.getScanFiles(); +163if (scanFiles != null) { +164 runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles, +165 cli.getExcludeList(), cli.getSymLinkDepth()); +166 } else { +167 LOGGER.error("No scan files configured"); +168 } +169 } catch (InvalidScanPathException ex) { +170 LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths"); +171 exitCode = -10; +172 } catch (DatabaseException ex) { +173 LOGGER.error(ex.getMessage()); +174 exitCode = -11; +175 } catch (ReportException ex) { +176 LOGGER.error(ex.getMessage()); +177 exitCode = -12; +178 } catch (ExceptionCollection ex) { +179if (ex.isFatal()) { +180 exitCode = -13; +181 LOGGER.error("One or more fatal errors occurred"); +182 } else { +183 exitCode = -14; +184 } +185for (Throwable e : ex.getExceptions()) { +186 LOGGER.error(e.getMessage()); +187 } +188 } +189 } else { +190 cli.printHelp(); +191 } +192return exitCode; +193 } +194 +195/** +196 * Scans the specified directories and writes the dependency reports to the +197 * reportDirectory. +198 * +199 * @param reportDirectory the path to the directory where the reports will +200 * be written +201 * @param outputFormat the output format of the report +202 * @param applicationName the application name for the report +203 * @param files the files/directories to scan +204 * @param excludes the patterns for files/directories to exclude +205 * @param symLinkDepth the depth that symbolic links will be followed +206 * +207 * @throws InvalidScanPathException thrown if the path to scan starts with +208 * "//" +209 * @throws ReportException thrown when the report cannot be generated +210 * @throws DatabaseException thrown when there is an error connecting to the +211 * database +212 * @throws ExceptionCollection thrown when an exception occurs during +213 * analysis; there may be multiple exceptions contained within the +214 * collection. +215 */ +216privatevoid runScan(String reportDirectory, String outputFormat, String applicationName, String[] files, +217 String[] excludes, int symLinkDepth) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException { +218 Engine engine = null; +219try { +220 engine = new Engine(); +221final List<String> antStylePaths = new ArrayList<String>(); +222for (String file : files) { +223final String antPath = ensureCanonicalPath(file); +224 antStylePaths.add(antPath); +225 } +226 +227final Set<File> paths = new HashSet<File>(); +228for (String file : antStylePaths) { +229 LOGGER.debug("Scanning {}", file); +230final DirectoryScanner scanner = new DirectoryScanner(); +231 String include = file.replace('\\', '/'); +232 File baseDir; +233 +234if (include.startsWith("//")) { +235thrownewInvalidScanPathException("Unable to scan paths specified by //"); +236 } else { +237finalint pos = getLastFileSeparator(include); +238final String tmpBase = include.substring(0, pos); +239final String tmpInclude = include.substring(pos + 1); +240if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0 +241 || (new File(include)).isFile()) { +242 baseDir = new File(tmpBase); +243 include = tmpInclude; +244 } else { +245 baseDir = new File(tmpBase, tmpInclude); +246 include = "**/*"; +247 } +248 } +249 scanner.setBasedir(baseDir); +250final String[] includes = {include}; +251 scanner.setIncludes(includes); +252 scanner.setMaxLevelsOfSymlinks(symLinkDepth); +253if (symLinkDepth <= 0) { +254 scanner.setFollowSymlinks(false); +255 } +256if (excludes != null && excludes.length > 0) { +257 scanner.addExcludes(excludes); +258 } +259 scanner.scan(); +260if (scanner.getIncludedFilesCount() > 0) { +261for (String s : scanner.getIncludedFiles()) { +262final File f = new File(baseDir, s); +263 LOGGER.debug("Found file {}", f.toString()); +264 paths.add(f); +265 } +266 } +267 } +268 engine.scan(paths); +269 +270 ExceptionCollection exCol = null; +271try { +272 engine.analyzeDependencies(); +273 } catch (ExceptionCollection ex) { +274if (ex.isFatal()) { +275throw ex; +276 } +277 exCol = ex; +278 } +279final List<Dependency> dependencies = engine.getDependencies(); +280 DatabaseProperties prop = null; +281 CveDB cve = null; +282try { +283 cve = new CveDB(); +284 cve.open(); +285 prop = cve.getDatabaseProperties(); +286 } finally { +287if (cve != null) { +288 cve.close(); +289 } +290 } +291final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop); +292try { +293 report.generateReports(reportDirectory, outputFormat); +294 } catch (ReportException ex) { +295if (exCol != null) { +296 exCol.addException(ex); +297throw exCol; +298 } else { +299throw ex; +300 } +301 } +302if (exCol != null && exCol.getExceptions().size() > 0) { +303throw exCol; +304 } +305 } finally { +306if (engine != null) { +307 engine.cleanup(); +308 } +309 } +310 +311 } +312 +313/** +314 * Only executes the update phase of dependency-check. +315 * +316 * @throws UpdateException thrown if there is an error updating +317 * @throws DatabaseException thrown if a fatal error occurred and a +318 * connection to the database could not be established +319 */ +320privatevoid runUpdateOnly() throws UpdateException, DatabaseException { +321 Engine engine = null; +322try { +323 engine = new Engine(); +324 engine.doUpdates(); +325 } finally { +326if (engine != null) { +327 engine.cleanup(); +328 } +329 } +330 } +331 +332/** +333 * Updates the global Settings. +334 * +335 * @param cli a reference to the CLI Parser that contains the command line +336 * arguments used to set the corresponding settings in the core engine. +337 * +338 * @throws InvalidSettingException thrown when a user defined properties +339 * file is unable to be loaded. +340 */ +341privatevoid populateSettings(CliParser cli) throws InvalidSettingException { +342finalboolean autoUpdate = cli.isAutoUpdate(); +343final String connectionTimeout = cli.getConnectionTimeout(); +344final String proxyServer = cli.getProxyServer(); +345final String proxyPort = cli.getProxyPort(); +346final String proxyUser = cli.getProxyUsername(); +347final String proxyPass = cli.getProxyPassword(); +348final String dataDirectory = cli.getDataDirectory(); +349final File propertiesFile = cli.getPropertiesFile(); +350final String suppressionFile = cli.getSuppressionFile(); +351final String hintsFile = cli.getHintsFile(); +352final String nexusUrl = cli.getNexusUrl(); +353final String databaseDriverName = cli.getDatabaseDriverName(); +354final String databaseDriverPath = cli.getDatabaseDriverPath(); +355final String connectionString = cli.getConnectionString(); +356final String databaseUser = cli.getDatabaseUser(); +357final String databasePassword = cli.getDatabasePassword(); +358final String additionalZipExtensions = cli.getAdditionalZipExtensions(); +359final String pathToMono = cli.getPathToMono(); +360final String cveMod12 = cli.getModifiedCve12Url(); +361final String cveMod20 = cli.getModifiedCve20Url(); +362final String cveBase12 = cli.getBaseCve12Url(); +363final String cveBase20 = cli.getBaseCve20Url(); +364final Integer cveValidForHours = cli.getCveValidForHours(); +365finalboolean experimentalEnabled = cli.isExperimentalEnabled(); +366 +367if (propertiesFile != null) { +368try { +369 Settings.mergeProperties(propertiesFile); +370 } catch (FileNotFoundException ex) { +371thrownew InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex); +372 } catch (IOException ex) { +373thrownew InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex); +374 } +375 } +376// We have to wait until we've merged the properties before attempting to set whether we use +377// the proxy for Nexus since it could be disabled in the properties, but not explicitly stated +378// on the command line +379finalboolean nexusUsesProxy = cli.isNexusUsesProxy(); +380if (dataDirectory != null) { +381 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory); +382 } elseif (System.getProperty("basedir") != null) { +383final File dataDir = new File(System.getProperty("basedir"), "data"); +384 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); +385 } else { +386final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath()); +387final File base = jarPath.getParentFile(); +388final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY); +389final File dataDir = new File(base, sub); +390 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); +391 } +392 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); +393 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer); +394 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort); +395 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser); +396 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPass); +397 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); +398 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); +399 Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile); +400 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); +401 +402//File Type Analyzer Settings +403 Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled); +404 Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled()); +405 Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled()); +406 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled()); +407 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !cli.isPythonPackageDisabled()); +408 Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, !cli.isAutoconfDisabled()); +409 Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, !cli.isCmakeDisabled()); +410 Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !cli.isNuspecDisabled()); +411 Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !cli.isAssemblyDisabled()); +412 Settings.setBoolean(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, !cli.isBundleAuditDisabled()); +413 Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, !cli.isOpenSSLDisabled()); +414 Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, !cli.isComposerDisabled()); +415 Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, !cli.isNodeJsDisabled()); +416 Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, !cli.isRubyGemspecDisabled()); +417 Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !cli.isCentralDisabled()); +418 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !cli.isNexusDisabled()); +419 +420 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, cli.getPathToBundleAudit()); +421 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); +422 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); +423 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); +424 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); +425 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); +426 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); +427 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); +428 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions); +429 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); +430if (cveBase12 != null && !cveBase12.isEmpty()) { +431 Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveBase12); +432 Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveBase20); +433 Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveMod12); +434 Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveMod20); +435 } +436 } +437 +438/** +439 * Creates a file appender and adds it to logback. +440 * +441 * @param verboseLog the path to the verbose log file +442 */ +443privatevoid prepareLogger(String verboseLog) { +444final StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton(); +445final LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory(); +446 +447final PatternLayoutEncoder encoder = new PatternLayoutEncoder(); +448 encoder.setPattern("%d %C:%L%n%-5level - %msg%n"); +449 encoder.setContext(context); +450 encoder.start(); +451final FileAppender<ILoggingEvent> fa = new FileAppender<ILoggingEvent>(); +452 fa.setAppend(true); +453 fa.setEncoder(encoder); +454 fa.setContext(context); +455 fa.setFile(verboseLog); +456final File f = new File(verboseLog); +457 String name = f.getName(); +458finalint i = name.lastIndexOf('.'); +459if (i > 1) { +460 name = name.substring(0, i); +461 } +462 fa.setName(name); +463 fa.start(); +464final ch.qos.logback.classic.Logger rootLogger = context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); +465 rootLogger.addAppender(fa); +466 } +467 +468/** +469 * Takes a path and resolves it to be a canonical &amp; absolute path. The +470 * caveats are that this method will take an Ant style file selector path +471 * (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at +472 * least to the left of the first * or ?). +473 * +474 * @param path the path to canonicalize +475 * @return the canonical path +476 */ +477protected String ensureCanonicalPath(String path) { +478 String basePath; +479 String wildCards = null; +480final String file = path.replace('\\', '/'); +481if (file.contains("*") || file.contains("?")) { +482 +483int pos = getLastFileSeparator(file); +484if (pos < 0) { +485return file; +486 } +487 pos += 1; +488 basePath = file.substring(0, pos); +489 wildCards = file.substring(pos); +490 } else { +491 basePath = file; +492 } +493 +494 File f = new File(basePath); +495try { +496 f = f.getCanonicalFile(); +497if (wildCards != null) { +498 f = new File(f, wildCards); +499 } +500 } catch (IOException ex) { +501 LOGGER.warn("Invalid path '{}' was provided.", path); +502 LOGGER.debug("Invalid path provided", ex); +503 } +504return f.getAbsolutePath().replace('\\', '/'); +505 } +506 +507/** +508 * Returns the position of the last file separator. +509 * +510 * @param file a file path +511 * @return the position of the last file separator +512 */ +513privateint getLastFileSeparator(String file) { +514if (file.contains("*") || file.contains("?")) { +515int p1 = file.indexOf('*'); +516int p2 = file.indexOf('?'); +517 p1 = p1 > 0 ? p1 : file.length(); +518 p2 = p2 > 0 ? p2 : file.length(); +519int pos = p1 < p2 ? p1 : p2; +520 pos = file.lastIndexOf('/', pos); +521return pos; +522 } else { +523return file.lastIndexOf('/'); +524 } +525 } +526 }
      diff --git a/dependency-check-cli/xref/org/owasp/dependencycheck/CliParser.html b/dependency-check-cli/xref/org/owasp/dependencycheck/CliParser.html index 133d1cec5..4b3456f45 100644 --- a/dependency-check-cli/xref/org/owasp/dependencycheck/CliParser.html +++ b/dependency-check-cli/xref/org/owasp/dependencycheck/CliParser.html @@ -285,1120 +285,1139 @@ 277 .desc("The file path to the suppression XML file.") 278 .build(); 279 -280final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS) -281 .desc("The number of hours to wait before checking for new updates from the NVD.") +280final Option hintsFile = Option.builder().argName("file").hasArg().longOpt(ARGUMENT.HINTS_FILE) +281 .desc("The file path to the hints XML file.") 282 .build(); 283 -284final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL) -285 .desc("Enables the experimental analzers.") +284final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS) +285 .desc("The number of hours to wait before checking for new updates from the NVD.") 286 .build(); 287 -288//This is an option group because it can be specified more then once. -289final OptionGroup og = new OptionGroup(); -290 og.addOption(path); +288final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL) +289 .desc("Enables the experimental analzers.") +290 .build(); 291 -292final OptionGroup exog = new OptionGroup(); -293 exog.addOption(excludes); -294 -295 options.addOptionGroup(og) -296 .addOptionGroup(exog) -297 .addOption(projectName) -298 .addOption(out) -299 .addOption(outputFormat) -300 .addOption(version) -301 .addOption(help) -302 .addOption(advancedHelp) -303 .addOption(noUpdate) -304 .addOption(symLinkDepth) -305 .addOption(props) -306 .addOption(verboseLog) -307 .addOption(suppressionFile) -308 .addOption(cveValidForHours) -309 .addOption(experimentalEnabled); -310 } -311 -312/** -313 * Adds the advanced command line options to the given options collection. -314 * These are split out for purposes of being able to display two different -315 * help messages. -316 * -317 * @param options a collection of command line arguments -318 * @throws IllegalArgumentException thrown if there is an exception -319 */ -320 @SuppressWarnings("static-access") -321privatevoid addAdvancedOptions(final Options options) throws IllegalArgumentException { -322 -323final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12) -324 .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ") -325 .build(); -326 -327final Option cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20) -328 .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.") -329 .build(); -330 -331final Option cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12) -332 .desc("URL for the modified CVE 1.2.") -333 .build(); -334 -335final Option cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20) -336 .desc("URL for the modified CVE 2.0.") -337 .build(); -338 -339final Option updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY) -340 .desc("Only update the local NVD data cache; no scan will be executed.").build(); -341 -342final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY) -343 .desc("The location of the H2 Database file. This option should generally not be set.") -344 .build(); -345 -346final Option nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL) -347 .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). " -348 + "If not set the Nexus Analyzer will be disabled.").build(); -349 -350final Option nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY) -351 .desc("Whether or not the configured proxy should be used when connecting to Nexus.") -352 .build(); -353 -354final Option additionalZipExtensions = Option.builder().argName("extensions").hasArg() -355 .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS) -356 .desc("A comma separated list of additional extensions to be scanned as ZIP files " -357 + "(ZIP, EAR, WAR are already treated as zip files)").build(); +292//This is an option group because it can be specified more then once. +293final OptionGroup og = new OptionGroup(); +294 og.addOption(path); +295 +296final OptionGroup exog = new OptionGroup(); +297 exog.addOption(excludes); +298 +299 options.addOptionGroup(og) +300 .addOptionGroup(exog) +301 .addOption(projectName) +302 .addOption(out) +303 .addOption(outputFormat) +304 .addOption(version) +305 .addOption(help) +306 .addOption(advancedHelp) +307 .addOption(noUpdate) +308 .addOption(symLinkDepth) +309 .addOption(props) +310 .addOption(verboseLog) +311 .addOption(suppressionFile) +312 .addOption(hintsFile) +313 .addOption(cveValidForHours) +314 .addOption(experimentalEnabled); +315 } +316 +317/** +318 * Adds the advanced command line options to the given options collection. +319 * These are split out for purposes of being able to display two different +320 * help messages. +321 * +322 * @param options a collection of command line arguments +323 * @throws IllegalArgumentException thrown if there is an exception +324 */ +325 @SuppressWarnings("static-access") +326privatevoid addAdvancedOptions(final Options options) throws IllegalArgumentException { +327 +328final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12) +329 .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ") +330 .build(); +331 +332final Option cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20) +333 .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.") +334 .build(); +335 +336final Option cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12) +337 .desc("URL for the modified CVE 1.2.") +338 .build(); +339 +340final Option cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20) +341 .desc("URL for the modified CVE 2.0.") +342 .build(); +343 +344final Option updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY) +345 .desc("Only update the local NVD data cache; no scan will be executed.").build(); +346 +347final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY) +348 .desc("The location of the H2 Database file. This option should generally not be set.") +349 .build(); +350 +351final Option nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL) +352 .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). " +353 + "If not set the Nexus Analyzer will be disabled.").build(); +354 +355final Option nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY) +356 .desc("Whether or not the configured proxy should be used when connecting to Nexus.") +357 .build(); 358 -359final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO) -360 .desc("The path to Mono for .NET Assembly analysis on non-windows systems.") -361 .build(); -362 -363final Option pathToBundleAudit = Option.builder().argName("path").hasArg() -364 .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT) -365 .desc("The path to bundle-audit for Gem bundle analysis.").build(); -366 -367final Option connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg() -368 .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.") -369 .build(); -370 -371final Option proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER) -372 .desc("The proxy server to use when downloading resources.").build(); -373 -374final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT) -375 .desc("The proxy port to use when downloading resources.").build(); -376 -377final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME) -378 .desc("The proxy username to use when downloading resources.").build(); -379 -380final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD) -381 .desc("The proxy password to use when downloading resources.").build(); -382 -383final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING) -384 .desc("The connection string to the database.").build(); -385 -386final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME) -387 .desc("The username used to connect to the database.").build(); -388 -389final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD) -390 .desc("The password for connecting to the database.").build(); -391 -392final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER) -393 .desc("The database driver name.").build(); -394 -395final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH) -396 .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.") -397 .build(); -398 -399final Option disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR) -400 .desc("Disable the Jar Analyzer.").build(); -401 -402final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE) -403 .desc("Disable the Archive Analyzer.").build(); -404 -405final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC) -406 .desc("Disable the Nuspec Analyzer.").build(); -407 -408final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY) -409 .desc("Disable the .NET Assembly Analyzer.").build(); -410 -411final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST) -412 .desc("Disable the Python Distribution Analyzer.").build(); -413 -414final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG) -415 .desc("Disable the Python Package Analyzer.").build(); -416 -417final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER) -418 .desc("Disable the PHP Composer Analyzer.").build(); -419 -420final Option disableAutoconfAnalyzer = Option.builder() -421 .longOpt(ARGUMENT.DISABLE_AUTOCONF) -422 .desc("Disable the Autoconf Analyzer.").build(); -423 -424final Option disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL) -425 .desc("Disable the OpenSSL Analyzer.").build(); -426final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE) -427 .desc("Disable the Cmake Analyzer.").build(); +359final Option additionalZipExtensions = Option.builder().argName("extensions").hasArg() +360 .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS) +361 .desc("A comma separated list of additional extensions to be scanned as ZIP files " +362 + "(ZIP, EAR, WAR are already treated as zip files)").build(); +363 +364final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO) +365 .desc("The path to Mono for .NET Assembly analysis on non-windows systems.") +366 .build(); +367 +368final Option pathToBundleAudit = Option.builder().argName("path").hasArg() +369 .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT) +370 .desc("The path to bundle-audit for Gem bundle analysis.").build(); +371 +372final Option connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg() +373 .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.") +374 .build(); +375 +376final Option proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER) +377 .desc("The proxy server to use when downloading resources.").build(); +378 +379final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT) +380 .desc("The proxy port to use when downloading resources.").build(); +381 +382final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME) +383 .desc("The proxy username to use when downloading resources.").build(); +384 +385final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD) +386 .desc("The proxy password to use when downloading resources.").build(); +387 +388final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING) +389 .desc("The connection string to the database.").build(); +390 +391final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME) +392 .desc("The username used to connect to the database.").build(); +393 +394final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD) +395 .desc("The password for connecting to the database.").build(); +396 +397final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER) +398 .desc("The database driver name.").build(); +399 +400final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH) +401 .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.") +402 .build(); +403 +404final Option disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR) +405 .desc("Disable the Jar Analyzer.").build(); +406 +407final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE) +408 .desc("Disable the Archive Analyzer.").build(); +409 +410final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC) +411 .desc("Disable the Nuspec Analyzer.").build(); +412 +413final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY) +414 .desc("Disable the .NET Assembly Analyzer.").build(); +415 +416final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST) +417 .desc("Disable the Python Distribution Analyzer.").build(); +418 +419final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG) +420 .desc("Disable the Python Package Analyzer.").build(); +421 +422final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER) +423 .desc("Disable the PHP Composer Analyzer.").build(); +424 +425final Option disableAutoconfAnalyzer = Option.builder() +426 .longOpt(ARGUMENT.DISABLE_AUTOCONF) +427 .desc("Disable the Autoconf Analyzer.").build(); 428 -429final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL) -430 .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable " -431 + "the Nexus Analyzer.").build(); -432 -433final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS) -434 .desc("Disable the Nexus Analyzer.").build(); -435 -436final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD) -437 .desc("Purges the local NVD data cache") -438 .build(); -439 -440 options.addOption(updateOnly) -441 .addOption(cve12Base) -442 .addOption(cve20Base) -443 .addOption(cve12Modified) -444 .addOption(cve20Modified) -445 .addOption(proxyPort) -446 .addOption(proxyServer) -447 .addOption(proxyUsername) -448 .addOption(proxyPassword) -449 .addOption(connectionTimeout) -450 .addOption(connectionString) -451 .addOption(dbUser) -452 .addOption(data) -453 .addOption(dbPassword) -454 .addOption(dbDriver) -455 .addOption(dbDriverPath) -456 .addOption(disableJarAnalyzer) -457 .addOption(disableArchiveAnalyzer) -458 .addOption(disableAssemblyAnalyzer) -459 .addOption(pathToBundleAudit) -460 .addOption(disablePythonDistributionAnalyzer) -461 .addOption(disableCmakeAnalyzer) -462 .addOption(disablePythonPackageAnalyzer) -463 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS) -464 .desc("Disable the Ruby Gemspec Analyzer.").build()) -465 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT) -466 .desc("Disable the Ruby Bundler-Audit Analyzer.").build()) -467 .addOption(disableAutoconfAnalyzer) -468 .addOption(disableComposerAnalyzer) -469 .addOption(disableOpenSSLAnalyzer) -470 .addOption(disableNuspecAnalyzer) -471 .addOption(disableCentralAnalyzer) -472 .addOption(disableNexusAnalyzer) -473 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS) -474 .desc("Disable the Node.js Package Analyzer.").build()) -475 .addOption(nexusUrl) -476 .addOption(nexusUsesProxy) -477 .addOption(additionalZipExtensions) -478 .addOption(pathToMono) -479 .addOption(pathToBundleAudit) -480 .addOption(purge); -481 } -482 -483/** -484 * Adds the deprecated command line options to the given options collection. -485 * These are split out for purposes of not including them in the help -486 * message. We need to add the deprecated options so as not to break -487 * existing scripts. -488 * -489 * @param options a collection of command line arguments -490 * @throws IllegalArgumentException thrown if there is an exception -491 */ -492 @SuppressWarnings({"static-access", "deprecation"}) -493privatevoid addDeprecatedOptions(final Options options) throws IllegalArgumentException { -494 -495final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL) -496 .desc("The proxy url argument is deprecated, use proxyserver instead.") -497 .build(); -498final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME) -499 .desc("The name of the project being scanned.") -500 .build(); -501 -502 options.addOption(proxyServer); -503 options.addOption(appName); -504 } -505 -506/** -507 * Determines if the 'version' command line argument was passed in. -508 * -509 * @return whether or not the 'version' command line argument was passed in -510 */ -511publicboolean isGetVersion() { -512return (line != null) && line.hasOption(ARGUMENT.VERSION); -513 } -514 -515/** -516 * Determines if the 'help' command line argument was passed in. -517 * -518 * @return whether or not the 'help' command line argument was passed in -519 */ -520publicboolean isGetHelp() { -521return (line != null) && line.hasOption(ARGUMENT.HELP); -522 } -523 -524/** -525 * Determines if the 'scan' command line argument was passed in. -526 * -527 * @return whether or not the 'scan' command line argument was passed in -528 */ -529publicboolean isRunScan() { -530return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN); -531 } -532 -533/** -534 * Returns the symbolic link depth (how deeply symbolic links will be -535 * followed). -536 * -537 * @return the symbolic link depth -538 */ -539publicint getSymLinkDepth() { -540int value = 0; -541try { -542 value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0")); -543if (value < 0) { -544 value = 0; -545 } -546 } catch (NumberFormatException ex) { -547 LOGGER.debug("Symbolic link was not a number"); -548 } -549return value; -550 } -551 -552/** -553 * Returns true if the disableJar command line argument was specified. -554 * -555 * @return true if the disableJar command line argument was specified; -556 * otherwise false -557 */ -558publicboolean isJarDisabled() { -559return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR); -560 } -561 -562/** -563 * Returns true if the disableArchive command line argument was specified. -564 * -565 * @return true if the disableArchive command line argument was specified; -566 * otherwise false -567 */ -568publicboolean isArchiveDisabled() { -569return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE); -570 } -571 -572/** -573 * Returns true if the disableNuspec command line argument was specified. -574 * -575 * @return true if the disableNuspec command line argument was specified; -576 * otherwise false -577 */ -578publicboolean isNuspecDisabled() { -579return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC); -580 } -581 -582/** -583 * Returns true if the disableAssembly command line argument was specified. -584 * -585 * @return true if the disableAssembly command line argument was specified; -586 * otherwise false -587 */ -588publicboolean isAssemblyDisabled() { -589return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY); -590 } -591 -592/** -593 * Returns true if the disableBundleAudit command line argument was -594 * specified. -595 * -596 * @return true if the disableBundleAudit command line argument was -597 * specified; otherwise false -598 */ -599publicboolean isBundleAuditDisabled() { -600return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT); -601 } -602 -603/** -604 * Returns true if the disablePyDist command line argument was specified. -605 * -606 * @return true if the disablePyDist command line argument was specified; -607 * otherwise false -608 */ -609publicboolean isPythonDistributionDisabled() { -610return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST); -611 } -612 -613/** -614 * Returns true if the disablePyPkg command line argument was specified. -615 * -616 * @return true if the disablePyPkg command line argument was specified; -617 * otherwise false -618 */ -619publicboolean isPythonPackageDisabled() { -620return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG); -621 } -622 -623/** -624 * Returns whether the Ruby gemspec analyzer is disabled. -625 * -626 * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line -627 * argument was specified; otherwise false -628 */ -629publicboolean isRubyGemspecDisabled() { -630return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS); -631 } -632 -633/** -634 * Returns true if the disableCmake command line argument was specified. -635 * -636 * @return true if the disableCmake command line argument was specified; -637 * otherwise false -638 */ -639publicboolean isCmakeDisabled() { -640return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE); -641 } -642 -643/** -644 * Returns true if the disableAutoconf command line argument was specified. -645 * -646 * @return true if the disableAutoconf command line argument was specified; -647 * otherwise false -648 */ -649publicboolean isAutoconfDisabled() { -650return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF); -651 } -652 -653/** -654 * Returns true if the disableComposer command line argument was specified. -655 * -656 * @return true if the disableComposer command line argument was specified; -657 * otherwise false -658 */ -659publicboolean isComposerDisabled() { -660return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER); -661 } -662 -663/** -664 * Returns true if the disableNexus command line argument was specified. -665 * -666 * @return true if the disableNexus command line argument was specified; -667 * otherwise false -668 */ -669publicboolean isNexusDisabled() { -670return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS); -671 } -672 -673/** -674 * Returns true if the disableOpenSSL command line argument was specified. -675 * -676 * @return true if the disableOpenSSL command line argument was specified; -677 * otherwise false -678 */ -679publicboolean isOpenSSLDisabled() { -680return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL); -681 } -682 -683/** -684 * Returns true if the disableNodeJS command line argument was specified. -685 * -686 * @return true if the disableNodeJS command line argument was specified; -687 * otherwise false -688 */ -689publicboolean isNodeJsDisabled() { -690return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS); -691 } -692 -693/** -694 * Returns true if the disableCentral command line argument was specified. -695 * -696 * @return true if the disableCentral command line argument was specified; -697 * otherwise false -698 */ -699publicboolean isCentralDisabled() { -700return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL); -701 } -702 -703/** -704 * Returns the url to the nexus server if one was specified. -705 * -706 * @return the url to the nexus server; if none was specified this will -707 * return null; -708 */ -709public String getNexusUrl() { -710if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) { -711returnnull; -712 } else { -713return line.getOptionValue(ARGUMENT.NEXUS_URL); -714 } -715 } -716 -717/** -718 * Returns true if the Nexus Analyzer should use the configured proxy to -719 * connect to Nexus; otherwise false is returned. -720 * -721 * @return true if the Nexus Analyzer should use the configured proxy to -722 * connect to Nexus; otherwise false -723 */ -724publicboolean isNexusUsesProxy() { -725// If they didn't specify whether Nexus needs to use the proxy, we should -726// still honor the property if it's set. -727if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) { -728try { -729return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY); -730 } catch (InvalidSettingException ise) { -731returntrue; -732 } -733 } else { -734return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY)); -735 } -736 } -737 -738/** -739 * Displays the command line help message to the standard output. -740 */ -741publicvoid printHelp() { -742final HelpFormatter formatter = new HelpFormatter(); -743final Options options = new Options(); -744 addStandardOptions(options); -745if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) { -746 addAdvancedOptions(options); -747 } -748final String helpMsg = String.format("%n%s" -749 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. " -750 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n", -751 Settings.getString("application.name", "DependencyCheck"), -752 Settings.getString("application.name", "DependencyCheck")); -753 -754 formatter.printHelp(Settings.getString("application.name", "DependencyCheck"), -755 helpMsg, -756 options, -757"", -758true); -759 } -760 -761/** -762 * Retrieves the file command line parameter(s) specified for the 'scan' -763 * argument. -764 * -765 * @return the file paths specified on the command line for scan -766 */ -767public String[] getScanFiles() { -768return line.getOptionValues(ARGUMENT.SCAN); -769 } -770 -771/** -772 * Retrieves the list of excluded file patterns specified by the 'exclude' -773 * argument. -774 * -775 * @return the excluded file patterns -776 */ -777public String[] getExcludeList() { -778return line.getOptionValues(ARGUMENT.EXCLUDE); -779 } -780 -781/** -782 * Returns the directory to write the reports to specified on the command -783 * line. -784 * -785 * @return the path to the reports directory. -786 */ -787public String getReportDirectory() { -788return line.getOptionValue(ARGUMENT.OUT, "."); -789 } -790 -791/** -792 * Returns the path to Mono for .NET Assembly analysis on non-windows -793 * systems. -794 * -795 * @return the path to Mono -796 */ -797public String getPathToMono() { -798return line.getOptionValue(ARGUMENT.PATH_TO_MONO); -799 } -800 -801/** -802 * Returns the path to bundle-audit for Ruby bundle analysis. -803 * -804 * @return the path to Mono -805 */ -806public String getPathToBundleAudit() { -807return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT); -808 } -809 -810/** -811 * Returns the output format specified on the command line. Defaults to HTML -812 * if no format was specified. -813 * -814 * @return the output format name. -815 */ -816public String getReportFormat() { -817return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML"); -818 } -819 -820/** -821 * Returns the application name specified on the command line. -822 * -823 * @return the application name. -824 */ -825public String getProjectName() { -826final String appName = line.getOptionValue(ARGUMENT.APP_NAME); -827 String name = line.getOptionValue(ARGUMENT.PROJECT); -828if (name == null && appName != null) { -829 name = appName; -830 LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead."); -831 } -832return name; -833 } -834 -835/** -836 * Returns the base URL for the CVE 1.2 XMl file. -837 * -838 * @return the URL to the CVE 1.2 XML file. -839 */ -840public String getBaseCve12Url() { -841return line.getOptionValue(ARGUMENT.CVE_BASE_12); -842 } -843 -844/** -845 * Returns the base URL for the CVE 2.0 XMl file. -846 * -847 * @return the URL to the CVE 2.0 XML file. -848 */ -849public String getBaseCve20Url() { -850return line.getOptionValue(ARGUMENT.CVE_BASE_20); -851 } -852 -853/** -854 * Returns the URL for the modified CVE 1.2 XMl file. -855 * -856 * @return the URL to the modified CVE 1.2 XML file. -857 */ -858public String getModifiedCve12Url() { -859return line.getOptionValue(ARGUMENT.CVE_MOD_12); -860 } -861 -862/** -863 * Returns the URL for the modified CVE 2.0 XMl file. -864 * -865 * @return the URL to the modified CVE 2.0 XML file. -866 */ -867public String getModifiedCve20Url() { -868return line.getOptionValue(ARGUMENT.CVE_MOD_20); -869 } -870 -871/** -872 * Returns the connection timeout. -873 * -874 * @return the connection timeout -875 */ -876public String getConnectionTimeout() { -877return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT); -878 } -879 -880/** -881 * Returns the proxy server. -882 * -883 * @return the proxy server -884 */ -885 @SuppressWarnings("deprecation") -886public String getProxyServer() { -887 -888 String server = line.getOptionValue(ARGUMENT.PROXY_SERVER); -889if (server == null) { -890 server = line.getOptionValue(ARGUMENT.PROXY_URL); -891if (server != null) { -892 LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead"); -893 } -894 } -895return server; -896 } -897 -898/** -899 * Returns the proxy port. -900 * -901 * @return the proxy port -902 */ -903public String getProxyPort() { -904return line.getOptionValue(ARGUMENT.PROXY_PORT); -905 } -906 -907/** -908 * Returns the proxy username. -909 * -910 * @return the proxy username -911 */ -912public String getProxyUsername() { -913return line.getOptionValue(ARGUMENT.PROXY_USERNAME); -914 } -915 -916/** -917 * Returns the proxy password. -918 * -919 * @return the proxy password -920 */ -921public String getProxyPassword() { -922return line.getOptionValue(ARGUMENT.PROXY_PASSWORD); -923 } -924 -925/** -926 * Get the value of dataDirectory. -927 * -928 * @return the value of dataDirectory -929 */ -930public String getDataDirectory() { -931return line.getOptionValue(ARGUMENT.DATA_DIRECTORY); -932 } -933 -934/** -935 * Returns the properties file specified on the command line. -936 * -937 * @return the properties file specified on the command line -938 */ -939public File getPropertiesFile() { -940final String path = line.getOptionValue(ARGUMENT.PROP); -941if (path != null) { -942returnnew File(path); -943 } -944returnnull; -945 } -946 -947/** -948 * Returns the path to the verbose log file. -949 * -950 * @return the path to the verbose log file -951 */ -952public String getVerboseLog() { -953return line.getOptionValue(ARGUMENT.VERBOSE_LOG); -954 } -955 -956/** -957 * Returns the path to the suppression file. -958 * -959 * @return the path to the suppression file -960 */ -961public String getSuppressionFile() { -962return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE); -963 } -964 -965/** -966 * <p> -967 * Prints the manifest information to standard output.</p> -968 * <ul><li>Implementation-Title: ${pom.name}</li> -969 * <li>Implementation-Version: ${pom.version}</li></ul> -970 */ -971publicvoid printVersionInfo() { -972final String version = String.format("%s version %s", -973 Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"), -974 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown")); -975 System.out.println(version); -976 } -977 -978/** -979 * Checks if the auto update feature has been disabled. If it has been -980 * disabled via the command line this will return false. -981 * -982 * @return <code>true</code> if auto-update is allowed; otherwise -983 * <code>false</code> +429final Option disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL) +430 .desc("Disable the OpenSSL Analyzer.").build(); +431final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE) +432 .desc("Disable the Cmake Analyzer.").build(); +433 +434final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL) +435 .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable " +436 + "the Nexus Analyzer.").build(); +437 +438final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS) +439 .desc("Disable the Nexus Analyzer.").build(); +440 +441final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD) +442 .desc("Purges the local NVD data cache") +443 .build(); +444 +445 options.addOption(updateOnly) +446 .addOption(cve12Base) +447 .addOption(cve20Base) +448 .addOption(cve12Modified) +449 .addOption(cve20Modified) +450 .addOption(proxyPort) +451 .addOption(proxyServer) +452 .addOption(proxyUsername) +453 .addOption(proxyPassword) +454 .addOption(connectionTimeout) +455 .addOption(connectionString) +456 .addOption(dbUser) +457 .addOption(data) +458 .addOption(dbPassword) +459 .addOption(dbDriver) +460 .addOption(dbDriverPath) +461 .addOption(disableJarAnalyzer) +462 .addOption(disableArchiveAnalyzer) +463 .addOption(disableAssemblyAnalyzer) +464 .addOption(pathToBundleAudit) +465 .addOption(disablePythonDistributionAnalyzer) +466 .addOption(disableCmakeAnalyzer) +467 .addOption(disablePythonPackageAnalyzer) +468 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS) +469 .desc("Disable the Ruby Gemspec Analyzer.").build()) +470 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT) +471 .desc("Disable the Ruby Bundler-Audit Analyzer.").build()) +472 .addOption(disableAutoconfAnalyzer) +473 .addOption(disableComposerAnalyzer) +474 .addOption(disableOpenSSLAnalyzer) +475 .addOption(disableNuspecAnalyzer) +476 .addOption(disableCentralAnalyzer) +477 .addOption(disableNexusAnalyzer) +478 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS) +479 .desc("Disable the Node.js Package Analyzer.").build()) +480 .addOption(nexusUrl) +481 .addOption(nexusUsesProxy) +482 .addOption(additionalZipExtensions) +483 .addOption(pathToMono) +484 .addOption(pathToBundleAudit) +485 .addOption(purge); +486 } +487 +488/** +489 * Adds the deprecated command line options to the given options collection. +490 * These are split out for purposes of not including them in the help +491 * message. We need to add the deprecated options so as not to break +492 * existing scripts. +493 * +494 * @param options a collection of command line arguments +495 * @throws IllegalArgumentException thrown if there is an exception +496 */ +497 @SuppressWarnings({"static-access", "deprecation"}) +498privatevoid addDeprecatedOptions(final Options options) throws IllegalArgumentException { +499 +500final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL) +501 .desc("The proxy url argument is deprecated, use proxyserver instead.") +502 .build(); +503final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME) +504 .desc("The name of the project being scanned.") +505 .build(); +506 +507 options.addOption(proxyServer); +508 options.addOption(appName); +509 } +510 +511/** +512 * Determines if the 'version' command line argument was passed in. +513 * +514 * @return whether or not the 'version' command line argument was passed in +515 */ +516publicboolean isGetVersion() { +517return (line != null) && line.hasOption(ARGUMENT.VERSION); +518 } +519 +520/** +521 * Determines if the 'help' command line argument was passed in. +522 * +523 * @return whether or not the 'help' command line argument was passed in +524 */ +525publicboolean isGetHelp() { +526return (line != null) && line.hasOption(ARGUMENT.HELP); +527 } +528 +529/** +530 * Determines if the 'scan' command line argument was passed in. +531 * +532 * @return whether or not the 'scan' command line argument was passed in +533 */ +534publicboolean isRunScan() { +535return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN); +536 } +537 +538/** +539 * Returns the symbolic link depth (how deeply symbolic links will be +540 * followed). +541 * +542 * @return the symbolic link depth +543 */ +544publicint getSymLinkDepth() { +545int value = 0; +546try { +547 value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0")); +548if (value < 0) { +549 value = 0; +550 } +551 } catch (NumberFormatException ex) { +552 LOGGER.debug("Symbolic link was not a number"); +553 } +554return value; +555 } +556 +557/** +558 * Returns true if the disableJar command line argument was specified. +559 * +560 * @return true if the disableJar command line argument was specified; +561 * otherwise false +562 */ +563publicboolean isJarDisabled() { +564return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR); +565 } +566 +567/** +568 * Returns true if the disableArchive command line argument was specified. +569 * +570 * @return true if the disableArchive command line argument was specified; +571 * otherwise false +572 */ +573publicboolean isArchiveDisabled() { +574return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE); +575 } +576 +577/** +578 * Returns true if the disableNuspec command line argument was specified. +579 * +580 * @return true if the disableNuspec command line argument was specified; +581 * otherwise false +582 */ +583publicboolean isNuspecDisabled() { +584return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC); +585 } +586 +587/** +588 * Returns true if the disableAssembly command line argument was specified. +589 * +590 * @return true if the disableAssembly command line argument was specified; +591 * otherwise false +592 */ +593publicboolean isAssemblyDisabled() { +594return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY); +595 } +596 +597/** +598 * Returns true if the disableBundleAudit command line argument was +599 * specified. +600 * +601 * @return true if the disableBundleAudit command line argument was +602 * specified; otherwise false +603 */ +604publicboolean isBundleAuditDisabled() { +605return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT); +606 } +607 +608/** +609 * Returns true if the disablePyDist command line argument was specified. +610 * +611 * @return true if the disablePyDist command line argument was specified; +612 * otherwise false +613 */ +614publicboolean isPythonDistributionDisabled() { +615return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST); +616 } +617 +618/** +619 * Returns true if the disablePyPkg command line argument was specified. +620 * +621 * @return true if the disablePyPkg command line argument was specified; +622 * otherwise false +623 */ +624publicboolean isPythonPackageDisabled() { +625return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG); +626 } +627 +628/** +629 * Returns whether the Ruby gemspec analyzer is disabled. +630 * +631 * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line +632 * argument was specified; otherwise false +633 */ +634publicboolean isRubyGemspecDisabled() { +635return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS); +636 } +637 +638/** +639 * Returns true if the disableCmake command line argument was specified. +640 * +641 * @return true if the disableCmake command line argument was specified; +642 * otherwise false +643 */ +644publicboolean isCmakeDisabled() { +645return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE); +646 } +647 +648/** +649 * Returns true if the disableAutoconf command line argument was specified. +650 * +651 * @return true if the disableAutoconf command line argument was specified; +652 * otherwise false +653 */ +654publicboolean isAutoconfDisabled() { +655return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF); +656 } +657 +658/** +659 * Returns true if the disableComposer command line argument was specified. +660 * +661 * @return true if the disableComposer command line argument was specified; +662 * otherwise false +663 */ +664publicboolean isComposerDisabled() { +665return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER); +666 } +667 +668/** +669 * Returns true if the disableNexus command line argument was specified. +670 * +671 * @return true if the disableNexus command line argument was specified; +672 * otherwise false +673 */ +674publicboolean isNexusDisabled() { +675return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS); +676 } +677 +678/** +679 * Returns true if the disableOpenSSL command line argument was specified. +680 * +681 * @return true if the disableOpenSSL command line argument was specified; +682 * otherwise false +683 */ +684publicboolean isOpenSSLDisabled() { +685return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL); +686 } +687 +688/** +689 * Returns true if the disableNodeJS command line argument was specified. +690 * +691 * @return true if the disableNodeJS command line argument was specified; +692 * otherwise false +693 */ +694publicboolean isNodeJsDisabled() { +695return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS); +696 } +697 +698/** +699 * Returns true if the disableCentral command line argument was specified. +700 * +701 * @return true if the disableCentral command line argument was specified; +702 * otherwise false +703 */ +704publicboolean isCentralDisabled() { +705return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL); +706 } +707 +708/** +709 * Returns the url to the nexus server if one was specified. +710 * +711 * @return the url to the nexus server; if none was specified this will +712 * return null; +713 */ +714public String getNexusUrl() { +715if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) { +716returnnull; +717 } else { +718return line.getOptionValue(ARGUMENT.NEXUS_URL); +719 } +720 } +721 +722/** +723 * Returns true if the Nexus Analyzer should use the configured proxy to +724 * connect to Nexus; otherwise false is returned. +725 * +726 * @return true if the Nexus Analyzer should use the configured proxy to +727 * connect to Nexus; otherwise false +728 */ +729publicboolean isNexusUsesProxy() { +730// If they didn't specify whether Nexus needs to use the proxy, we should +731// still honor the property if it's set. +732if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) { +733try { +734return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY); +735 } catch (InvalidSettingException ise) { +736returntrue; +737 } +738 } else { +739return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY)); +740 } +741 } +742 +743/** +744 * Displays the command line help message to the standard output. +745 */ +746publicvoid printHelp() { +747final HelpFormatter formatter = new HelpFormatter(); +748final Options options = new Options(); +749 addStandardOptions(options); +750if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) { +751 addAdvancedOptions(options); +752 } +753final String helpMsg = String.format("%n%s" +754 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. " +755 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n", +756 Settings.getString("application.name", "DependencyCheck"), +757 Settings.getString("application.name", "DependencyCheck")); +758 +759 formatter.printHelp(Settings.getString("application.name", "DependencyCheck"), +760 helpMsg, +761 options, +762"", +763true); +764 } +765 +766/** +767 * Retrieves the file command line parameter(s) specified for the 'scan' +768 * argument. +769 * +770 * @return the file paths specified on the command line for scan +771 */ +772public String[] getScanFiles() { +773return line.getOptionValues(ARGUMENT.SCAN); +774 } +775 +776/** +777 * Retrieves the list of excluded file patterns specified by the 'exclude' +778 * argument. +779 * +780 * @return the excluded file patterns +781 */ +782public String[] getExcludeList() { +783return line.getOptionValues(ARGUMENT.EXCLUDE); +784 } +785 +786/** +787 * Returns the directory to write the reports to specified on the command +788 * line. +789 * +790 * @return the path to the reports directory. +791 */ +792public String getReportDirectory() { +793return line.getOptionValue(ARGUMENT.OUT, "."); +794 } +795 +796/** +797 * Returns the path to Mono for .NET Assembly analysis on non-windows +798 * systems. +799 * +800 * @return the path to Mono +801 */ +802public String getPathToMono() { +803return line.getOptionValue(ARGUMENT.PATH_TO_MONO); +804 } +805 +806/** +807 * Returns the path to bundle-audit for Ruby bundle analysis. +808 * +809 * @return the path to Mono +810 */ +811public String getPathToBundleAudit() { +812return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT); +813 } +814 +815/** +816 * Returns the output format specified on the command line. Defaults to HTML +817 * if no format was specified. +818 * +819 * @return the output format name. +820 */ +821public String getReportFormat() { +822return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML"); +823 } +824 +825/** +826 * Returns the application name specified on the command line. +827 * +828 * @return the application name. +829 */ +830public String getProjectName() { +831final String appName = line.getOptionValue(ARGUMENT.APP_NAME); +832 String name = line.getOptionValue(ARGUMENT.PROJECT); +833if (name == null && appName != null) { +834 name = appName; +835 LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead."); +836 } +837return name; +838 } +839 +840/** +841 * Returns the base URL for the CVE 1.2 XMl file. +842 * +843 * @return the URL to the CVE 1.2 XML file. +844 */ +845public String getBaseCve12Url() { +846return line.getOptionValue(ARGUMENT.CVE_BASE_12); +847 } +848 +849/** +850 * Returns the base URL for the CVE 2.0 XMl file. +851 * +852 * @return the URL to the CVE 2.0 XML file. +853 */ +854public String getBaseCve20Url() { +855return line.getOptionValue(ARGUMENT.CVE_BASE_20); +856 } +857 +858/** +859 * Returns the URL for the modified CVE 1.2 XMl file. +860 * +861 * @return the URL to the modified CVE 1.2 XML file. +862 */ +863public String getModifiedCve12Url() { +864return line.getOptionValue(ARGUMENT.CVE_MOD_12); +865 } +866 +867/** +868 * Returns the URL for the modified CVE 2.0 XMl file. +869 * +870 * @return the URL to the modified CVE 2.0 XML file. +871 */ +872public String getModifiedCve20Url() { +873return line.getOptionValue(ARGUMENT.CVE_MOD_20); +874 } +875 +876/** +877 * Returns the connection timeout. +878 * +879 * @return the connection timeout +880 */ +881public String getConnectionTimeout() { +882return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT); +883 } +884 +885/** +886 * Returns the proxy server. +887 * +888 * @return the proxy server +889 */ +890 @SuppressWarnings("deprecation") +891public String getProxyServer() { +892 +893 String server = line.getOptionValue(ARGUMENT.PROXY_SERVER); +894if (server == null) { +895 server = line.getOptionValue(ARGUMENT.PROXY_URL); +896if (server != null) { +897 LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead"); +898 } +899 } +900return server; +901 } +902 +903/** +904 * Returns the proxy port. +905 * +906 * @return the proxy port +907 */ +908public String getProxyPort() { +909return line.getOptionValue(ARGUMENT.PROXY_PORT); +910 } +911 +912/** +913 * Returns the proxy username. +914 * +915 * @return the proxy username +916 */ +917public String getProxyUsername() { +918return line.getOptionValue(ARGUMENT.PROXY_USERNAME); +919 } +920 +921/** +922 * Returns the proxy password. +923 * +924 * @return the proxy password +925 */ +926public String getProxyPassword() { +927return line.getOptionValue(ARGUMENT.PROXY_PASSWORD); +928 } +929 +930/** +931 * Get the value of dataDirectory. +932 * +933 * @return the value of dataDirectory +934 */ +935public String getDataDirectory() { +936return line.getOptionValue(ARGUMENT.DATA_DIRECTORY); +937 } +938 +939/** +940 * Returns the properties file specified on the command line. +941 * +942 * @return the properties file specified on the command line +943 */ +944public File getPropertiesFile() { +945final String path = line.getOptionValue(ARGUMENT.PROP); +946if (path != null) { +947returnnew File(path); +948 } +949returnnull; +950 } +951 +952/** +953 * Returns the path to the verbose log file. +954 * +955 * @return the path to the verbose log file +956 */ +957public String getVerboseLog() { +958return line.getOptionValue(ARGUMENT.VERBOSE_LOG); +959 } +960 +961/** +962 * Returns the path to the suppression file. +963 * +964 * @return the path to the suppression file +965 */ +966public String getSuppressionFile() { +967return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE); +968 } +969 +970/** +971 * Returns the path to the hints file. +972 * +973 * @return the path to the hints file +974 */ +975public String getHintsFile() { +976return line.getOptionValue(ARGUMENT.HINTS_FILE); +977 } +978 +979/** +980 * <p> +981 * Prints the manifest information to standard output.</p> +982 * <ul><li>Implementation-Title: ${pom.name}</li> +983 * <li>Implementation-Version: ${pom.version}</li></ul>984 */ -985publicboolean isAutoUpdate() { -986return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE); -987 } -988 -989/** -990 * Checks if the update only flag has been set. -991 * -992 * @return <code>true</code> if the update only flag has been set; otherwise -993 * <code>false</code>. -994 */ -995publicboolean isUpdateOnly() { -996return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY); -997 } -998 -999/** -1000 * Checks if the purge NVD flag has been set. -1001 * -1002 * @return <code>true</code> if the purge nvd flag has been set; otherwise -1003 * <code>false</code>. -1004 */ -1005publicboolean isPurge() { -1006return line != null && line.hasOption(ARGUMENT.PURGE_NVD); -1007 } -1008 -1009/** -1010 * Returns the database driver name if specified; otherwise null is -1011 * returned. -1012 * -1013 * @return the database driver name if specified; otherwise null is returned -1014 */ -1015public String getDatabaseDriverName() { -1016return line.getOptionValue(ARGUMENT.DB_DRIVER); -1017 } -1018 -1019/** -1020 * Returns the database driver path if specified; otherwise null is -1021 * returned. -1022 * -1023 * @return the database driver name if specified; otherwise null is returned -1024 */ -1025public String getDatabaseDriverPath() { -1026return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH); -1027 } -1028 -1029/** -1030 * Returns the database connection string if specified; otherwise null is -1031 * returned. -1032 * -1033 * @return the database connection string if specified; otherwise null is -1034 * returned -1035 */ -1036public String getConnectionString() { -1037return line.getOptionValue(ARGUMENT.CONNECTION_STRING); -1038 } -1039 -1040/** -1041 * Returns the database database user name if specified; otherwise null is -1042 * returned. -1043 * -1044 * @return the database database user name if specified; otherwise null is -1045 * returned -1046 */ -1047public String getDatabaseUser() { -1048return line.getOptionValue(ARGUMENT.DB_NAME); -1049 } -1050 -1051/** -1052 * Returns the database database password if specified; otherwise null is -1053 * returned. -1054 * -1055 * @return the database database password if specified; otherwise null is -1056 * returned -1057 */ -1058public String getDatabasePassword() { -1059return line.getOptionValue(ARGUMENT.DB_PASSWORD); -1060 } -1061 -1062/** -1063 * Returns the additional Extensions if specified; otherwise null is -1064 * returned. -1065 * -1066 * @return the additional Extensions; otherwise null is returned -1067 */ -1068public String getAdditionalZipExtensions() { -1069return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS); -1070 } -1071 -1072/** -1073 * Get the value of cveValidForHours. -1074 * -1075 * @return the value of cveValidForHours -1076 */ -1077public Integer getCveValidForHours() { -1078final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS); -1079if (v != null) { -1080return Integer.parseInt(v); -1081 } -1082returnnull; -1083 } -1084 -1085/** -1086 * Returns true if the experimental analyzers are enabled. -1087 * -1088 * @return true if the experimental analyzers are enabled; otherwise false -1089 */ -1090publicboolean isExperimentalEnabled() { -1091return line.hasOption(ARGUMENT.EXPERIMENTAL); -1092 } -1093 -1094/** -1095 * A collection of static final strings that represent the possible command -1096 * line arguments. -1097 */ -1098publicstaticclassARGUMENT { -1099 -1100/** -1101 * The long CLI argument name specifying the directory/file to scan. -1102 */ -1103publicstaticfinal String SCAN = "scan"; -1104/** -1105 * The short CLI argument name specifying the directory/file to scan. -1106 */ -1107publicstaticfinal String SCAN_SHORT = "s"; -1108/** -1109 * The long CLI argument name specifying that the CPE/CVE/etc. data -1110 * should not be automatically updated. -1111 */ -1112publicstaticfinal String DISABLE_AUTO_UPDATE = "noupdate"; -1113/** -1114 * The short CLI argument name specifying that the CPE/CVE/etc. data -1115 * should not be automatically updated. +985publicvoid printVersionInfo() { +986final String version = String.format("%s version %s", +987 Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"), +988 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown")); +989 System.out.println(version); +990 } +991 +992/** +993 * Checks if the auto update feature has been disabled. If it has been +994 * disabled via the command line this will return false. +995 * +996 * @return <code>true</code> if auto-update is allowed; otherwise +997 * <code>false</code> +998 */ +999publicboolean isAutoUpdate() { +1000return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE); +1001 } +1002 +1003/** +1004 * Checks if the update only flag has been set. +1005 * +1006 * @return <code>true</code> if the update only flag has been set; otherwise +1007 * <code>false</code>. +1008 */ +1009publicboolean isUpdateOnly() { +1010return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY); +1011 } +1012 +1013/** +1014 * Checks if the purge NVD flag has been set. +1015 * +1016 * @return <code>true</code> if the purge nvd flag has been set; otherwise +1017 * <code>false</code>. +1018 */ +1019publicboolean isPurge() { +1020return line != null && line.hasOption(ARGUMENT.PURGE_NVD); +1021 } +1022 +1023/** +1024 * Returns the database driver name if specified; otherwise null is +1025 * returned. +1026 * +1027 * @return the database driver name if specified; otherwise null is returned +1028 */ +1029public String getDatabaseDriverName() { +1030return line.getOptionValue(ARGUMENT.DB_DRIVER); +1031 } +1032 +1033/** +1034 * Returns the database driver path if specified; otherwise null is +1035 * returned. +1036 * +1037 * @return the database driver name if specified; otherwise null is returned +1038 */ +1039public String getDatabaseDriverPath() { +1040return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH); +1041 } +1042 +1043/** +1044 * Returns the database connection string if specified; otherwise null is +1045 * returned. +1046 * +1047 * @return the database connection string if specified; otherwise null is +1048 * returned +1049 */ +1050public String getConnectionString() { +1051return line.getOptionValue(ARGUMENT.CONNECTION_STRING); +1052 } +1053 +1054/** +1055 * Returns the database database user name if specified; otherwise null is +1056 * returned. +1057 * +1058 * @return the database database user name if specified; otherwise null is +1059 * returned +1060 */ +1061public String getDatabaseUser() { +1062return line.getOptionValue(ARGUMENT.DB_NAME); +1063 } +1064 +1065/** +1066 * Returns the database database password if specified; otherwise null is +1067 * returned. +1068 * +1069 * @return the database database password if specified; otherwise null is +1070 * returned +1071 */ +1072public String getDatabasePassword() { +1073return line.getOptionValue(ARGUMENT.DB_PASSWORD); +1074 } +1075 +1076/** +1077 * Returns the additional Extensions if specified; otherwise null is +1078 * returned. +1079 * +1080 * @return the additional Extensions; otherwise null is returned +1081 */ +1082public String getAdditionalZipExtensions() { +1083return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS); +1084 } +1085 +1086/** +1087 * Get the value of cveValidForHours. +1088 * +1089 * @return the value of cveValidForHours +1090 */ +1091public Integer getCveValidForHours() { +1092final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS); +1093if (v != null) { +1094return Integer.parseInt(v); +1095 } +1096returnnull; +1097 } +1098 +1099/** +1100 * Returns true if the experimental analyzers are enabled. +1101 * +1102 * @return true if the experimental analyzers are enabled; otherwise false +1103 */ +1104publicboolean isExperimentalEnabled() { +1105return line.hasOption(ARGUMENT.EXPERIMENTAL); +1106 } +1107 +1108/** +1109 * A collection of static final strings that represent the possible command +1110 * line arguments. +1111 */ +1112publicstaticclassARGUMENT { +1113 +1114/** +1115 * The long CLI argument name specifying the directory/file to scan.1116 */ -1117publicstaticfinal String DISABLE_AUTO_UPDATE_SHORT = "n"; +1117publicstaticfinal String SCAN = "scan"; 1118/** -1119 * The long CLI argument name specifying that only the update phase -1120 * should be executed; no scan should be run. -1121 */ -1122publicstaticfinal String UPDATE_ONLY = "updateonly"; -1123/** -1124 * The long CLI argument name specifying that only the update phase -1125 * should be executed; no scan should be run. -1126 */ -1127publicstaticfinal String PURGE_NVD = "purge"; -1128/** -1129 * The long CLI argument name specifying the directory to write the -1130 * reports to. -1131 */ -1132publicstaticfinal String OUT = "out"; -1133/** -1134 * The short CLI argument name specifying the directory to write the -1135 * reports to. -1136 */ -1137publicstaticfinal String OUT_SHORT = "o"; -1138/** -1139 * The long CLI argument name specifying the output format to write the -1140 * reports to. -1141 */ -1142publicstaticfinal String OUTPUT_FORMAT = "format"; -1143/** -1144 * The short CLI argument name specifying the output format to write the -1145 * reports to. -1146 */ -1147publicstaticfinal String OUTPUT_FORMAT_SHORT = "f"; -1148/** -1149 * The long CLI argument name specifying the name of the project to be -1150 * scanned. -1151 */ -1152publicstaticfinal String PROJECT = "project"; -1153/** -1154 * The long CLI argument name specifying the name of the application to -1155 * be scanned. -1156 * -1157 * @deprecated project should be used instead -1158 */ -1159 @Deprecated -1160publicstaticfinal String APP_NAME = "app"; -1161/** -1162 * The short CLI argument name specifying the name of the application to -1163 * be scanned. -1164 * -1165 * @deprecated project should be used instead -1166 */ -1167 @Deprecated -1168publicstaticfinal String APP_NAME_SHORT = "a"; -1169/** -1170 * The long CLI argument name asking for help. -1171 */ -1172publicstaticfinal String HELP = "help"; -1173/** -1174 * The long CLI argument name asking for advanced help. -1175 */ -1176publicstaticfinal String ADVANCED_HELP = "advancedHelp"; -1177/** -1178 * The short CLI argument name asking for help. -1179 */ -1180publicstaticfinal String HELP_SHORT = "h"; -1181/** -1182 * The long CLI argument name asking for the version. -1183 */ -1184publicstaticfinal String VERSION_SHORT = "v"; -1185/** -1186 * The short CLI argument name asking for the version. -1187 */ -1188publicstaticfinal String VERSION = "version"; -1189/** -1190 * The CLI argument name indicating the proxy port. -1191 */ -1192publicstaticfinal String PROXY_PORT = "proxyport"; -1193/** -1194 * The CLI argument name indicating the proxy server. -1195 */ -1196publicstaticfinal String PROXY_SERVER = "proxyserver"; -1197/** -1198 * The CLI argument name indicating the proxy url. -1199 * -1200 * @deprecated use {@link #PROXY_SERVER} instead +1119 * The short CLI argument name specifying the directory/file to scan. +1120 */ +1121publicstaticfinal String SCAN_SHORT = "s"; +1122/** +1123 * The long CLI argument name specifying that the CPE/CVE/etc. data +1124 * should not be automatically updated. +1125 */ +1126publicstaticfinal String DISABLE_AUTO_UPDATE = "noupdate"; +1127/** +1128 * The short CLI argument name specifying that the CPE/CVE/etc. data +1129 * should not be automatically updated. +1130 */ +1131publicstaticfinal String DISABLE_AUTO_UPDATE_SHORT = "n"; +1132/** +1133 * The long CLI argument name specifying that only the update phase +1134 * should be executed; no scan should be run. +1135 */ +1136publicstaticfinal String UPDATE_ONLY = "updateonly"; +1137/** +1138 * The long CLI argument name specifying that only the update phase +1139 * should be executed; no scan should be run. +1140 */ +1141publicstaticfinal String PURGE_NVD = "purge"; +1142/** +1143 * The long CLI argument name specifying the directory to write the +1144 * reports to. +1145 */ +1146publicstaticfinal String OUT = "out"; +1147/** +1148 * The short CLI argument name specifying the directory to write the +1149 * reports to. +1150 */ +1151publicstaticfinal String OUT_SHORT = "o"; +1152/** +1153 * The long CLI argument name specifying the output format to write the +1154 * reports to. +1155 */ +1156publicstaticfinal String OUTPUT_FORMAT = "format"; +1157/** +1158 * The short CLI argument name specifying the output format to write the +1159 * reports to. +1160 */ +1161publicstaticfinal String OUTPUT_FORMAT_SHORT = "f"; +1162/** +1163 * The long CLI argument name specifying the name of the project to be +1164 * scanned. +1165 */ +1166publicstaticfinal String PROJECT = "project"; +1167/** +1168 * The long CLI argument name specifying the name of the application to +1169 * be scanned. +1170 * +1171 * @deprecated project should be used instead +1172 */ +1173 @Deprecated +1174publicstaticfinal String APP_NAME = "app"; +1175/** +1176 * The short CLI argument name specifying the name of the application to +1177 * be scanned. +1178 * +1179 * @deprecated project should be used instead +1180 */ +1181 @Deprecated +1182publicstaticfinal String APP_NAME_SHORT = "a"; +1183/** +1184 * The long CLI argument name asking for help. +1185 */ +1186publicstaticfinal String HELP = "help"; +1187/** +1188 * The long CLI argument name asking for advanced help. +1189 */ +1190publicstaticfinal String ADVANCED_HELP = "advancedHelp"; +1191/** +1192 * The short CLI argument name asking for help. +1193 */ +1194publicstaticfinal String HELP_SHORT = "h"; +1195/** +1196 * The long CLI argument name asking for the version. +1197 */ +1198publicstaticfinal String VERSION_SHORT = "v"; +1199/** +1200 * The short CLI argument name asking for the version.1201 */ -1202 @Deprecated -1203publicstaticfinal String PROXY_URL = "proxyurl"; -1204/** -1205 * The CLI argument name indicating the proxy username. -1206 */ -1207publicstaticfinal String PROXY_USERNAME = "proxyuser"; -1208/** -1209 * The CLI argument name indicating the proxy password. -1210 */ -1211publicstaticfinal String PROXY_PASSWORD = "proxypass"; -1212/** -1213 * The short CLI argument name indicating the connection timeout. -1214 */ -1215publicstaticfinal String CONNECTION_TIMEOUT_SHORT = "c"; -1216/** -1217 * The CLI argument name indicating the connection timeout. -1218 */ -1219publicstaticfinal String CONNECTION_TIMEOUT = "connectiontimeout"; -1220/** -1221 * The short CLI argument name for setting the location of an additional -1222 * properties file. -1223 */ -1224publicstaticfinal String PROP_SHORT = "P"; -1225/** -1226 * The CLI argument name for setting the location of an additional -1227 * properties file. +1202publicstaticfinal String VERSION = "version"; +1203/** +1204 * The CLI argument name indicating the proxy port. +1205 */ +1206publicstaticfinal String PROXY_PORT = "proxyport"; +1207/** +1208 * The CLI argument name indicating the proxy server. +1209 */ +1210publicstaticfinal String PROXY_SERVER = "proxyserver"; +1211/** +1212 * The CLI argument name indicating the proxy url. +1213 * +1214 * @deprecated use {@link #PROXY_SERVER} instead +1215 */ +1216 @Deprecated +1217publicstaticfinal String PROXY_URL = "proxyurl"; +1218/** +1219 * The CLI argument name indicating the proxy username. +1220 */ +1221publicstaticfinal String PROXY_USERNAME = "proxyuser"; +1222/** +1223 * The CLI argument name indicating the proxy password. +1224 */ +1225publicstaticfinal String PROXY_PASSWORD = "proxypass"; +1226/** +1227 * The short CLI argument name indicating the connection timeout.1228 */ -1229publicstaticfinal String PROP = "propertyfile"; +1229publicstaticfinal String CONNECTION_TIMEOUT_SHORT = "c"; 1230/** -1231 * The CLI argument name for setting the location of the data directory. +1231 * The CLI argument name indicating the connection timeout.1232 */ -1233publicstaticfinal String DATA_DIRECTORY = "data"; +1233publicstaticfinal String CONNECTION_TIMEOUT = "connectiontimeout"; 1234/** -1235 * The CLI argument name for setting the URL for the CVE Data Files. -1236 */ -1237publicstaticfinal String CVE_MOD_12 = "cveUrl12Modified"; -1238/** -1239 * The CLI argument name for setting the URL for the CVE Data Files. -1240 */ -1241publicstaticfinal String CVE_MOD_20 = "cveUrl20Modified"; -1242/** -1243 * The CLI argument name for setting the URL for the CVE Data Files. -1244 */ -1245publicstaticfinal String CVE_BASE_12 = "cveUrl12Base"; -1246/** -1247 * The CLI argument name for setting the URL for the CVE Data Files. -1248 */ -1249publicstaticfinal String CVE_BASE_20 = "cveUrl20Base"; -1250/** -1251 * The short CLI argument name for setting the location of the data -1252 * directory. -1253 */ -1254publicstaticfinal String DATA_DIRECTORY_SHORT = "d"; -1255/** -1256 * The CLI argument name for setting the location of the data directory. -1257 */ -1258publicstaticfinal String VERBOSE_LOG = "log"; -1259/** -1260 * The short CLI argument name for setting the location of the data -1261 * directory. +1235 * The short CLI argument name for setting the location of an additional +1236 * properties file. +1237 */ +1238publicstaticfinal String PROP_SHORT = "P"; +1239/** +1240 * The CLI argument name for setting the location of an additional +1241 * properties file. +1242 */ +1243publicstaticfinal String PROP = "propertyfile"; +1244/** +1245 * The CLI argument name for setting the location of the data directory. +1246 */ +1247publicstaticfinal String DATA_DIRECTORY = "data"; +1248/** +1249 * The CLI argument name for setting the URL for the CVE Data Files. +1250 */ +1251publicstaticfinal String CVE_MOD_12 = "cveUrl12Modified"; +1252/** +1253 * The CLI argument name for setting the URL for the CVE Data Files. +1254 */ +1255publicstaticfinal String CVE_MOD_20 = "cveUrl20Modified"; +1256/** +1257 * The CLI argument name for setting the URL for the CVE Data Files. +1258 */ +1259publicstaticfinal String CVE_BASE_12 = "cveUrl12Base"; +1260/** +1261 * The CLI argument name for setting the URL for the CVE Data Files.1262 */ -1263publicstaticfinal String VERBOSE_LOG_SHORT = "l"; -1264 -1265/** -1266 * The CLI argument name for setting the depth of symbolic links that -1267 * will be followed. -1268 */ -1269publicstaticfinal String SYM_LINK_DEPTH = "symLink"; -1270/** -1271 * The CLI argument name for setting the location of the suppression -1272 * file. -1273 */ -1274publicstaticfinal String SUPPRESSION_FILE = "suppression"; -1275/** -1276 * The CLI argument name for setting the location of the suppression -1277 * file. -1278 */ -1279publicstaticfinal String CVE_VALID_FOR_HOURS = "cveValidForHours"; -1280/** -1281 * Disables the Jar Analyzer. +1263publicstaticfinal String CVE_BASE_20 = "cveUrl20Base"; +1264/** +1265 * The short CLI argument name for setting the location of the data +1266 * directory. +1267 */ +1268publicstaticfinal String DATA_DIRECTORY_SHORT = "d"; +1269/** +1270 * The CLI argument name for setting the location of the data directory. +1271 */ +1272publicstaticfinal String VERBOSE_LOG = "log"; +1273/** +1274 * The short CLI argument name for setting the location of the data +1275 * directory. +1276 */ +1277publicstaticfinal String VERBOSE_LOG_SHORT = "l"; +1278 +1279/** +1280 * The CLI argument name for setting the depth of symbolic links that +1281 * will be followed.1282 */ -1283publicstaticfinal String DISABLE_JAR = "disableJar"; +1283publicstaticfinal String SYM_LINK_DEPTH = "symLink"; 1284/** -1285 * Disables the Archive Analyzer. -1286 */ -1287publicstaticfinal String DISABLE_ARCHIVE = "disableArchive"; -1288/** -1289 * Disables the Python Distribution Analyzer. -1290 */ -1291publicstaticfinal String DISABLE_PY_DIST = "disablePyDist"; -1292/** -1293 * Disables the Python Package Analyzer. -1294 */ -1295publicstaticfinal String DISABLE_PY_PKG = "disablePyPkg"; -1296/** -1297 * Disables the Python Package Analyzer. -1298 */ -1299publicstaticfinal String DISABLE_COMPOSER = "disableComposer"; -1300/** -1301 * Disables the Ruby Gemspec Analyzer. -1302 */ -1303publicstaticfinal String DISABLE_RUBYGEMS = "disableRubygems"; -1304/** -1305 * Disables the Autoconf Analyzer. -1306 */ -1307publicstaticfinal String DISABLE_AUTOCONF = "disableAutoconf"; -1308/** -1309 * Disables the Cmake Analyzer. -1310 */ -1311publicstaticfinal String DISABLE_CMAKE = "disableCmake"; -1312/** -1313 * Disables the Assembly Analyzer. -1314 */ -1315publicstaticfinal String DISABLE_ASSEMBLY = "disableAssembly"; -1316/** -1317 * Disables the Ruby Bundler Audit Analyzer. -1318 */ -1319publicstaticfinal String DISABLE_BUNDLE_AUDIT = "disableBundleAudit"; -1320/** -1321 * Disables the Nuspec Analyzer. -1322 */ -1323publicstaticfinal String DISABLE_NUSPEC = "disableNuspec"; -1324/** -1325 * Disables the Central Analyzer. -1326 */ -1327publicstaticfinal String DISABLE_CENTRAL = "disableCentral"; -1328/** -1329 * Disables the Nexus Analyzer. -1330 */ -1331publicstaticfinal String DISABLE_NEXUS = "disableNexus"; -1332/** -1333 * Disables the OpenSSL Analyzer. -1334 */ -1335publicstaticfinal String DISABLE_OPENSSL = "disableOpenSSL"; -1336/** -1337 * Disables the Node.js Package Analyzer. -1338 */ -1339publicstaticfinal String DISABLE_NODE_JS = "disableNodeJS"; -1340/** -1341 * The URL of the nexus server. -1342 */ -1343publicstaticfinal String NEXUS_URL = "nexus"; -1344/** -1345 * Whether or not the defined proxy should be used when connecting to -1346 * Nexus. -1347 */ -1348publicstaticfinal String NEXUS_USES_PROXY = "nexusUsesProxy"; -1349/** -1350 * The CLI argument name for setting the connection string. -1351 */ -1352publicstaticfinal String CONNECTION_STRING = "connectionString"; -1353/** -1354 * The CLI argument name for setting the database user name. -1355 */ -1356publicstaticfinal String DB_NAME = "dbUser"; -1357/** -1358 * The CLI argument name for setting the database password. -1359 */ -1360publicstaticfinal String DB_PASSWORD = "dbPassword"; -1361/** -1362 * The CLI argument name for setting the database driver name. -1363 */ -1364publicstaticfinal String DB_DRIVER = "dbDriverName"; -1365/** -1366 * The CLI argument name for setting the path to the database driver; in -1367 * case it is not on the class path. -1368 */ -1369publicstaticfinal String DB_DRIVER_PATH = "dbDriverPath"; -1370/** -1371 * The CLI argument name for setting the path to mono for .NET Assembly -1372 * analysis on non-windows systems. -1373 */ -1374publicstaticfinal String PATH_TO_MONO = "mono"; -1375/** -1376 * The CLI argument name for setting extra extensions. -1377 */ -1378publicstaticfinal String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions"; -1379/** -1380 * Exclude path argument. -1381 */ -1382publicstaticfinal String EXCLUDE = "exclude"; -1383/** -1384 * The CLI argument name for setting the path to bundle-audit for Ruby -1385 * bundle analysis. -1386 */ -1387publicstaticfinal String PATH_TO_BUNDLE_AUDIT = "bundleAudit"; -1388/** -1389 * The CLI argument to enable the experimental analyzers. -1390 */ -1391privatestaticfinal String EXPERIMENTAL = "enableExperimental"; -1392 } -1393 } +1285 * The CLI argument name for setting the location of the suppression +1286 * file. +1287 */ +1288publicstaticfinal String SUPPRESSION_FILE = "suppression"; +1289/** +1290 * The CLI argument name for setting the location of the hint +1291 * file. +1292 */ +1293publicstaticfinal String HINTS_FILE = "hints"; +1294/** +1295 * The CLI argument name for setting the number of hours to wait before +1296 * checking for new updates from the NVD. +1297 */ +1298publicstaticfinal String CVE_VALID_FOR_HOURS = "cveValidForHours"; +1299/** +1300 * Disables the Jar Analyzer. +1301 */ +1302publicstaticfinal String DISABLE_JAR = "disableJar"; +1303/** +1304 * Disables the Archive Analyzer. +1305 */ +1306publicstaticfinal String DISABLE_ARCHIVE = "disableArchive"; +1307/** +1308 * Disables the Python Distribution Analyzer. +1309 */ +1310publicstaticfinal String DISABLE_PY_DIST = "disablePyDist"; +1311/** +1312 * Disables the Python Package Analyzer. +1313 */ +1314publicstaticfinal String DISABLE_PY_PKG = "disablePyPkg"; +1315/** +1316 * Disables the Python Package Analyzer. +1317 */ +1318publicstaticfinal String DISABLE_COMPOSER = "disableComposer"; +1319/** +1320 * Disables the Ruby Gemspec Analyzer. +1321 */ +1322publicstaticfinal String DISABLE_RUBYGEMS = "disableRubygems"; +1323/** +1324 * Disables the Autoconf Analyzer. +1325 */ +1326publicstaticfinal String DISABLE_AUTOCONF = "disableAutoconf"; +1327/** +1328 * Disables the Cmake Analyzer. +1329 */ +1330publicstaticfinal String DISABLE_CMAKE = "disableCmake"; +1331/** +1332 * Disables the Assembly Analyzer. +1333 */ +1334publicstaticfinal String DISABLE_ASSEMBLY = "disableAssembly"; +1335/** +1336 * Disables the Ruby Bundler Audit Analyzer. +1337 */ +1338publicstaticfinal String DISABLE_BUNDLE_AUDIT = "disableBundleAudit"; +1339/** +1340 * Disables the Nuspec Analyzer. +1341 */ +1342publicstaticfinal String DISABLE_NUSPEC = "disableNuspec"; +1343/** +1344 * Disables the Central Analyzer. +1345 */ +1346publicstaticfinal String DISABLE_CENTRAL = "disableCentral"; +1347/** +1348 * Disables the Nexus Analyzer. +1349 */ +1350publicstaticfinal String DISABLE_NEXUS = "disableNexus"; +1351/** +1352 * Disables the OpenSSL Analyzer. +1353 */ +1354publicstaticfinal String DISABLE_OPENSSL = "disableOpenSSL"; +1355/** +1356 * Disables the Node.js Package Analyzer. +1357 */ +1358publicstaticfinal String DISABLE_NODE_JS = "disableNodeJS"; +1359/** +1360 * The URL of the nexus server. +1361 */ +1362publicstaticfinal String NEXUS_URL = "nexus"; +1363/** +1364 * Whether or not the defined proxy should be used when connecting to +1365 * Nexus. +1366 */ +1367publicstaticfinal String NEXUS_USES_PROXY = "nexusUsesProxy"; +1368/** +1369 * The CLI argument name for setting the connection string. +1370 */ +1371publicstaticfinal String CONNECTION_STRING = "connectionString"; +1372/** +1373 * The CLI argument name for setting the database user name. +1374 */ +1375publicstaticfinal String DB_NAME = "dbUser"; +1376/** +1377 * The CLI argument name for setting the database password. +1378 */ +1379publicstaticfinal String DB_PASSWORD = "dbPassword"; +1380/** +1381 * The CLI argument name for setting the database driver name. +1382 */ +1383publicstaticfinal String DB_DRIVER = "dbDriverName"; +1384/** +1385 * The CLI argument name for setting the path to the database driver; in +1386 * case it is not on the class path. +1387 */ +1388publicstaticfinal String DB_DRIVER_PATH = "dbDriverPath"; +1389/** +1390 * The CLI argument name for setting the path to mono for .NET Assembly +1391 * analysis on non-windows systems. +1392 */ +1393publicstaticfinal String PATH_TO_MONO = "mono"; +1394/** +1395 * The CLI argument name for setting extra extensions. +1396 */ +1397publicstaticfinal String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions"; +1398/** +1399 * Exclude path argument. +1400 */ +1401publicstaticfinal String EXCLUDE = "exclude"; +1402/** +1403 * The CLI argument name for setting the path to bundle-audit for Ruby +1404 * bundle analysis. +1405 */ +1406publicstaticfinal String PATH_TO_BUNDLE_AUDIT = "bundleAudit"; +1407/** +1408 * The CLI argument to enable the experimental analyzers. +1409 */ +1410privatestaticfinal String EXPERIMENTAL = "enableExperimental"; +1411 } +1412 }
      diff --git a/dependency-check-cli/xref/org/owasp/dependencycheck/package-frame.html b/dependency-check-cli/xref/org/owasp/dependencycheck/package-frame.html index 64fecfbd4..152a2f475 100644 --- a/dependency-check-cli/xref/org/owasp/dependencycheck/package-frame.html +++ b/dependency-check-cli/xref/org/owasp/dependencycheck/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Command Line 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check Command Line 1.4.4 Reference Package org.owasp.dependencycheck diff --git a/dependency-check-cli/xref/org/owasp/dependencycheck/package-summary.html b/dependency-check-cli/xref/org/owasp/dependencycheck/package-summary.html index 47836ed79..531f37040 100644 --- a/dependency-check-cli/xref/org/owasp/dependencycheck/package-summary.html +++ b/dependency-check-cli/xref/org/owasp/dependencycheck/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Command Line 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check Command Line 1.4.4 Reference Package org.owasp.dependencycheck diff --git a/dependency-check-cli/xref/overview-frame.html b/dependency-check-cli/xref/overview-frame.html index 8dccbdb4d..8afc9d35e 100644 --- a/dependency-check-cli/xref/overview-frame.html +++ b/dependency-check-cli/xref/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Command Line 1.4.3 Reference + Dependency-Check Command Line 1.4.4 Reference diff --git a/dependency-check-cli/xref/overview-summary.html b/dependency-check-cli/xref/overview-summary.html index d03aa3af5..a0404678c 100644 --- a/dependency-check-cli/xref/overview-summary.html +++ b/dependency-check-cli/xref/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Command Line 1.4.3 Reference + Dependency-Check Command Line 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Command Line 1.4.3 Reference

      +

      Dependency-Check Command Line 1.4.4 Reference

      diff --git a/dependency-check-core/apidocs/allclasses-frame.html b/dependency-check-core/apidocs/allclasses-frame.html index 622197446..83d57a10b 100644 --- a/dependency-check-core/apidocs/allclasses-frame.html +++ b/dependency-check-core/apidocs/allclasses-frame.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Core 1.4.3 API) - +All Classes (Dependency-Check Core 1.4.4 API) + diff --git a/dependency-check-core/apidocs/allclasses-noframe.html b/dependency-check-core/apidocs/allclasses-noframe.html index cb9cfef01..a32c5af5a 100644 --- a/dependency-check-core/apidocs/allclasses-noframe.html +++ b/dependency-check-core/apidocs/allclasses-noframe.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Core 1.4.3 API) - +All Classes (Dependency-Check Core 1.4.4 API) + diff --git a/dependency-check-core/apidocs/constant-values.html b/dependency-check-core/apidocs/constant-values.html index 51016ea19..2501d19ec 100644 --- a/dependency-check-core/apidocs/constant-values.html +++ b/dependency-check-core/apidocs/constant-values.html @@ -2,10 +2,10 @@ - + -Constant Field Values (Dependency-Check Core 1.4.3 API) - +Constant Field Values (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,13 +13,13 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/agent/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/agent/package-summary.html index e1b76cb39..26d376b1f 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/agent/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/agent/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.agent (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.agent (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,13 +13,13 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,13 +13,13 @@ @@ -13,7 +13,7 @@ @@ -13,13 +13,13 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,13 +13,13 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,14 +13,14 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/exception/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/exception/package-summary.html index 4df0d8681..6c0f2adf8 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/exception/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/exception/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.analyzer.exception (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.analyzer.exception (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/package-summary.html index aacc9d20d..f82414874 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/analyzer/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.analyzer (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.analyzer (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/central/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/central/package-summary.html index e7ff0a544..379ac2250 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/central/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/central/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.central (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.central (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/composer/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/composer/package-summary.html index af2b1942f..1d7e76019 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/composer/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/composer/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.composer (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.composer (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/cpe/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/cpe/package-summary.html index 3661f7874..f7f36f220 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/cpe/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/cpe/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.cpe (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.cpe (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/cwe/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/cwe/package-summary.html index 4e3ec45e5..3c782172d 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/cwe/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/cwe/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.cwe (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.cwe (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/lucene/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/lucene/package-summary.html index a6170cec0..a72b9d526 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/lucene/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/lucene/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.lucene (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.lucene (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nexus/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nexus/package-summary.html index b05a3e82d..9a6a652aa 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nexus/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nexus/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.nexus (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.nexus (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nuget/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nuget/package-summary.html index 683fc8a20..9bb4fc0c5 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nuget/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nuget/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.nuget (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.nuget (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nvdcve/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nvdcve/package-summary.html index d58a8490a..f779b7de2 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nvdcve/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/nvdcve/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.nvdcve (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.nvdcve (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/cpe/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/cpe/package-summary.html index 8e4c9e640..475220de1 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/cpe/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/cpe/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.update.cpe (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.update.cpe (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/exception/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/exception/package-summary.html index bf32ccc6c..23398f9e3 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/exception/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/exception/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.update.exception (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.update.exception (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/nvd/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/nvd/package-summary.html index cfefffdac..669014015 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/nvd/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/nvd/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.update.nvd (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.update.nvd (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/package-summary.html index f604098f7..9861784bc 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/data/update/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.data.update (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.data.update (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/dependency/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/dependency/package-summary.html index 295c0cdcc..629160de9 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/dependency/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/dependency/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.dependency (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.dependency (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/exception/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/exception/package-summary.html index 432570c8a..bcea75902 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/exception/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/exception/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.exception (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.exception (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/package-summary.html index 9bada77b1..f7983e6bf 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/reporting/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/reporting/package-summary.html index 9aae5f043..5416cd003 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/reporting/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/reporting/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.reporting (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.reporting (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/utils/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/utils/package-summary.html index 696a8c465..18ee04ec6 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/utils/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/utils/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.utils (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.utils (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/hints/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/hints/package-summary.html index 16720447c..7d240f63e 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/hints/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/hints/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.xml.hints (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.xml.hints (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/pom/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/pom/package-summary.html index 29be3fc47..e78cd1af3 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/pom/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/pom/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.xml.pom (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.xml.pom (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/suppression/package-summary.html b/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/suppression/package-summary.html index 3156382e6..91ca914bb 100644 --- a/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/suppression/package-summary.html +++ b/dependency-check-core/apidocs/org/owasp/dependencycheck/xml/suppression/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.xml.suppression (Dependency-Check Core 1.4.3 API) - +org.owasp.dependencycheck.xml.suppression (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-core/apidocs/overview-summary.html b/dependency-check-core/apidocs/overview-summary.html index 7dae7e249..5a3b31dba 100644 --- a/dependency-check-core/apidocs/overview-summary.html +++ b/dependency-check-core/apidocs/overview-summary.html @@ -2,10 +2,10 @@ - + -Overview (Dependency-Check Core 1.4.3 API) - +Overview (Dependency-Check Core 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.analyzer.exception.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.analyzer.exception.html index d882c8ff7..eb8905e40 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.analyzer.exception.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.analyzer.exception.html @@ -39,6 +39,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.analyzer.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.analyzer.html index 8ada35276..012df8b5a 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.analyzer.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.analyzer.html @@ -16,7 +16,7 @@
      - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.analyzer39
      58%
      1757/3029
      42%
      689/1628
      4.67
      org.owasp.dependencycheck.analyzer39
      57%
      1777/3082
      41%
      690/1652
      4.652
      org.owasp.dependencycheck.analyzer.exception2
      12%
      2/16
      N/A
      1
      @@ -29,11 +29,11 @@ packageTable.sort(0); - + - + @@ -41,15 +41,15 @@ packageTable.sort(0); - + - + - + - + - + @@ -57,15 +57,15 @@ packageTable.sort(0); - + - + - + @@ -73,10 +73,10 @@ packageTable.sort(0); - - + + - + @@ -86,11 +86,11 @@ packageTable.sort(0); - + - + - + @@ -109,6 +109,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.central.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.central.html index 889f19382..c49c34a65 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.central.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.central.html @@ -16,7 +16,7 @@
      Classes in this Package Line Coverage Branch Coverage Complexity
      AbstractAnalyzer
      100%
      3/3
      N/A
      1
      AbstractAnalyzer
      100%
      4/4
      N/A
      1
      AbstractFileTypeAnalyzer
      84%
      33/39
      80%
      8/10
      1.429
      AbstractSuppressionAnalyzer
      79%
      54/68
      75%
      12/16
      4.667
      AbstractSuppressionAnalyzer
      68%
      51/74
      77%
      14/18
      5.333
      AnalysisPhase
      100%
      11/11
      N/A
      0
      AnalyzerService
      89%
      17/19
      100%
      6/6
      3
      ArchiveAnalyzer
      37%
      86/230
      20%
      28/140
      6.588
      ArchiveAnalyzer
      34%
      91/261
      18%
      27/146
      6.5
      AssemblyAnalyzer
      31%
      47/147
      21%
      10/46
      7
      AssemblyAnalyzer
      32%
      48/148
      21%
      10/46
      7
      AutoconfAnalyzer
      90%
      64/71
      76%
      26/34
      3.222
      AutoconfAnalyzer
      94%
      64/68
      76%
      26/34
      3.222
      CMakeAnalyzer
      91%
      65/71
      80%
      8/10
      2.143
      CMakeAnalyzer
      94%
      71/75
      80%
      8/10
      2.625
      CPEAnalyzer
      80%
      191/238
      76%
      103/134
      4.679
      CPEAnalyzer
      80%
      191/238
      76%
      102/134
      4.679
      CPEAnalyzer$IdentifierConfidence
      100%
      4/4
      N/A
      4.679
      CPEAnalyzer$IdentifierMatch
      36%
      14/38
      0%
      0/20
      4.679
      CocoaPodsAnalyzer
      95%
      47/49
      75%
      9/12
      2
      ComposerLockAnalyzer
      78%
      32/41
      75%
      3/4
      2.167
      ComposerLockAnalyzer
      86%
      39/45
      75%
      3/4
      2.429
      CpeSuppressionAnalyzer
      90%
      9/10
      66%
      4/6
      2.333
      DependencyBundlingAnalyzer
      40%
      82/201
      30%
      64/212
      8
      DependencyBundlingAnalyzer
      42%
      85/201
      30%
      65/210
      7.2
      Experimental
      N/A
      N/A
      0
      FalsePositiveAnalyzer
      47%
      106/224
      25%
      58/230
      10.385
      FalsePositiveAnalyzer
      46%
      106/227
      25%
      58/230
      10.385
      FileNameAnalyzer
      90%
      18/20
      62%
      5/8
      2.333
      HintAnalyzer
      44%
      50/113
      57%
      29/50
      9.2
      JarAnalyzer
      66%
      351/531
      55%
      198/354
      7.581
      JarAnalyzer$ClassNameInformation
      80%
      17/21
      80%
      8/10
      7.581
      JarAnalyzer
      65%
      351/532
      55%
      198/360
      7.677
      JarAnalyzer$ClassNameInformation
      80%
      17/21
      80%
      8/10
      7.677
      NexusAnalyzer
      19%
      14/71
      3%
      1/26
      3.75
      NexusAnalyzer
      18%
      14/77
      3%
      1/30
      3.778
      NodePackageAnalyzer
      86%
      46/53
      64%
      9/14
      2.429
      OpenSSLAnalyzer
      91%
      32/35
      71%
      10/14
      2.25
      PythonDistributionAnalyzer
      80%
      96/119
      61%
      32/52
      3.769
      PythonDistributionAnalyzer
      79%
      96/121
      55%
      32/58
      4
      PythonPackageAnalyzer
      91%
      66/72
      77%
      14/18
      2
      PythonPackageAnalyzer
      95%
      66/69
      77%
      14/18
      2
      RubyBundleAuditAnalyzer
      14%
      32/221
      2%
      2/78
      6.154
      RubyBundleAuditAnalyzer
      14%
      32/221
      2%
      2/80
      6.231
      RubyBundlerAnalyzer
      66%
      20/30
      43%
      13/30
      4.5
      RubyBundlerAnalyzer$1
      100%
      2/2
      N/A
      4.5
      - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.data.central1
      86%
      53/61
      87%
      21/24
      9.5
      org.owasp.dependencycheck.data.central1
      87%
      55/63
      87%
      21/24
      9.5
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.composer.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.composer.html index fbb767a97..c1b50c73c 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.composer.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.composer.html @@ -41,6 +41,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.cpe.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.cpe.html index 46a21f5f6..03b725b43 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.cpe.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.cpe.html @@ -43,6 +43,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.cwe.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.cwe.html index ac0f568b1..0c7489bc0 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.cwe.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.cwe.html @@ -39,6 +39,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.lucene.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.lucene.html index b1d1bcf83..6037e0b78 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.lucene.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.lucene.html @@ -51,6 +51,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nexus.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nexus.html index 69524717a..cd3b6c6fb 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nexus.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nexus.html @@ -16,7 +16,7 @@ - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.data.nexus2
      20%
      22/105
      10%
      3/30
      2.444
      org.owasp.dependencycheck.data.nexus2
      22%
      22/99
      12%
      3/25
      2.278
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nuget.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nuget.html index c553c8c24..966fe4cfd 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nuget.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nuget.html @@ -16,7 +16,7 @@ - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.data.nuget4
      66%
      44/66
      15%
      6/40
      2.238
      org.owasp.dependencycheck.data.nuget4
      67%
      46/68
      15%
      6/40
      2.238
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nvdcve.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nvdcve.html index 92f48c732..bc8016e8e 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nvdcve.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.nvdcve.html @@ -52,6 +52,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.cpe.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.cpe.html index 149c1c0f3..3d920aa29 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.cpe.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.cpe.html @@ -40,6 +40,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.exception.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.exception.html index f2ef4da87..c066a944c 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.exception.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.exception.html @@ -39,6 +39,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.html index 4dde40b0f..c2de5b58b 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.html @@ -16,10 +16,10 @@ - + - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.data.update6
      15%
      52/345
      11%
      14/122
      5.68
      org.owasp.dependencycheck.data.update6
      15%
      52/346
      11%
      14/122
      5.68
      org.owasp.dependencycheck.data.update.cpe3
      0%
      0/66
      0%
      0/18
      1.5
      org.owasp.dependencycheck.data.update.exception2
      0%
      0/12
      N/A
      1
      org.owasp.dependencycheck.data.update.nvd8
      69%
      289/413
      71%
      135/188
      2.824
      org.owasp.dependencycheck.data.update.nvd8
      69%
      289/414
      71%
      135/188
      2.824
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.nvd.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.nvd.html index 5d1e7b5a6..8deb02b6e 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.nvd.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.data.update.nvd.html @@ -16,7 +16,7 @@ - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.data.update.nvd8
      69%
      289/413
      71%
      135/188
      2.824
      org.owasp.dependencycheck.data.update.nvd8
      69%
      289/414
      71%
      135/188
      2.824
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.dependency.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.dependency.html index 27cb3fdee..ac3ee564b 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.dependency.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.dependency.html @@ -16,7 +16,7 @@ - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.dependency14
      63%
      408/639
      54%
      157/288
      1.957
      org.owasp.dependencycheck.dependency14
      63%
      405/639
      54%
      156/288
      1.957
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.exception.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.exception.html index 3c6d610f1..7d761f756 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.exception.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.exception.html @@ -16,7 +16,7 @@ - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.exception5
      6%
      6/92
      0%
      0/10
      1.161
      org.owasp.dependencycheck.exception5
      10%
      10/92
      0%
      0/10
      1.161
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.html index 3ba4ebb21..4cdeac94f 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.html @@ -16,29 +16,29 @@ - + - + - + - - + + - + - - - + + + - - - - + + + +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck1
      55%
      116/208
      62%
      41/66
      3.478
      org.owasp.dependencycheck2
      64%
      181/282
      64%
      57/88
      2.895
      org.owasp.dependencycheck.agent1
      0%
      0/231
      0%
      0/38
      1.375
      org.owasp.dependencycheck.analyzer39
      58%
      1757/3029
      42%
      689/1628
      4.67
      org.owasp.dependencycheck.analyzer39
      57%
      1777/3082
      41%
      690/1652
      4.652
      org.owasp.dependencycheck.analyzer.exception2
      12%
      2/16
      N/A
      1
      org.owasp.dependencycheck.data.central1
      86%
      53/61
      87%
      21/24
      9.5
      org.owasp.dependencycheck.data.central1
      87%
      55/63
      87%
      21/24
      9.5
      org.owasp.dependencycheck.data.composer3
      79%
      53/67
      45%
      19/42
      3.417
      org.owasp.dependencycheck.data.cpe4
      70%
      101/144
      43%
      26/60
      2.621
      org.owasp.dependencycheck.data.cwe2
      39%
      13/33
      25%
      2/8
      2.8
      org.owasp.dependencycheck.data.lucene8
      78%
      97/124
      53%
      35/66
      3.32
      org.owasp.dependencycheck.data.nexus2
      20%
      22/105
      10%
      3/30
      2.444
      org.owasp.dependencycheck.data.nuget4
      66%
      44/66
      15%
      6/40
      2.238
      org.owasp.dependencycheck.data.nexus2
      22%
      22/99
      12%
      3/25
      2.278
      org.owasp.dependencycheck.data.nuget4
      67%
      46/68
      15%
      6/40
      2.238
      org.owasp.dependencycheck.data.nvdcve9
      41%
      315/754
      43%
      96/222
      4.258
      org.owasp.dependencycheck.data.update6
      15%
      52/345
      11%
      14/122
      5.68
      org.owasp.dependencycheck.data.update6
      15%
      52/346
      11%
      14/122
      5.68
      org.owasp.dependencycheck.data.update.cpe3
      0%
      0/66
      0%
      0/18
      1.5
      org.owasp.dependencycheck.data.update.exception2
      0%
      0/12
      N/A
      1
      org.owasp.dependencycheck.data.update.nvd8
      69%
      289/413
      71%
      135/188
      2.824
      org.owasp.dependencycheck.dependency14
      63%
      408/639
      54%
      157/288
      1.957
      org.owasp.dependencycheck.exception5
      6%
      6/92
      0%
      0/10
      1.161
      org.owasp.dependencycheck.data.update.nvd8
      69%
      289/414
      71%
      135/188
      2.824
      org.owasp.dependencycheck.dependency14
      63%
      405/639
      54%
      156/288
      1.957
      org.owasp.dependencycheck.exception5
      10%
      10/92
      0%
      0/10
      1.161
      org.owasp.dependencycheck.reporting4
      0%
      0/164
      0%
      0/90
      5.6
      org.owasp.dependencycheck.utils11
      63%
      237/371
      61%
      117/190
      3.782
      org.owasp.dependencycheck.xml.hints7
      71%
      128/178
      62%
      30/48
      2.229
      org.owasp.dependencycheck.xml.pom7
      60%
      132/218
      54%
      40/74
      2.388
      org.owasp.dependencycheck.xml.suppression6
      73%
      261/353
      64%
      120/186
      3.357
      org.owasp.dependencycheck.utils11
      64%
      243/375
      64%
      127/196
      3.855
      org.owasp.dependencycheck.xml.hints7
      72%
      129/179
      62%
      30/48
      2.229
      org.owasp.dependencycheck.xml.pom7
      60%
      133/219
      54%
      40/74
      2.388
      org.owasp.dependencycheck.xml.suppression6
      72%
      257/354
      64%
      120/186
      3.357
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.reporting.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.reporting.html index 8db2f0781..f49092010 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.reporting.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.reporting.html @@ -42,6 +42,6 @@ var classTable = new SortableTable(document.getElementById("classResults"), ["String", "Percentage", "Percentage", "FormattedNumber"]); classTable.sort(0); - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.utils.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.utils.html index e5c5cfd8d..1b2016c1b 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.utils.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.utils.html @@ -16,7 +16,7 @@ - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.utils11
      63%
      237/371
      61%
      117/190
      3.782
      org.owasp.dependencycheck.utils11
      64%
      243/375
      64%
      127/196
      3.855
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.hints.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.hints.html index ec4bdfc3b..f6663a44b 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.hints.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.hints.html @@ -16,7 +16,7 @@ - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.xml.hints7
      71%
      128/178
      62%
      30/48
      2.229
      org.owasp.dependencycheck.xml.hints7
      72%
      129/179
      62%
      30/48
      2.229
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.pom.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.pom.html index 27c978578..ec79012ba 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.pom.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.pom.html @@ -16,7 +16,7 @@ - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.xml.pom7
      60%
      132/218
      54%
      40/74
      2.388
      org.owasp.dependencycheck.xml.pom7
      60%
      133/219
      54%
      40/74
      2.388
      - + diff --git a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.suppression.html b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.suppression.html index 16a3a8250..2162e8e85 100644 --- a/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.suppression.html +++ b/dependency-check-core/cobertura/frame-summary-org.owasp.dependencycheck.xml.suppression.html @@ -16,7 +16,7 @@ - +
      Package # Classes Line Coverage Branch Coverage Complexity
      org.owasp.dependencycheck.xml.suppression6
      73%
      261/353
      64%
      120/186
      3.357
      org.owasp.dependencycheck.xml.suppression6
      72%
      257/354
      64%
      120/186
      3.357
      - + diff --git a/dependency-check-core/cobertura/frame-summary.html b/dependency-check-core/cobertura/frame-summary.html index 5a5d9e044..86f01e233 100644 --- a/dependency-check-core/cobertura/frame-summary.html +++ b/dependency-check-core/cobertura/frame-summary.html @@ -16,30 +16,30 @@ - - + + - + - + - - + + - + - - - + + + - - - - + + + +
      Package # Classes Line Coverage Branch Coverage Complexity
      All Packages149
      53%
      4086/7689
      45%
      1551/3438
      3.207
      org.owasp.dependencycheck1
      55%
      116/208
      62%
      41/66
      3.478
      All Packages150
      53%
      4180/7823
      45%
      1577/3485
      3.197
      org.owasp.dependencycheck2
      64%
      181/282
      64%
      57/88
      2.895
      org.owasp.dependencycheck.agent1
      0%
      0/231
      0%
      0/38
      1.375
      org.owasp.dependencycheck.analyzer39
      58%
      1757/3029
      42%
      689/1628
      4.67
      org.owasp.dependencycheck.analyzer39
      57%
      1777/3082
      41%
      690/1652
      4.652
      org.owasp.dependencycheck.analyzer.exception2
      12%
      2/16
      N/A
      1
      org.owasp.dependencycheck.data.central1
      86%
      53/61
      87%
      21/24
      9.5
      org.owasp.dependencycheck.data.central1
      87%
      55/63
      87%
      21/24
      9.5
      org.owasp.dependencycheck.data.composer3
      79%
      53/67
      45%
      19/42
      3.417
      org.owasp.dependencycheck.data.cpe4
      70%
      101/144
      43%
      26/60
      2.621
      org.owasp.dependencycheck.data.cwe2
      39%
      13/33
      25%
      2/8
      2.8
      org.owasp.dependencycheck.data.lucene8
      78%
      97/124
      53%
      35/66
      3.32
      org.owasp.dependencycheck.data.nexus2
      20%
      22/105
      10%
      3/30
      2.444
      org.owasp.dependencycheck.data.nuget4
      66%
      44/66
      15%
      6/40
      2.238
      org.owasp.dependencycheck.data.nexus2
      22%
      22/99
      12%
      3/25
      2.278
      org.owasp.dependencycheck.data.nuget4
      67%
      46/68
      15%
      6/40
      2.238
      org.owasp.dependencycheck.data.nvdcve9
      41%
      315/754
      43%
      96/222
      4.258
      org.owasp.dependencycheck.data.update6
      15%
      52/345
      11%
      14/122
      5.68
      org.owasp.dependencycheck.data.update6
      15%
      52/346
      11%
      14/122
      5.68
      org.owasp.dependencycheck.data.update.cpe3
      0%
      0/66
      0%
      0/18
      1.5
      org.owasp.dependencycheck.data.update.exception2
      0%
      0/12
      N/A
      1
      org.owasp.dependencycheck.data.update.nvd8
      69%
      289/413
      71%
      135/188
      2.824
      org.owasp.dependencycheck.dependency14
      63%
      408/639
      54%
      157/288
      1.957
      org.owasp.dependencycheck.exception5
      6%
      6/92
      0%
      0/10
      1.161
      org.owasp.dependencycheck.data.update.nvd8
      69%
      289/414
      71%
      135/188
      2.824
      org.owasp.dependencycheck.dependency14
      63%
      405/639
      54%
      156/288
      1.957
      org.owasp.dependencycheck.exception5
      10%
      10/92
      0%
      0/10
      1.161
      org.owasp.dependencycheck.reporting4
      0%
      0/164
      0%
      0/90
      5.6
      org.owasp.dependencycheck.utils11
      63%
      237/371
      61%
      117/190
      3.782
      org.owasp.dependencycheck.xml.hints7
      71%
      128/178
      62%
      30/48
      2.229
      org.owasp.dependencycheck.xml.pom7
      60%
      132/218
      54%
      40/74
      2.388
      org.owasp.dependencycheck.xml.suppression6
      73%
      261/353
      64%
      120/186
      3.357
      org.owasp.dependencycheck.utils11
      64%
      243/375
      64%
      127/196
      3.855
      org.owasp.dependencycheck.xml.hints7
      72%
      129/179
      62%
      30/48
      2.229
      org.owasp.dependencycheck.xml.pom7
      60%
      133/219
      54%
      40/74
      2.388
      org.owasp.dependencycheck.xml.suppression6
      72%
      257/354
      64%
      120/186
      3.357
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.AnalysisTask.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.AnalysisTask.html new file mode 100644 index 000000000..46624b4d0 --- /dev/null +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.AnalysisTask.html @@ -0,0 +1,235 @@ + + + + +Coverage Report + + + + +
      Coverage Report - org.owasp.dependencycheck.AnalysisTask
      +
       
      + + + + +
      Classes in this File Line Coverage Branch Coverage Complexity
      AnalysisTask
      66%
      18/27
      100%
      4/4
      2.667
      +
       
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       1  
       /*
       2  
        * This file is part of dependency-check-core.
       3  
        *
       4  
        * Licensed under the Apache License, Version 2.0 (the "License");
       5  
        * you may not use this file except in compliance with the License.
       6  
        * You may obtain a copy of the License at
       7  
        *
       8  
        *     http://www.apache.org/licenses/LICENSE-2.0
       9  
        *
       10  
        * Unless required by applicable law or agreed to in writing, software
       11  
        * distributed under the License is distributed on an "AS IS" BASIS,
       12  
        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       13  
        * See the License for the specific language governing permissions and
       14  
        * limitations under the License.
       15  
        *
       16  
        * Copyright (c) 2016 Stefan Neuhaus. All Rights Reserved.
       17  
        */
       18  
       package org.owasp.dependencycheck;
       19  
       
       20  
       import org.owasp.dependencycheck.analyzer.Analyzer;
       21  
       import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
       22  
       import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
       23  
       import org.owasp.dependencycheck.dependency.Dependency;
       24  
       import org.owasp.dependencycheck.utils.Settings;
       25  
       import org.slf4j.Logger;
       26  
       import org.slf4j.LoggerFactory;
       27  
       
       28  
       import java.util.List;
       29  
       import java.util.concurrent.Callable;
       30  
       
       31  
       /**
       32  
        * Task to support parallelism of dependency-check analysis.
       33  
        * Analyses a single {@link Dependency} by a specific {@link Analyzer}.
       34  
        *
       35  
        * @author Stefan Neuhaus
       36  
        */
       37  101
       class AnalysisTask implements Callable<Void> {
       38  
       
       39  
           /**
       40  
            * Instance of the logger.
       41  
            */
       42  1
           private static final Logger LOGGER = LoggerFactory.getLogger(AnalysisTask.class);
       43  
       
       44  
           /**
       45  
            * A reference to the analyzer.
       46  
            */
       47  
           private final Analyzer analyzer;
       48  
           /**
       49  
            * The dependency to analyze.
       50  
            */
       51  
           private final Dependency dependency;
       52  
           /**
       53  
            * A reference to the dependency-check engine.
       54  
            */
       55  
           private final Engine engine;
       56  
           /**
       57  
            * The list of exceptions that may occur during analysis.
       58  
            */
       59  
           private final List<Throwable> exceptions;
       60  
       
       61  
           /**
       62  
            * Creates a new analysis task.
       63  
            *
       64  
            * @param analyzer a reference of the analyzer to execute
       65  
            * @param dependency the dependency to analyze
       66  
            * @param engine the dependency-check engine
       67  
            * @param exceptions exceptions that occur during analysis will be added to
       68  
            * this collection of exceptions
       69  
            */
       70  107
           AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List<Throwable> exceptions) {
       71  107
               this.analyzer = analyzer;
       72  107
               this.dependency = dependency;
       73  107
               this.engine = engine;
       74  107
               this.exceptions = exceptions;
       75  107
           }
       76  
       
       77  
           /**
       78  
            * Executes the analysis task.
       79  
            *
       80  
            * @return null
       81  
            * @throws Exception thrown if unable to execute the analysis task
       82  
            */
       83  
           @Override
       84  
           public Void call() {
       85  102
               Settings.initialize();
       86  
       
       87  102
               if (shouldAnalyze()) {
       88  39
                   LOGGER.debug("Begin Analysis of '{}' ({})", dependency.getActualFilePath(), analyzer.getName());
       89  
                   try {
       90  39
                       analyzer.analyze(dependency, engine);
       91  0
                   } catch (AnalysisException ex) {
       92  0
                       LOGGER.warn("An error occurred while analyzing '{}' ({}).", dependency.getActualFilePath(), analyzer.getName());
       93  0
                       LOGGER.debug("", ex);
       94  0
                       exceptions.add(ex);
       95  0
                   } catch (Throwable ex) {
       96  0
                       LOGGER.warn("An unexpected error occurred during analysis of '{}' ({}): {}",
       97  0
                               dependency.getActualFilePath(), analyzer.getName(), ex.getMessage());
       98  0
                       LOGGER.debug("", ex);
       99  0
                       exceptions.add(ex);
       100  39
                   }
       101  
               }
       102  
       
       103  102
               return null;
       104  
           }
       105  
       
       106  
           /**
       107  
            * Determines if the analyzer can analyze the given dependency.
       108  
            *
       109  
            * @return whether or not the analyzer can analyze the dependency
       110  
            */
       111  
           boolean shouldAnalyze() {
       112  104
               if (analyzer instanceof FileTypeAnalyzer) {
       113  70
                   final FileTypeAnalyzer fileTypeAnalyzer = (FileTypeAnalyzer) analyzer;
       114  69
                   return fileTypeAnalyzer.accept(dependency.getActualFile());
       115  
               }
       116  
       
       117  32
               return true;
       118  
           }
       119  
       }
      + + + + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.Engine.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.Engine.html index a4c3ec765..de14e8ba1 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.Engine.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.Engine.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      Engine
      55%
      116/208
      62%
      41/66
      3.478
      Engine
      63%
      163/255
      63%
      53/84
      2.914
       
      @@ -64,45 +64,45 @@  23  
       import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
       24   -
       import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
      -  25  
       import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory;
      -  26   +  25  
       import org.owasp.dependencycheck.data.nvdcve.CveDB;
      -  27   +  26  
       import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
      -  28   +  27  
       import org.owasp.dependencycheck.data.update.CachedWebDataSource;
      -  29   +  28  
       import org.owasp.dependencycheck.data.update.UpdateService;
      -  30   +  29  
       import org.owasp.dependencycheck.data.update.exception.UpdateException;
      -  31   +  30  
       import org.owasp.dependencycheck.dependency.Dependency;
      -  32   -
       import org.owasp.dependencycheck.exception.NoDataException;
      -  33   +  31  
       import org.owasp.dependencycheck.exception.ExceptionCollection;
      -  34   +  32  
       import org.owasp.dependencycheck.exception.InitializationException;
      -  35   +  33   +
       import org.owasp.dependencycheck.exception.NoDataException;
      +  34  
       import org.owasp.dependencycheck.utils.InvalidSettingException;
      -  36   +  35  
       import org.owasp.dependencycheck.utils.Settings;
      -  37   +  36  
       import org.slf4j.Logger;
      -  38   +  37  
       import org.slf4j.LoggerFactory;
      -  39   +  38  
       
      -  40   +  39  
       import java.io.File;
      -  41   +  40  
       import java.io.FileFilter;
      -  42   +  41  
       import java.util.ArrayList;
      -  43   +  42  
       import java.util.Collection;
      +  43   +
       import java.util.Collections;
       44  
       import java.util.EnumMap;
       45   @@ -116,827 +116,1204 @@  49  
       import java.util.Set;
       50   -
       
      +
       import java.util.concurrent.CancellationException;
       51   -
       /**
      +
       import java.util.concurrent.ExecutionException;
       52   -
        * Scans files, directories, etc. for Dependencies. Analyzers are loaded and
      +
       import java.util.concurrent.ExecutorService;
       53   -
        * used to process the files found by the scan, if a file is encountered and an
      +
       import java.util.concurrent.Executors;
       54   -
        * Analyzer is associated with the file type then the file is turned into a
      +
       import java.util.concurrent.Future;
       55   -
        * dependency.
      +
       import java.util.concurrent.TimeUnit;
       56   -
        *
      +
       
       57   -
        * @author Jeremy Long
      +
       /**
       58   -
        */
      +
        * Scans files, directories, etc. for Dependencies. Analyzers are loaded and
       59   -
       public class Engine implements FileFilter {
      +
        * used to process the files found by the scan, if a file is encountered and an
       60   -
       
      +
        * Analyzer is associated with the file type then the file is turned into a
       61   -
           /**
      +
        * dependency.
       62   -
            * The list of dependencies.
      +
        *
       63   -
            */
      -  64  4
           private List<Dependency> dependencies = new ArrayList<Dependency>();
      +
        * @author Jeremy Long
      +  64   +
        */
       65   -
           /**
      +
       public class Engine implements FileFilter {
       66   -
            * A Map of analyzers grouped by Analysis phase.
      +
       
       67   -
            */
      -  68  4
           private final Map<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class);
      +
           /**
      +  68   +
            * The list of dependencies.
       69   -
       
      -  70   -
           /**
      -  71   -
            * A Map of analyzers grouped by Analysis phase.
      -  72  
            */
      -  73  4
           private final Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>();
      -  74   -
       
      -  75   +  70  6
           private final List<Dependency> dependencies = Collections.synchronizedList(new ArrayList<Dependency>());
      +  71  
           /**
      +  72   +
            * A Map of analyzers grouped by Analysis phase.
      +  73   +
            */
      +  74  6
           private final Map<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class);
      +  75   +
       
       76   -
            * The ClassLoader to use when dynamically loading Analyzer and Update
      +
           /**
       77   -
            * services.
      +
            * A Map of analyzers grouped by Analysis phase.
       78  
            */
      -  79  4
           private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader();
      +  79  6
           private final Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>();
       80   -
           /**
      +
       
       81   -
            * The Logger for use throughout the class.
      +
           /**
       82   -
            */
      -  83  1
           private static final Logger LOGGER = LoggerFactory.getLogger(Engine.class);
      +
            * The ClassLoader to use when dynamically loading Analyzer and Update
      +  83   +
            * services.
       84   -
       
      -  85   -
           /**
      +
            */
      +  85  6
           private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader();
       86   -
            * Creates a new Engine.
      +
           /**
       87   -
            *
      +
            * The Logger for use throughout the class.
       88   -
            * @throws DatabaseException thrown if there is an error connecting to the
      -  89   -
            * database
      +
            */
      +  89  1
           private static final Logger LOGGER = LoggerFactory.getLogger(Engine.class);
       90   -
            */
      -  91  4
           public Engine() throws DatabaseException {
      -  92  4
               initializeEngine();
      -  93  4
           }
      -  94  
       
      -  95   +  91  
           /**
      -  96   +  92  
            * Creates a new Engine.
      -  97   +  93  
            *
      -  98   -
            * @param serviceClassLoader a reference the class loader being used
      -  99   +  94  
            * @throws DatabaseException thrown if there is an error connecting to the
      +  95   +
            * database
      +  96   +
            */
      +  97  6
           public Engine() throws DatabaseException {
      +  98  6
               initializeEngine();
      +  99  6
           }
       100   -
            * database
      +
       
       101   -
            */
      -  102  0
           public Engine(ClassLoader serviceClassLoader) throws DatabaseException {
      -  103  0
               this.serviceClassLoader = serviceClassLoader;
      -  104  0
               initializeEngine();
      -  105  0
           }
      -  106   -
       
      -  107  
           /**
      -  108   -
            * Creates a new Engine using the specified classloader to dynamically load
      -  109   -
            * Analyzer and Update services.
      -  110   +  102   +
            * Creates a new Engine.
      +  103  
            *
      -  111   +  104   +
            * @param serviceClassLoader a reference the class loader being used
      +  105  
            * @throws DatabaseException thrown if there is an error connecting to the
      -  112   +  106  
            * database
      +  107   +
            */
      +  108  0
           public Engine(ClassLoader serviceClassLoader) throws DatabaseException {
      +  109  0
               this.serviceClassLoader = serviceClassLoader;
      +  110  0
               initializeEngine();
      +  111  0
           }
      +  112   +
       
       113   -
            */
      +
           /**
       114   -
           protected final void initializeEngine() throws DatabaseException {
      -  115  4
               ConnectionFactory.initialize();
      -  116  4
               loadAnalyzers();
      -  117  4
           }
      +
            * Creates a new Engine using the specified classloader to dynamically load
      +  115   +
            * Analyzer and Update services.
      +  116   +
            *
      +  117   +
            * @throws DatabaseException thrown if there is an error connecting to the
       118   -
       
      +
            * database
       119   -
           /**
      +
            */
       120   -
            * Properly cleans up resources allocated during analysis.
      -  121   -
            */
      -  122   -
           public void cleanup() {
      -  123  0
               ConnectionFactory.cleanup();
      -  124  0
           }
      +
           protected final void initializeEngine() throws DatabaseException {
      +  121  6
               ConnectionFactory.initialize();
      +  122  6
               loadAnalyzers();
      +  123  6
           }
      +  124   +
       
       125   -
       
      +
           /**
       126   -
           /**
      +
            * Properly cleans up resources allocated during analysis.
       127   -
            * Loads the analyzers specified in the configuration file (or system
      +
            */
       128   -
            * properties).
      -  129   -
            */
      -  130   -
           private void loadAnalyzers() {
      -  131  4
               if (!analyzers.isEmpty()) {
      -  132  0
                   return;
      +
           public void cleanup() {
      +  129  0
               ConnectionFactory.cleanup();
      +  130  0
           }
      +  131   +
       
      +  132   +
           /**
       133   -
               }
      -  134  44
               for (AnalysisPhase phase : AnalysisPhase.values()) {
      -  135  40
                   analyzers.put(phase, new ArrayList<Analyzer>());
      +
            * Loads the analyzers specified in the configuration file (or system
      +  134   +
            * properties).
      +  135   +
            */
       136   +
           private void loadAnalyzers() {
      +  137  6
               if (!analyzers.isEmpty()) {
      +  138  0
                   return;
      +  139  
               }
      -  137   +  140  66
               for (AnalysisPhase phase : AnalysisPhase.values()) {
      +  141  60
                   analyzers.put(phase, new ArrayList<Analyzer>());
      +  142   +
               }
      +  143  
       
      -  138  4
               final AnalyzerService service = new AnalyzerService(serviceClassLoader);
      -  139  4
               final List<Analyzer> iterator = service.getAnalyzers();
      -  140  4
               for (Analyzer a : iterator) {
      -  141  104
                   analyzers.get(a.getAnalysisPhase()).add(a);
      -  142  104
                   if (a instanceof FileTypeAnalyzer) {
      -  143  72
                       this.fileTypeAnalyzers.add((FileTypeAnalyzer) a);
      -  144   -
                   }
      -  145  104
               }
      -  146  4
           }
      -  147   -
       
      -  148   -
           /**
      -  149   -
            * Get the List of the analyzers for a specific phase of analysis.
      +  144  6
               final AnalyzerService service = new AnalyzerService(serviceClassLoader);
      +  145  6
               final List<Analyzer> iterator = service.getAnalyzers();
      +  146  6
               for (Analyzer a : iterator) {
      +  147  156
                   analyzers.get(a.getAnalysisPhase()).add(a);
      +  148  156
                   if (a instanceof FileTypeAnalyzer) {
      +  149  108
                       this.fileTypeAnalyzers.add((FileTypeAnalyzer) a);
       150   -
            *
      -  151   -
            * @param phase the phase to get the configured analyzers.
      -  152   -
            * @return the analyzers loaded
      +
                   }
      +  151  156
               }
      +  152  6
           }
       153   -
            */
      +
       
       154   -
           public List<Analyzer> getAnalyzers(AnalysisPhase phase) {
      -  155  0
               return analyzers.get(phase);
      +
           /**
      +  155   +
            * Get the List of the analyzers for a specific phase of analysis.
       156   -
           }
      -  157   -
       
      -  158   -
           /**
      -  159   -
            * Get the dependencies identified.
      -  160  
            *
      -  161   -
            * @return the dependencies identified
      -  162   +  157   +
            * @param phase the phase to get the configured analyzers.
      +  158   +
            * @return the analyzers loaded
      +  159  
            */
      -  163   -
           public List<Dependency> getDependencies() {
      -  164  48
               return dependencies;
      -  165   +  160   +
           public List<Analyzer> getAnalyzers(AnalysisPhase phase) {
      +  161  0
               return analyzers.get(phase);
      +  162  
           }
      -  166   +  163  
       
      -  167   +  164  
           /**
      +  165   +
            * Get the dependencies identified. The returned list is a reference to the
      +  166   +
            * engine's synchronized list. You must synchronize on it, when you modify
      +  167   +
            * and iterate over it from multiple threads. E.g. this holds for analyzers
       168   -
            * Sets the dependencies.
      +
            * supporting parallel processing during their analysis phase.
       169  
            *
       170   -
            * @param dependencies the dependencies
      +
            * @return the dependencies identified
       171   -
            */
      +
            * @see Collections#synchronizedList(List)
       172   -
           public void setDependencies(List<Dependency> dependencies) {
      -  173  0
               this.dependencies = dependencies;
      -  174  0
           }
      -  175   -
       
      +
            * @see Analyzer#supportsParallelProcessing()
      +  173   +
            */
      +  174   +
           public List<Dependency> getDependencies() {
      +  175  46
               return dependencies;
       176   -
           /**
      +
           }
       177   -
            * Scans an array of files or directories. If a directory is specified, it
      +
       
       178   -
            * will be scanned recursively. Any dependencies identified are added to the
      +
           /**
       179   -
            * dependency collection.
      +
            * Sets the dependencies.
       180  
            *
       181   -
            * @param paths an array of paths to files or directories to be analyzed
      +
            * @param dependencies the dependencies
       182   -
            * @return the list of dependencies scanned
      +
            */
       183   -
            * @since v0.3.2.5
      -  184   -
            */
      -  185   -
           public List<Dependency> scan(String[] paths) {
      -  186  0
               final List<Dependency> deps = new ArrayList<Dependency>();
      -  187  0
               for (String path : paths) {
      -  188  0
                   final List<Dependency> d = scan(path);
      -  189  0
                   if (d != null) {
      -  190  0
                       deps.addAll(d);
      +
           public void setDependencies(List<Dependency> dependencies) {
      +  184  0
               synchronized (this.dependencies) {
      +  185  0
                   this.dependencies.clear();
      +  186  0
                   this.dependencies.addAll(dependencies);
      +  187  0
               }
      +  188  0
           }
      +  189   +
       
      +  190   +
           /**
       191   -
                   }
      -  192   -
               }
      -  193  0
               return deps;
      -  194   -
           }
      -  195   -
       
      -  196   -
           /**
      -  197   -
            * Scans a given file or directory. If a directory is specified, it will be
      -  198   -
            * scanned recursively. Any dependencies identified are added to the
      -  199   -
            * dependency collection.
      -  200   -
            *
      -  201   -
            * @param path the path to a file or directory to be analyzed
      -  202   -
            * @return the list of dependencies scanned
      -  203   -
            */
      -  204   -
           public List<Dependency> scan(String path) {
      -  205  0
               final File file = new File(path);
      -  206  0
               return scan(file);
      -  207   -
           }
      -  208   -
       
      -  209   -
           /**
      -  210  
            * Scans an array of files or directories. If a directory is specified, it
      -  211   +  192  
            * will be scanned recursively. Any dependencies identified are added to the
      +  193   +
            * dependency collection.
      +  194   +
            *
      +  195   +
            * @param paths an array of paths to files or directories to be analyzed
      +  196   +
            * @return the list of dependencies scanned
      +  197   +
            * @since v0.3.2.5
      +  198   +
            */
      +  199   +
           public List<Dependency> scan(String[] paths) {
      +  200  0
               return scan(paths, null);
      +  201   +
           }
      +  202   +
       
      +  203   +
           /**
      +  204   +
            * Scans an array of files or directories. If a directory is specified, it
      +  205   +
            * will be scanned recursively. Any dependencies identified are added to the
      +  206   +
            * dependency collection.
      +  207   +
            *
      +  208   +
            * @param paths an array of paths to files or directories to be analyzed
      +  209   +
            * @param projectReference the name of the project or scope in which the
      +  210   +
            * dependency was identified
      +  211   +
            * @return the list of dependencies scanned
       212   -
            * dependency collection.
      +
            * @since v1.4.4
       213   -
            *
      +
            */
       214   -
            * @param files an array of paths to files or directories to be analyzed.
      -  215   -
            * @return the list of dependencies
      -  216   -
            * @since v0.3.2.5
      -  217   -
            */
      -  218   -
           public List<Dependency> scan(File[] files) {
      -  219  0
               final List<Dependency> deps = new ArrayList<Dependency>();
      -  220  0
               for (File file : files) {
      -  221  0
                   final List<Dependency> d = scan(file);
      -  222  0
                   if (d != null) {
      -  223  0
                       deps.addAll(d);
      +
           public List<Dependency> scan(String[] paths, String projectReference) {
      +  215  0
               final List<Dependency> deps = new ArrayList<Dependency>();
      +  216  0
               for (String path : paths) {
      +  217  0
                   final List<Dependency> d = scan(path, projectReference);
      +  218  0
                   if (d != null) {
      +  219  0
                       deps.addAll(d);
      +  220   +
                   }
      +  221   +
               }
      +  222  0
               return deps;
      +  223   +
           }
       224   -
                   }
      +
       
       225   -
               }
      -  226  0
               return deps;
      -  227   -
           }
      -  228   -
       
      -  229  
           /**
      -  230   -
            * Scans a collection of files or directories. If a directory is specified,
      -  231   -
            * it will be scanned recursively. Any dependencies identified are added to
      -  232   -
            * the dependency collection.
      -  233   -
            *
      -  234   -
            * @param files a set of paths to files or directories to be analyzed
      -  235   -
            * @return the list of dependencies scanned
      -  236   -
            * @since v0.3.2.5
      -  237   -
            */
      -  238   -
           public List<Dependency> scan(Collection<File> files) {
      -  239  0
               final List<Dependency> deps = new ArrayList<Dependency>();
      -  240  0
               for (File file : files) {
      -  241  0
                   final List<Dependency> d = scan(file);
      -  242  0
                   if (d != null) {
      -  243  0
                       deps.addAll(d);
      -  244   -
                   }
      -  245  0
               }
      -  246  0
               return deps;
      -  247   -
           }
      -  248   -
       
      -  249   -
           /**
      -  250   +  226  
            * Scans a given file or directory. If a directory is specified, it will be
      -  251   +  227  
            * scanned recursively. Any dependencies identified are added to the
      -  252   +  228  
            * dependency collection.
      -  253   +  229  
            *
      -  254   -
            * @param file the path to a file or directory to be analyzed
      -  255   +  230   +
            * @param path the path to a file or directory to be analyzed
      +  231  
            * @return the list of dependencies scanned
      -  256   -
            * @since v0.3.2.4
      -  257   +  232  
            */
      -  258   -
           public List<Dependency> scan(File file) {
      -  259  5
               if (file.exists()) {
      -  260  5
                   if (file.isDirectory()) {
      -  261  3
                       return scanDirectory(file);
      -  262   -
                   } else {
      -  263  2
                       final Dependency d = scanFile(file);
      -  264  2
                       if (d != null) {
      -  265  2
                           final List<Dependency> deps = new ArrayList<Dependency>();
      -  266  2
                           deps.add(d);
      -  267  2
                           return deps;
      -  268   -
                       }
      -  269   -
                   }
      -  270   -
               }
      -  271  0
               return null;
      -  272   +  233   +
           public List<Dependency> scan(String path) {
      +  234  0
               return scan(path, null);
      +  235  
           }
      -  273   +  236  
       
      -  274   +  237  
           /**
      -  275   -
            * Recursively scans files and directories. Any dependencies identified are
      -  276   -
            * added to the dependency collection.
      -  277   -
            *
      -  278   -
            * @param dir the directory to scan
      -  279   -
            * @return the list of Dependency objects scanned
      -  280   -
            */
      -  281   -
           protected List<Dependency> scanDirectory(File dir) {
      -  282  46
               final File[] files = dir.listFiles();
      -  283  46
               final List<Dependency> deps = new ArrayList<Dependency>();
      -  284  46
               if (files != null) {
      -  285  93
                   for (File f : files) {
      -  286  47
                       if (f.isDirectory()) {
      -  287  43
                           final List<Dependency> d = scanDirectory(f);
      -  288  43
                           if (d != null) {
      -  289  43
                               deps.addAll(d);
      -  290   -
                           }
      -  291  43
                       } else {
      -  292  4
                           final Dependency d = scanFile(f);
      -  293  4
                           deps.add(d);
      -  294   -
                       }
      -  295   -
                   }
      -  296   -
               }
      -  297  46
               return deps;
      -  298   -
           }
      -  299   -
       
      -  300   -
           /**
      -  301   -
            * Scans a specified file. If a dependency is identified it is added to the
      -  302   +  238   +
            * Scans a given file or directory. If a directory is specified, it will be
      +  239   +
            * scanned recursively. Any dependencies identified are added to the
      +  240  
            * dependency collection.
      -  303   +  241  
            *
      -  304   -
            * @param file The file to scan
      -  305   -
            * @return the scanned dependency
      -  306   +  242   +
            * @param path the path to a file or directory to be analyzed
      +  243   +
            * @param projectReference the name of the project or scope in which the
      +  244   +
            * dependency was identified
      +  245   +
            * @return the list of dependencies scanned
      +  246   +
            * @since v1.4.4
      +  247  
            */
      -  307   -
           protected Dependency scanFile(File file) {
      -  308  6
               Dependency dependency = null;
      -  309  6
               if (file.isFile()) {
      -  310  6
                   if (accept(file)) {
      -  311  4
                       dependency = new Dependency(file);
      -  312  4
                       dependencies.add(dependency);
      -  313   -
                   }
      -  314   -
               } else {
      -  315  0
                   LOGGER.debug("Path passed to scanFile(File) is not a file: {}. Skipping the file.", file);
      -  316   -
               }
      -  317  6
               return dependency;
      -  318   +  248   +
           public List<Dependency> scan(String path, String projectReference) {
      +  249  0
               final File file = new File(path);
      +  250  0
               return scan(file, projectReference);
      +  251  
           }
      -  319   +  252  
       
      -  320   +  253  
           /**
      -  321   -
            * Runs the analyzers against all of the dependencies. Since the mutable
      -  322   -
            * dependencies list is exposed via {@link #getDependencies()}, this method
      -  323   -
            * iterates over a copy of the dependencies list. Thus, the potential for
      -  324   -
            * {@link java.util.ConcurrentModificationException}s is avoided, and
      -  325   -
            * analyzers may safely add or remove entries from the dependencies list.
      -  326   +  254   +
            * Scans an array of files or directories. If a directory is specified, it
      +  255   +
            * will be scanned recursively. Any dependencies identified are added to the
      +  256   +
            * dependency collection.
      +  257  
            *
      -  327   -
            * Every effort is made to complete analysis on the dependencies. In some
      -  328   -
            * cases an exception will occur with part of the analysis being performed
      -  329   -
            * which may not affect the entire analysis. If an exception occurs it will
      -  330   -
            * be included in the thrown exception collection.
      -  331   -
            *
      -  332   -
            * @throws ExceptionCollection a collections of any exceptions that occurred
      -  333   -
            * during analysis
      -  334   +  258   +
            * @param files an array of paths to files or directories to be analyzed.
      +  259   +
            * @return the list of dependencies
      +  260   +
            * @since v0.3.2.5
      +  261  
            */
      -  335   -
           public void analyzeDependencies() throws ExceptionCollection {
      -  336  2
               final List<Throwable> exceptions = new ArrayList<Throwable>();
      -  337  2
               boolean autoUpdate = true;
      -  338   -
               try {
      -  339  2
                   autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
      -  340  0
               } catch (InvalidSettingException ex) {
      -  341  0
                   LOGGER.debug("Invalid setting for auto-update; using true.");
      -  342  0
                   exceptions.add(ex);
      -  343  2
               }
      -  344  2
               if (autoUpdate) {
      -  345   -
                   try {
      -  346  0
                       doUpdates();
      -  347  0
                   } catch (UpdateException ex) {
      -  348  0
                       exceptions.add(ex);
      -  349  0
                       LOGGER.warn("Unable to update Cached Web DataSource, using local "
      -  350   -
                               + "data instead. Results may not include recent vulnerabilities.");
      -  351  0
                       LOGGER.debug("Update Error", ex);
      -  352  0
                   }
      -  353   +  262   +
           public List<Dependency> scan(File[] files) {
      +  263  0
               return scan(files, null);
      +  264   +
           }
      +  265   +
       
      +  266   +
           /**
      +  267   +
            * Scans an array of files or directories. If a directory is specified, it
      +  268   +
            * will be scanned recursively. Any dependencies identified are added to the
      +  269   +
            * dependency collection.
      +  270   +
            *
      +  271   +
            * @param files an array of paths to files or directories to be analyzed.
      +  272   +
            * @param projectReference the name of the project or scope in which the
      +  273   +
            * dependency was identified
      +  274   +
            * @return the list of dependencies
      +  275   +
            * @since v1.4.4
      +  276   +
            */
      +  277   +
           public List<Dependency> scan(File[] files, String projectReference) {
      +  278  0
               final List<Dependency> deps = new ArrayList<Dependency>();
      +  279  0
               for (File file : files) {
      +  280  0
                   final List<Dependency> d = scan(file, projectReference);
      +  281  0
                   if (d != null) {
      +  282  0
                       deps.addAll(d);
      +  283   +
                   }
      +  284  
               }
      -  354   +  285  0
               return deps;
      +  286   +
           }
      +  287  
       
      -  355   -
               //need to ensure that data exists
      -  356   -
               try {
      -  357  2
                   ensureDataExists();
      -  358  0
               } catch (NoDataException ex) {
      -  359  0
                   LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage());
      -  360  0
                   LOGGER.debug("", ex);
      -  361  0
                   exceptions.add(ex);
      -  362  0
                   throw new ExceptionCollection("Unable to continue dependency-check analysis.", exceptions, true);
      -  363  0
               } catch (DatabaseException ex) {
      -  364  0
                   LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage());
      -  365  0
                   LOGGER.debug("", ex);
      -  366  0
                   exceptions.add(ex);
      -  367  0
                   throw new ExceptionCollection("Unable to connect to the dependency-check database", exceptions, true);
      -  368  2
               }
      +  288   +
           /**
      +  289   +
            * Scans a collection of files or directories. If a directory is specified,
      +  290   +
            * it will be scanned recursively. Any dependencies identified are added to
      +  291   +
            * the dependency collection.
      +  292   +
            *
      +  293   +
            * @param files a set of paths to files or directories to be analyzed
      +  294   +
            * @return the list of dependencies scanned
      +  295   +
            * @since v0.3.2.5
      +  296   +
            */
      +  297   +
           public List<Dependency> scan(Collection<File> files) {
      +  298  0
               return scan(files, null);
      +  299   +
           }
      +  300   +
       
      +  301   +
           /**
      +  302   +
            * Scans a collection of files or directories. If a directory is specified,
      +  303   +
            * it will be scanned recursively. Any dependencies identified are added to
      +  304   +
            * the dependency collection.
      +  305   +
            *
      +  306   +
            * @param files a set of paths to files or directories to be analyzed
      +  307   +
            * @param projectReference the name of the project or scope in which the
      +  308   +
            * dependency was identified
      +  309   +
            * @return the list of dependencies scanned
      +  310   +
            * @since v1.4.4
      +  311   +
            */
      +  312   +
           public List<Dependency> scan(Collection<File> files, String projectReference) {
      +  313  0
               final List<Dependency> deps = new ArrayList<Dependency>();
      +  314  0
               for (File file : files) {
      +  315  0
                   final List<Dependency> d = scan(file, projectReference);
      +  316  0
                   if (d != null) {
      +  317  0
                       deps.addAll(d);
      +  318   +
                   }
      +  319  0
               }
      +  320  0
               return deps;
      +  321   +
           }
      +  322   +
       
      +  323   +
           /**
      +  324   +
            * Scans a given file or directory. If a directory is specified, it will be
      +  325   +
            * scanned recursively. Any dependencies identified are added to the
      +  326   +
            * dependency collection.
      +  327   +
            *
      +  328   +
            * @param file the path to a file or directory to be analyzed
      +  329   +
            * @return the list of dependencies scanned
      +  330   +
            * @since v0.3.2.4
      +  331   +
            */
      +  332   +
           public List<Dependency> scan(File file) {
      +  333  5
               return scan(file, null);
      +  334   +
           }
      +  335   +
       
      +  336   +
           /**
      +  337   +
            * Scans a given file or directory. If a directory is specified, it will be
      +  338   +
            * scanned recursively. Any dependencies identified are added to the
      +  339   +
            * dependency collection.
      +  340   +
            *
      +  341   +
            * @param file the path to a file or directory to be analyzed
      +  342   +
            * @param projectReference the name of the project or scope in which the
      +  343   +
            * dependency was identified
      +  344   +
            * @return the list of dependencies scanned
      +  345   +
            * @since v1.4.4
      +  346   +
            */
      +  347   +
           public List<Dependency> scan(File file, String projectReference) {
      +  348  5
               if (file.exists()) {
      +  349  5
                   if (file.isDirectory()) {
      +  350  3
                       return scanDirectory(file, projectReference);
      +  351   +
                   } else {
      +  352  2
                       final Dependency d = scanFile(file, projectReference);
      +  353  2
                       if (d != null) {
      +  354  2
                           final List<Dependency> deps = new ArrayList<Dependency>();
      +  355  2
                           deps.add(d);
      +  356  2
                           return deps;
      +  357   +
                       }
      +  358   +
                   }
      +  359   +
               }
      +  360  0
               return null;
      +  361   +
           }
      +  362   +
       
      +  363   +
           /**
      +  364   +
            * Recursively scans files and directories. Any dependencies identified are
      +  365   +
            * added to the dependency collection.
      +  366   +
            *
      +  367   +
            * @param dir the directory to scan
      +  368   +
            * @return the list of Dependency objects scanned
       369   -
       
      -  370  2
               LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
      -  371  2
               LOGGER.info("Analysis Started");
      -  372  2
               final long analysisStart = System.currentTimeMillis();
      +
            */
      +  370   +
           protected List<Dependency> scanDirectory(File dir) {
      +  371  0
               return scanDirectory(dir, null);
      +  372   +
           }
       373  
       
       374   -
               // analysis phases
      -  375  22
               for (AnalysisPhase phase : AnalysisPhase.values()) {
      -  376  20
                   final List<Analyzer> analyzerList = analyzers.get(phase);
      +
           /**
      +  375   +
            * Recursively scans files and directories. Any dependencies identified are
      +  376   +
            * added to the dependency collection.
       377   -
       
      -  378  20
                   for (Analyzer a : analyzerList) {
      +
            *
      +  378   +
            * @param dir the directory to scan
       379   -
                       try {
      -  380  52
                           a = initializeAnalyzer(a);
      -  381  1
                       } catch (InitializationException ex) {
      -  382  1
                           exceptions.add(ex);
      -  383  1
                           continue;
      -  384  51
                       }
      -  385   -
       
      -  386   -
                       /* need to create a copy of the collection because some of the
      -  387   -
                        * analyzers may modify it. This prevents ConcurrentModificationExceptions.
      -  388   -
                        * This is okay for adds/deletes because it happens per analyzer.
      -  389   -
                        */
      -  390  51
                       LOGGER.debug("Begin Analyzer '{}'", a.getName());
      -  391  51
                       final Set<Dependency> dependencySet = new HashSet<Dependency>(dependencies);
      -  392  51
                       for (Dependency d : dependencySet) {
      -  393  102
                           boolean shouldAnalyze = true;
      -  394  102
                           if (a instanceof FileTypeAnalyzer) {
      -  395  70
                               final FileTypeAnalyzer fAnalyzer = (FileTypeAnalyzer) a;
      -  396  70
                               shouldAnalyze = fAnalyzer.accept(d.getActualFile());
      +
            * @param projectReference the name of the project or scope in which the
      +  380   +
            * dependency was identified
      +  381   +
            * @return the list of Dependency objects scanned
      +  382   +
            * @since v1.4.4
      +  383   +
            */
      +  384   +
           protected List<Dependency> scanDirectory(File dir, String projectReference) {
      +  385  46
               final File[] files = dir.listFiles();
      +  386  46
               final List<Dependency> deps = new ArrayList<Dependency>();
      +  387  46
               if (files != null) {
      +  388  93
                   for (File f : files) {
      +  389  47
                       if (f.isDirectory()) {
      +  390  43
                           final List<Dependency> d = scanDirectory(f, projectReference);
      +  391  43
                           if (d != null) {
      +  392  43
                               deps.addAll(d);
      +  393   +
                           }
      +  394  43
                       } else {
      +  395  4
                           final Dependency d = scanFile(f, projectReference);
      +  396  4
                           deps.add(d);
       397   -
                           }
      -  398  102
                           if (shouldAnalyze) {
      -  399  38
                               LOGGER.debug("Begin Analysis of '{}'", d.getActualFilePath());
      -  400   -
                               try {
      -  401  38
                                   a.analyze(d, this);
      -  402  0
                               } catch (AnalysisException ex) {
      -  403  0
                                   LOGGER.warn("An error occurred while analyzing '{}'.", d.getActualFilePath());
      -  404  0
                                   LOGGER.debug("", ex);
      -  405  0
                                   exceptions.add(ex);
      -  406  0
                               } catch (Throwable ex) {
      -  407   -
                                   //final AnalysisException ax = new AnalysisException(axMsg, ex);
      -  408  0
                                   LOGGER.warn("An unexpected error occurred during analysis of '{}'", d.getActualFilePath());
      -  409  0
                                   LOGGER.debug("", ex);
      -  410  0
                                   exceptions.add(ex);
      -  411  38
                               }
      -  412   -
                           }
      -  413  102
                       }
      -  414  51
                   }
      -  415   -
               }
      -  416  22
               for (AnalysisPhase phase : AnalysisPhase.values()) {
      -  417  20
                   final List<Analyzer> analyzerList = analyzers.get(phase);
      -  418   -
       
      -  419  20
                   for (Analyzer a : analyzerList) {
      -  420  52
                       closeAnalyzer(a);
      -  421  52
                   }
      -  422   -
               }
      -  423   -
       
      -  424  2
               LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------");
      -  425  2
               LOGGER.info("Analysis Complete ({} ms)", System.currentTimeMillis() - analysisStart);
      -  426  2
               if (exceptions.size() > 0) {
      -  427  1
                   throw new ExceptionCollection("One or more exceptions occured during dependency-check analysis", exceptions);
      -  428   -
               }
      -  429  1
           }
      -  430   -
       
      -  431   -
           /**
      -  432   -
            * Initializes the given analyzer.
      -  433   -
            *
      -  434   -
            * @param analyzer the analyzer to initialize
      -  435   -
            * @return the initialized analyzer
      -  436   -
            * @throws InitializationException thrown when there is a problem
      -  437   -
            * initializing the analyzer
      -  438   -
            */
      -  439   -
           protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException {
      -  440   -
               try {
      -  441  52
                   LOGGER.debug("Initializing {}", analyzer.getName());
      -  442  52
                   analyzer.initialize();
      -  443  1
               } catch (InitializationException ex) {
      -  444  1
                   LOGGER.error("Exception occurred initializing {}.", analyzer.getName());
      -  445  1
                   LOGGER.debug("", ex);
      -  446   -
                   try {
      -  447  1
                       analyzer.close();
      -  448  0
                   } catch (Throwable ex1) {
      -  449  0
                       LOGGER.trace("", ex1);
      -  450  1
                   }
      -  451  1
                   throw ex;
      -  452  0
               } catch (Throwable ex) {
      -  453  0
                   LOGGER.error("Unexpected exception occurred initializing {}.", analyzer.getName());
      -  454  0
                   LOGGER.debug("", ex);
      -  455   -
                   try {
      -  456  0
                       analyzer.close();
      -  457  0
                   } catch (Throwable ex1) {
      -  458  0
                       LOGGER.trace("", ex1);
      -  459  0
                   }
      -  460  0
                   throw new InitializationException("Unexpected Exception", ex);
      -  461  51
               }
      -  462  51
               return analyzer;
      -  463   -
           }
      -  464   -
       
      -  465   -
           /**
      -  466   -
            * Closes the given analyzer.
      -  467   -
            *
      -  468   -
            * @param analyzer the analyzer to close
      -  469   -
            */
      -  470   -
           protected void closeAnalyzer(Analyzer analyzer) {
      -  471  52
               LOGGER.debug("Closing Analyzer '{}'", analyzer.getName());
      -  472   -
               try {
      -  473  52
                   analyzer.close();
      -  474  0
               } catch (Throwable ex) {
      -  475  0
                   LOGGER.trace("", ex);
      -  476  52
               }
      -  477  52
           }
      -  478   -
       
      -  479   -
           /**
      -  480   -
            * Cycles through the cached web data sources and calls update on all of
      -  481   -
            * them.
      -  482   -
            *
      -  483   -
            * @throws UpdateException thrown if the operation fails
      -  484   -
            */
      -  485   -
           public void doUpdates() throws UpdateException {
      -  486  0
               LOGGER.info("Checking for updates");
      -  487  0
               final long updateStart = System.currentTimeMillis();
      -  488  0
               final UpdateService service = new UpdateService(serviceClassLoader);
      -  489  0
               final Iterator<CachedWebDataSource> iterator = service.getDataSources();
      -  490  0
               while (iterator.hasNext()) {
      -  491  0
                   final CachedWebDataSource source = iterator.next();
      -  492  0
                   source.update();
      -  493  0
               }
      -  494  0
               LOGGER.info("Check for updates complete ({} ms)", System.currentTimeMillis() - updateStart);
      -  495  0
           }
      -  496   -
       
      -  497   -
           /**
      -  498   -
            * Returns a full list of all of the analyzers. This is useful for reporting
      -  499   -
            * which analyzers where used.
      -  500   -
            *
      -  501   -
            * @return a list of Analyzers
      -  502   -
            */
      -  503   -
           public List<Analyzer> getAnalyzers() {
      -  504  0
               final List<Analyzer> ret = new ArrayList<Analyzer>();
      -  505  0
               for (AnalysisPhase phase : AnalysisPhase.values()) {
      -  506  0
                   final List<Analyzer> analyzerList = analyzers.get(phase);
      -  507  0
                   ret.addAll(analyzerList);
      -  508   -
               }
      -  509  0
               return ret;
      -  510   -
           }
      -  511   -
       
      -  512   -
           /**
      -  513   -
            * Checks all analyzers to see if an extension is supported.
      -  514   -
            *
      -  515   -
            * @param file a file extension
      -  516   -
            * @return true or false depending on whether or not the file extension is
      -  517   -
            * supported
      -  518   -
            */
      -  519   -
           @Override
      -  520   -
           public boolean accept(File file) {
      -  521  855
               if (file == null) {
      -  522  0
                   return false;
      -  523   -
               }
      -  524  855
               boolean scan = false;
      -  525  855
               for (FileTypeAnalyzer a : this.fileTypeAnalyzers) {
      -  526   -
                   /* note, we can't break early on this loop as the analyzers need to know if
      -  527   -
                    they have files to work on prior to initialization */
      -  528  15390
                   scan |= a.accept(file);
      -  529  15390
               }
      -  530  855
               return scan;
      -  531   -
           }
      -  532   -
       
      -  533   -
           /**
      -  534   -
            * Returns the set of file type analyzers.
      -  535   -
            *
      -  536   -
            * @return the set of file type analyzers
      -  537   -
            */
      -  538   -
           public Set<FileTypeAnalyzer> getFileTypeAnalyzers() {
      -  539  0
               return this.fileTypeAnalyzers;
      -  540   -
           }
      -  541   -
       
      -  542   -
           /**
      -  543   -
            * Checks the CPE Index to ensure documents exists. If none exist a
      -  544   -
            * NoDataException is thrown.
      -  545   -
            *
      -  546   -
            * @throws NoDataException thrown if no data exists in the CPE Index
      -  547   -
            * @throws DatabaseException thrown if there is an exception opening the
      -  548   -
            * database
      -  549   -
            */
      -  550   -
           private void ensureDataExists() throws NoDataException, DatabaseException {
      -  551  2
               final CveDB cve = new CveDB();
      -  552   -
               try {
      -  553  2
                   cve.open();
      -  554  2
                   if (!cve.dataExists()) {
      -  555  0
                       throw new NoDataException("No documents exist");
      -  556   +
                       }
      +  398  
                   }
      -  557  0
               } catch (DatabaseException ex) {
      -  558  0
                   throw new NoDataException(ex.getMessage(), ex);
      +  399   +
               }
      +  400  46
               return deps;
      +  401   +
           }
      +  402   +
       
      +  403   +
           /**
      +  404   +
            * Scans a specified file. If a dependency is identified it is added to the
      +  405   +
            * dependency collection.
      +  406   +
            *
      +  407   +
            * @param file The file to scan
      +  408   +
            * @return the scanned dependency
      +  409   +
            */
      +  410   +
           protected Dependency scanFile(File file) {
      +  411  3
               return scanFile(file, null);
      +  412   +
           }
      +  413   +
       
      +  414   +
           /**
      +  415   +
            * Scans a specified file. If a dependency is identified it is added to the
      +  416   +
            * dependency collection.
      +  417   +
            *
      +  418   +
            * @param file The file to scan
      +  419   +
            * @param projectReference the name of the project or scope in which the
      +  420   +
            * dependency was identified
      +  421   +
            * @return the scanned dependency
      +  422   +
            * @since v1.4.4
      +  423   +
            */
      +  424   +
           protected Dependency scanFile(File file, String projectReference) {
      +  425  9
               Dependency dependency = null;
      +  426  9
               if (file.isFile()) {
      +  427  9
                   if (accept(file)) {
      +  428  7
                       dependency = new Dependency(file);
      +  429  7
                       if (projectReference != null) {
      +  430  0
                           dependency.addProjectReference(projectReference);
      +  431   +
                       }
      +  432  7
                       final String sha1 = dependency.getSha1sum();
      +  433  7
                       boolean found = false;
      +  434  7
                       synchronized (dependencies) {
      +  435  7
                           if (sha1 != null) {
      +  436  7
                               for (Dependency existing : dependencies) {
      +  437  4
                                   if (sha1.equals(existing.getSha1sum())) {
      +  438  1
                                       found = true;
      +  439  1
                                       if (projectReference != null) {
      +  440  0
                                           existing.addProjectReference(projectReference);
      +  441   +
                                       }
      +  442  1
                                       if (existing.getActualFilePath() != null && dependency.getActualFilePath() != null
      +  443  1
                                               && !existing.getActualFilePath().equals(dependency.getActualFilePath())) {
      +  444  0
                                           existing.addRelatedDependency(dependency);
      +  445   +
                                       } else {
      +  446  1
                                           dependency = existing;
      +  447   +
                                       }
      +  448  1
                                       break;
      +  449   +
                                   }
      +  450  3
                               }
      +  451   +
                           }
      +  452  7
                           if (!found) {
      +  453  6
                               dependencies.add(dependency);
      +  454   +
                           }
      +  455  7
                       }
      +  456  7
                   } else {
      +  457  2
                       LOGGER.debug("Path passed to scanFile(File) is not a file: {}. Skipping the file.", file);
      +  458   +
                   }
      +  459   +
               }
      +  460  9
               return dependency;
      +  461   +
           }
      +  462   +
       
      +  463   +
           /**
      +  464   +
            * Runs the analyzers against all of the dependencies. Since the mutable
      +  465   +
            * dependencies list is exposed via {@link #getDependencies()}, this method
      +  466   +
            * iterates over a copy of the dependencies list. Thus, the potential for
      +  467   +
            * {@link java.util.ConcurrentModificationException}s is avoided, and
      +  468   +
            * analyzers may safely add or remove entries from the dependencies list.
      +  469   +
            * <p>
      +  470   +
            * Every effort is made to complete analysis on the dependencies. In some
      +  471   +
            * cases an exception will occur with part of the analysis being performed
      +  472   +
            * which may not affect the entire analysis. If an exception occurs it will
      +  473   +
            * be included in the thrown exception collection.
      +  474   +
            *
      +  475   +
            * @throws ExceptionCollection a collections of any exceptions that occurred
      +  476   +
            * during analysis
      +  477   +
            */
      +  478   +
           public void analyzeDependencies() throws ExceptionCollection {
      +  479  2
               final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>());
      +  480  2
               boolean autoUpdate = true;
      +  481   +
               try {
      +  482  2
                   autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
      +  483  0
               } catch (InvalidSettingException ex) {
      +  484  0
                   LOGGER.debug("Invalid setting for auto-update; using true.");
      +  485  0
                   exceptions.add(ex);
      +  486  2
               }
      +  487  2
               if (autoUpdate) {
      +  488   +
                   try {
      +  489  0
                       doUpdates();
      +  490  0
                   } catch (UpdateException ex) {
      +  491  0
                       exceptions.add(ex);
      +  492  0
                       LOGGER.warn("Unable to update Cached Web DataSource, using local "
      +  493   +
                               + "data instead. Results may not include recent vulnerabilities.");
      +  494  0
                       LOGGER.debug("Update Error", ex);
      +  495  0
                   }
      +  496   +
               }
      +  497   +
       
      +  498   +
               //need to ensure that data exists
      +  499   +
               try {
      +  500  2
                   ensureDataExists();
      +  501  0
               } catch (NoDataException ex) {
      +  502  0
                   throwFatalExceptionCollection("Unable to continue dependency-check analysis.", ex, exceptions);
      +  503  0
               } catch (DatabaseException ex) {
      +  504  0
                   throwFatalExceptionCollection("Unable to connect to the dependency-check database.", ex, exceptions);
      +  505  2
               }
      +  506   +
       
      +  507  2
               LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
      +  508  2
               LOGGER.info("Analysis Started");
      +  509  2
               final long analysisStart = System.currentTimeMillis();
      +  510   +
       
      +  511   +
               // analysis phases
      +  512  22
               for (AnalysisPhase phase : AnalysisPhase.values()) {
      +  513  20
                   final List<Analyzer> analyzerList = analyzers.get(phase);
      +  514   +
       
      +  515  20
                   for (final Analyzer analyzer : analyzerList) {
      +  516  52
                       final long analyzerStart = System.currentTimeMillis();
      +  517   +
                       try {
      +  518  52
                           initializeAnalyzer(analyzer);
      +  519  1
                       } catch (InitializationException ex) {
      +  520  1
                           exceptions.add(ex);
      +  521  1
                           continue;
      +  522  51
                       }
      +  523   +
       
      +  524  51
                       executeAnalysisTasks(analyzer, exceptions);
      +  525   +
       
      +  526  51
                       final long analyzerDurationMillis = System.currentTimeMillis() - analyzerStart;
      +  527  51
                       final long analyzerDurationSeconds = TimeUnit.MILLISECONDS.toSeconds(analyzerDurationMillis);
      +  528  51
                       LOGGER.info("Finished {} ({} seconds)", analyzer.getName(), analyzerDurationSeconds);
      +  529  51
                   }
      +  530   +
               }
      +  531  22
               for (AnalysisPhase phase : AnalysisPhase.values()) {
      +  532  20
                   final List<Analyzer> analyzerList = analyzers.get(phase);
      +  533   +
       
      +  534  20
                   for (Analyzer a : analyzerList) {
      +  535  52
                       closeAnalyzer(a);
      +  536  52
                   }
      +  537   +
               }
      +  538   +
       
      +  539  2
               LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------");
      +  540  2
               final long analysisDurationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - analysisStart);
      +  541  2
               LOGGER.info("Analysis Complete ({} seconds)", analysisDurationSeconds);
      +  542  2
               if (exceptions.size() > 0) {
      +  543  1
                   throw new ExceptionCollection("One or more exceptions occurred during dependency-check analysis", exceptions);
      +  544   +
               }
      +  545  1
           }
      +  546   +
       
      +  547   +
           /**
      +  548   +
            * Executes executes the analyzer using multiple threads.
      +  549   +
            *
      +  550   +
            * @param exceptions a collection of exceptions that occurred during
      +  551   +
            * analysis
      +  552   +
            * @param analyzer the analyzer to execute
      +  553   +
            * @throws ExceptionCollection thrown if exceptions occurred during analysis
      +  554   +
            */
      +  555   +
           void executeAnalysisTasks(Analyzer analyzer, List<Throwable> exceptions) throws ExceptionCollection {
      +  556  52
               LOGGER.debug("Starting {}", analyzer.getName());
      +  557  52
               final List<AnalysisTask> analysisTasks = getAnalysisTasks(analyzer, exceptions);
      +  558  52
               final ExecutorService executorService = getExecutorService(analyzer);
       559   -
               } finally {
      -  560  2
                   cve.close();
      -  561  2
               }
      -  562  2
           }
      +
       
      +  560   +
               try {
      +  561  52
                   final List<Future<Void>> results = executorService.invokeAll(analysisTasks, 10, TimeUnit.MINUTES);
      +  562   +
       
       563   +
                   // ensure there was no exception during execution
      +  564  52
                   for (Future<Void> result : results) {
      +  565   +
                       try {
      +  566  103
                           result.get();
      +  567  1
                       } catch (ExecutionException e) {
      +  568  1
                           throwFatalExceptionCollection("Analysis task failed with a fatal exception.", e, exceptions);
      +  569  0
                       } catch (CancellationException e) {
      +  570  0
                           throwFatalExceptionCollection("Analysis task timed out.", e, exceptions);
      +  571  102
                       }
      +  572  102
                   }
      +  573  0
               } catch (InterruptedException e) {
      +  574  0
                   throwFatalExceptionCollection("Analysis has been interrupted.", e, exceptions);
      +  575   +
               } finally {
      +  576  52
                   executorService.shutdown();
      +  577  51
               }
      +  578  51
           }
      +  579   +
       
      +  580   +
           /**
      +  581   +
            * Returns the analysis tasks for the dependencies.
      +  582   +
            *
      +  583   +
            * @param analyzer the analyzer to create tasks for
      +  584   +
            * @param exceptions the collection of exceptions to collect
      +  585   +
            * @return a collection of analysis tasks
      +  586   +
            */
      +  587   +
           List<AnalysisTask> getAnalysisTasks(Analyzer analyzer, List<Throwable> exceptions) {
      +  588  51
               final List<AnalysisTask> result = new ArrayList<AnalysisTask>();
      +  589  51
               synchronized (dependencies) {
      +  590  51
                   for (final Dependency dependency : dependencies) {
      +  591  102
                       final AnalysisTask task = new AnalysisTask(analyzer, dependency, this, exceptions);
      +  592  102
                       result.add(task);
      +  593  102
                   }
      +  594  51
               }
      +  595  51
               return result;
      +  596   +
           }
      +  597   +
       
      +  598   +
           /**
      +  599   +
            * Returns the executor service for a given analyzer.
      +  600   +
            *
      +  601   +
            * @param analyzer the analyzer to obtain an executor
      +  602   +
            * @return the executor service
      +  603   +
            */
      +  604   +
           ExecutorService getExecutorService(Analyzer analyzer) {
      +  605  51
               if (analyzer.supportsParallelProcessing()) {
      +  606   +
                   // just a fair trade-off that should be reasonable for all analyzer types
      +  607  47
                   final int maximumNumberOfThreads = 4 * Runtime.getRuntime().availableProcessors();
      +  608   +
       
      +  609  47
                   LOGGER.debug("Parallel processing with up to {} threads: {}.", maximumNumberOfThreads, analyzer.getName());
      +  610  47
                   return Executors.newFixedThreadPool(maximumNumberOfThreads);
      +  611   +
               } else {
      +  612  4
                   LOGGER.debug("Parallel processing is not supported: {}.", analyzer.getName());
      +  613  4
                   return Executors.newSingleThreadExecutor();
      +  614   +
               }
      +  615   +
           }
      +  616   +
       
      +  617   +
           /**
      +  618   +
            * Initializes the given analyzer.
      +  619   +
            *
      +  620   +
            * @param analyzer the analyzer to initialize
      +  621   +
            * @return the initialized analyzer
      +  622   +
            * @throws InitializationException thrown when there is a problem
      +  623   +
            * initializing the analyzer
      +  624   +
            */
      +  625   +
           protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException {
      +  626   +
               try {
      +  627  52
                   LOGGER.debug("Initializing {}", analyzer.getName());
      +  628  52
                   analyzer.initialize();
      +  629  1
               } catch (InitializationException ex) {
      +  630  1
                   LOGGER.error("Exception occurred initializing {}.", analyzer.getName());
      +  631  1
                   LOGGER.debug("", ex);
      +  632   +
                   try {
      +  633  1
                       analyzer.close();
      +  634  0
                   } catch (Throwable ex1) {
      +  635  0
                       LOGGER.trace("", ex1);
      +  636  1
                   }
      +  637  1
                   throw ex;
      +  638  0
               } catch (Throwable ex) {
      +  639  0
                   LOGGER.error("Unexpected exception occurred initializing {}.", analyzer.getName());
      +  640  0
                   LOGGER.debug("", ex);
      +  641   +
                   try {
      +  642  0
                       analyzer.close();
      +  643  0
                   } catch (Throwable ex1) {
      +  644  0
                       LOGGER.trace("", ex1);
      +  645  0
                   }
      +  646  0
                   throw new InitializationException("Unexpected Exception", ex);
      +  647  51
               }
      +  648  51
               return analyzer;
      +  649   +
           }
      +  650   +
       
      +  651   +
           /**
      +  652   +
            * Closes the given analyzer.
      +  653   +
            *
      +  654   +
            * @param analyzer the analyzer to close
      +  655   +
            */
      +  656   +
           protected void closeAnalyzer(Analyzer analyzer) {
      +  657  52
               LOGGER.debug("Closing Analyzer '{}'", analyzer.getName());
      +  658   +
               try {
      +  659  52
                   analyzer.close();
      +  660  0
               } catch (Throwable ex) {
      +  661  0
                   LOGGER.trace("", ex);
      +  662  52
               }
      +  663  52
           }
      +  664   +
       
      +  665   +
           /**
      +  666   +
            * Cycles through the cached web data sources and calls update on all of
      +  667   +
            * them.
      +  668   +
            *
      +  669   +
            * @throws UpdateException thrown if the operation fails
      +  670   +
            */
      +  671   +
           public void doUpdates() throws UpdateException {
      +  672  0
               LOGGER.info("Checking for updates");
      +  673  0
               final long updateStart = System.currentTimeMillis();
      +  674  0
               final UpdateService service = new UpdateService(serviceClassLoader);
      +  675  0
               final Iterator<CachedWebDataSource> iterator = service.getDataSources();
      +  676  0
               while (iterator.hasNext()) {
      +  677  0
                   final CachedWebDataSource source = iterator.next();
      +  678  0
                   source.update();
      +  679  0
               }
      +  680  0
               LOGGER.info("Check for updates complete ({} ms)", System.currentTimeMillis() - updateStart);
      +  681  0
           }
      +  682   +
       
      +  683   +
           /**
      +  684   +
            * Returns a full list of all of the analyzers. This is useful for reporting
      +  685   +
            * which analyzers where used.
      +  686   +
            *
      +  687   +
            * @return a list of Analyzers
      +  688   +
            */
      +  689   +
           public List<Analyzer> getAnalyzers() {
      +  690  0
               final List<Analyzer> ret = new ArrayList<Analyzer>();
      +  691  0
               for (AnalysisPhase phase : AnalysisPhase.values()) {
      +  692  0
                   final List<Analyzer> analyzerList = analyzers.get(phase);
      +  693  0
                   ret.addAll(analyzerList);
      +  694   +
               }
      +  695  0
               return ret;
      +  696   +
           }
      +  697   +
       
      +  698   +
           /**
      +  699   +
            * Checks all analyzers to see if an extension is supported.
      +  700   +
            *
      +  701   +
            * @param file a file extension
      +  702   +
            * @return true or false depending on whether or not the file extension is
      +  703   +
            * supported
      +  704   +
            */
      +  705   +
           @Override
      +  706   +
           public boolean accept(File file) {
      +  707  858
               if (file == null) {
      +  708  0
                   return false;
      +  709   +
               }
      +  710  858
               boolean scan = false;
      +  711  858
               for (FileTypeAnalyzer a : this.fileTypeAnalyzers) {
      +  712   +
                   /* note, we can't break early on this loop as the analyzers need to know if
      +  713   +
                    they have files to work on prior to initialization */
      +  714  15447
                   scan |= a.accept(file);
      +  715  15447
               }
      +  716  858
               return scan;
      +  717   +
           }
      +  718   +
       
      +  719   +
           /**
      +  720   +
            * Returns the set of file type analyzers.
      +  721   +
            *
      +  722   +
            * @return the set of file type analyzers
      +  723   +
            */
      +  724   +
           public Set<FileTypeAnalyzer> getFileTypeAnalyzers() {
      +  725  0
               return this.fileTypeAnalyzers;
      +  726   +
           }
      +  727   +
       
      +  728   +
           /**
      +  729   +
            * Adds a file type analyzer. This has been added solely to assist in unit
      +  730   +
            * testing the Engine.
      +  731   +
            *
      +  732   +
            * @param fta the file type analyzer to add
      +  733   +
            */
      +  734   +
           protected void addFileTypeAnalyzer(FileTypeAnalyzer fta) {
      +  735  1
               this.fileTypeAnalyzers.add(fta);
      +  736  1
           }
      +  737   +
       
      +  738   +
           /**
      +  739   +
            * Checks the CPE Index to ensure documents exists. If none exist a
      +  740   +
            * NoDataException is thrown.
      +  741   +
            *
      +  742   +
            * @throws NoDataException thrown if no data exists in the CPE Index
      +  743   +
            * @throws DatabaseException thrown if there is an exception opening the
      +  744   +
            * database
      +  745   +
            */
      +  746   +
           private void ensureDataExists() throws NoDataException, DatabaseException {
      +  747  2
               final CveDB cve = new CveDB();
      +  748   +
               try {
      +  749  2
                   cve.open();
      +  750  2
                   if (!cve.dataExists()) {
      +  751  0
                       throw new NoDataException("No documents exist");
      +  752   +
                   }
      +  753  0
               } catch (DatabaseException ex) {
      +  754  0
                   throw new NoDataException(ex.getMessage(), ex);
      +  755   +
               } finally {
      +  756  2
                   cve.close();
      +  757  2
               }
      +  758  2
           }
      +  759   +
       
      +  760   +
           /**
      +  761   +
            * Constructs and throws a fatal exception collection.
      +  762   +
            *
      +  763   +
            * @param message the exception message
      +  764   +
            * @param throwable the cause
      +  765   +
            * @param exceptions a collection of exception to include
      +  766   +
            * @throws ExceptionCollection a collection of exceptions that occurred
      +  767   +
            * during analysis
      +  768   +
            */
      +  769   +
           private void throwFatalExceptionCollection(String message, Throwable throwable, List<Throwable> exceptions) throws ExceptionCollection {
      +  770  1
               LOGGER.error("{}\n\n{}", throwable.getMessage(), message);
      +  771  1
               LOGGER.debug("", throwable);
      +  772  1
               exceptions.add(throwable);
      +  773  1
               throw new ExceptionCollection(message, exceptions, true);
      +  774   +
           }
      +  775  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.agent.DependencyCheckScanAgent.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.agent.DependencyCheckScanAgent.html index 4c1abe879..f8725f5f2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.agent.DependencyCheckScanAgent.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.agent.DependencyCheckScanAgent.html @@ -1884,6 +1884,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractAnalyzer.html index e4d63a2a7..93eb5e48b 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      AbstractAnalyzer
      100%
      3/3
      N/A
      1
      AbstractAnalyzer
      100%
      4/4
      N/A
      1
       
      @@ -71,7 +71,7 @@
        * @author Jeremy Long
       27  
        */
      -  28  231
       public abstract class AbstractAnalyzer implements Analyzer {
      +  28  302
       public abstract class AbstractAnalyzer implements Analyzer {
       29  
       
       30   @@ -109,11 +109,26 @@
           public void close() throws Exception {
       47  
               //do nothing
      -  48  97
           }
      +  48  99
           }
       49   +
       
      +  50   +
           /**
      +  51   +
            * The default is to support parallel processing.
      +  52   +
            */
      +  53   +
           @Override
      +  54   +
           public boolean supportsParallelProcessing() {
      +  55  47
               return true;
      +  56   +
           }
      +  57  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractFileTypeAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractFileTypeAnalyzer.html index 503e01e9d..6adc7c0ad 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractFileTypeAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractFileTypeAnalyzer.html @@ -111,9 +111,9 @@
            * configuration to determine if the analyzer is enabled.
       47  
            */
      -  48  176
           public AbstractFileTypeAnalyzer() {
      -  49  176
               reset();
      -  50  176
           }
      +  48  217
           public AbstractFileTypeAnalyzer() {
      +  49  217
               reset();
      +  50  217
           }
       51  
       //</editor-fold>
       52   @@ -133,7 +133,7 @@
            * Whether the file type analyzer detected any files it needs to analyze.
       60  
            */
      -  61  176
           private boolean filesMatched = false;
      +  61  217
           private boolean filesMatched = false;
       62  
       
       63   @@ -169,8 +169,8 @@
            */
       79  
           protected void setFilesMatched(boolean filesMatched) {
      -  80  56
               this.filesMatched = filesMatched;
      -  81  56
           }
      +  80  60
               this.filesMatched = filesMatched;
      +  81  60
           }
       82  
       
       83   @@ -179,7 +179,7 @@
            * A flag indicating whether or not the analyzer is enabled.
       85  
            */
      -  86  176
           private boolean enabled = true;
      +  86  217
           private volatile boolean enabled = true;
       87  
       
       88   @@ -194,7 +194,7 @@
            */
       93  
           public boolean isEnabled() {
      -  94  1
               return enabled;
      +  94  3
               return enabled;
       95  
           }
       96   @@ -211,8 +211,8 @@
            */
       102  
           public void setEnabled(boolean enabled) {
      -  103  8
               this.enabled = enabled;
      -  104  8
           }
      +  103  10
               this.enabled = enabled;
      +  104  10
           }
       105  
       //</editor-fold>
       106   @@ -321,14 +321,14 @@
           @Override
       158  
           public final void initialize() throws InitializationException {
      -  159  98
               if (filesMatched) {
      -  160  63
                   initializeFileTypeAnalyzer();
      +  159  102
               if (filesMatched) {
      +  160  67
                   initializeFileTypeAnalyzer();
       161  
               } else {
       162  35
                   enabled = false;
       163  
               }
      -  164  94
           }
      +  164  96
           }
       165  
       
       166   @@ -341,16 +341,16 @@
           @Override
       170  
           public final void reset() {
      -  171  176
               final String key = getAnalyzerEnabledSettingKey();
      +  171  217
               final String key = getAnalyzerEnabledSettingKey();
       172  
               try {
      -  173  176
                   enabled = Settings.getBoolean(key, true);
      +  173  217
                   enabled = Settings.getBoolean(key, true);
       174  0
               } catch (InvalidSettingException ex) {
       175  0
                   LOGGER.warn("Invalid setting for property '{}'", key);
       176  0
                   LOGGER.debug("", ex);
       177  0
                   LOGGER.warn("{} has been disabled", getName());
      -  178  176
               }
      -  179  176
           }
      +  178  217
               }
      +  179  217
           }
       180  
       
       181   @@ -386,19 +386,19 @@
           @Override
       198  
           public boolean accept(File pathname) {
      -  199  15489
               final FileFilter filter = getFileFilter();
      -  200  15489
               boolean accepted = false;
      -  201  15489
               if (null == filter) {
      +  199  15543
               final FileFilter filter = getFileFilter();
      +  200  15543
               boolean accepted = false;
      +  201  15544
               if (null == filter) {
       202  0
                   LOGGER.error("The '{}' analyzer is misconfigured and does not have a file filter; it will be disabled", getName());
      -  203  15489
               } else if (enabled) {
      -  204  13717
                   accepted = filter.accept(pathname);
      -  205  13717
                   if (accepted) {
      -  206  41
                       filesMatched = true;
      +  203  15544
               } else if (enabled) {
      +  204  13771
                   accepted = filter.accept(pathname);
      +  205  13771
                   if (accepted) {
      +  206  53
                       filesMatched = true;
       207  
                   }
       208  
               }
      -  209  15489
               return accepted;
      +  209  15545
               return accepted;
       210  
           }
       211   @@ -444,6 +444,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractSuppressionAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractSuppressionAnalyzer.html index 2a9fd7946..7d7cf96f1 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractSuppressionAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AbstractSuppressionAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      AbstractSuppressionAnalyzer
      79%
      54/68
      75%
      12/16
      4.667
      AbstractSuppressionAnalyzer
      68%
      51/74
      77%
      14/18
      5.333
       
      @@ -107,7 +107,7 @@
        * @author Jeremy Long
       45  
        */
      -  46  16
       public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
      +  46  20
       public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
       47  
       
       48   @@ -282,61 +282,69 @@  156  
                   }
       157  3
                   if (file != null) {
      -  158   +  158  3
                       if (!file.exists()) {
      +  159  1
                           final String msg = String.format("Suppression file '%s' does not exists", file.getPath());
      +  160  1
                           LOGGER.warn(msg);
      +  161  1
                           throw new SuppressionParseException(msg);
      +  162   +
                       }
      +  163  
                       try {
      -  159  3
                           rules.addAll(parser.parseSuppressionRules(file));
      -  160  2
                           LOGGER.debug("{} suppression rules were loaded.", rules.size());
      -  161  1
                       } catch (SuppressionParseException ex) {
      -  162  1
                           LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath());
      -  163  1
                           LOGGER.warn(ex.getMessage());
      -  164  1
                           throw ex;
      -  165  2
                       }
      -  166   +  164  2
                           rules.addAll(parser.parseSuppressionRules(file));
      +  165  2
                           LOGGER.debug("{} suppression rules were loaded.", rules.size());
      +  166  0
                       } catch (SuppressionParseException ex) {
      +  167  0
                           LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath());
      +  168  0
                           LOGGER.warn(ex.getMessage());
      +  169  0
                           throw ex;
      +  170  2
                       }
      +  171  
                   }
      -  167  0
               } catch (DownloadFailedException ex) {
      -  168  0
                   throwSuppressionParseException("Unable to fetch the configured suppression file", ex);
      -  169  0
               } catch (MalformedURLException ex) {
      -  170  0
                   throwSuppressionParseException("Configured suppression file has an invalid URL", ex);
      -  171  1
               } catch (IOException ex) {
      -  172  1
                   throwSuppressionParseException("Unable to create temp file for suppressions", ex);
      -  173   -
               } finally {
      -  174  3
                   if (deleteTempFile && file != null) {
      -  175  2
                       FileUtils.delete(file);
      -  176   -
                   }
      -  177   -
               }
      -  178  2
           }
      -  179   -
       
      +  172  0
               } catch (DownloadFailedException ex) {
      +  173  0
                   throwSuppressionParseException("Unable to fetch the configured suppression file", ex);
      +  174  0
               } catch (MalformedURLException ex) {
      +  175  0
                   throwSuppressionParseException("Configured suppression file has an invalid URL", ex);
      +  176  1
               } catch (SuppressionParseException ex) {
      +  177  1
                   throw ex;
      +  178  0
               } catch (IOException ex) {
      +  179  0
                   throwSuppressionParseException("Unable to create temp file for suppressions", ex);
       180   -
           /**
      -  181   -
            * Utility method to throw parse exceptions.
      -  182   -
            *
      +
               } finally {
      +  181  3
                   if (deleteTempFile && file != null) {
      +  182  2
                       FileUtils.delete(file);
       183   -
            * @param message the exception message
      +
                   }
       184   -
            * @param exception the cause of the exception
      -  185   -
            * @throws SuppressionParseException throws the generated
      +
               }
      +  185  2
           }
       186   -
            * SuppressionParseException
      +
       
       187   -
            */
      +
           /**
       188   -
           private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException {
      -  189  1
               LOGGER.warn(message);
      -  190  1
               LOGGER.debug("", exception);
      -  191  1
               throw new SuppressionParseException(message, exception);
      +
            * Utility method to throw parse exceptions.
      +  189   +
            *
      +  190   +
            * @param message the exception message
      +  191   +
            * @param exception the cause of the exception
       192   -
           }
      +
            * @throws SuppressionParseException throws the generated
       193   +
            * SuppressionParseException
      +  194   +
            */
      +  195   +
           private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException {
      +  196  0
               LOGGER.warn(message);
      +  197  0
               LOGGER.debug("", exception);
      +  198  0
               throw new SuppressionParseException(message, exception);
      +  199   +
           }
      +  200  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalysisPhase.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalysisPhase.html index 901c52570..eb4e63c37 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalysisPhase.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalysisPhase.html @@ -65,7 +65,7 @@
        * @author Jeremy Long
       24  
        */
      -  25  20
       public enum AnalysisPhase {
      +  25  22
       public enum AnalysisPhase {
       26  
       
       27   @@ -142,6 +142,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Analyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Analyzer.html index 455e9bc2b..90f9cb571 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Analyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Analyzer.html @@ -172,9 +172,25 @@  77  
           void close() throws Exception;
       78   +
       
      +  79   +
           /**
      +  80   +
            * Returns whether multiple instances of the same type of analyzer can run in parallel.
      +  81   +
            * Note that running analyzers of different types in parallel is not supported at all.
      +  82   +
            *
      +  83   +
            * @return {@code true} if the analyzer supports parallel processing, {@code false} else
      +  84   +
            */
      +  85   +
           boolean supportsParallelProcessing();
      +  86  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalyzerService.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalyzerService.html index 7dce151fe..7c3f939a1 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalyzerService.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AnalyzerService.html @@ -114,9 +114,9 @@
            * @param classLoader the ClassLoader to use when dynamically loading Analyzer and Update services
       49  
            */
      -  50  6
           public AnalyzerService(ClassLoader classLoader) {
      -  51  6
               service = ServiceLoader.load(Analyzer.class, classLoader);
      -  52  6
           }
      +  50  8
           public AnalyzerService(ClassLoader classLoader) {
      +  51  8
               service = ServiceLoader.load(Analyzer.class, classLoader);
      +  52  8
           }
       53  
       
       54   @@ -131,31 +131,31 @@
            */
       59  
           public List<Analyzer> getAnalyzers() {
      -  60  7
               final List<Analyzer> analyzers = new ArrayList<Analyzer>();
      -  61  7
               final Iterator<Analyzer> iterator = service.iterator();
      -  62  7
               boolean experimentalEnabled = false;
      +  60  9
               final List<Analyzer> analyzers = new ArrayList<Analyzer>();
      +  61  9
               final Iterator<Analyzer> iterator = service.iterator();
      +  62  9
               boolean experimentalEnabled = false;
       63  
               try {
      -  64  7
                   experimentalEnabled = Settings.getBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, false);
      +  64  9
                   experimentalEnabled = Settings.getBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, false);
       65  0
               } catch (InvalidSettingException ex) {
       66  0
                   LOGGER.error("invalide experimental setting", ex);
      -  67  7
               }
      -  68  189
               while (iterator.hasNext()) {
      -  69  182
                   final Analyzer a = iterator.next();
      -  70  182
                   if (!experimentalEnabled && a.getClass().isAnnotationPresent(Experimental.class)) {
      +  67  9
               }
      +  68  243
               while (iterator.hasNext()) {
      +  69  234
                   final Analyzer a = iterator.next();
      +  70  234
                   if (!experimentalEnabled && a.getClass().isAnnotationPresent(Experimental.class)) {
       71  11
                       continue;
       72  
                   }
      -  73  171
                   LOGGER.debug("Loaded Analyzer {}", a.getName());
      -  74  171
                   analyzers.add(a);
      -  75  171
               }
      -  76  7
               return analyzers;
      +  73  223
                   LOGGER.debug("Loaded Analyzer {}", a.getName());
      +  74  223
                   analyzers.add(a);
      +  75  223
               }
      +  76  9
               return analyzers;
       77  
           }
       78  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ArchiveAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ArchiveAnalyzer.html index 998fe22f8..fa18f2829 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ArchiveAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ArchiveAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      ArchiveAnalyzer
      37%
      86/230
      20%
      28/140
      6.588
      ArchiveAnalyzer
      34%
      91/261
      18%
      27/146
      6.5
       
      @@ -72,905 +72,958 @@  27  
       import java.io.IOException;
       28   -
       import java.util.ArrayList;
      -  29  
       import java.util.Collections;
      -  30   +  29  
       import java.util.Enumeration;
      -  31   -
       import java.util.HashSet;
      -  32   +  30  
       import java.util.List;
      -  33   +  31  
       import java.util.Set;
      -  34   +  32  
       
      -  35   +  33  
       import org.apache.commons.compress.archivers.ArchiveEntry;
      -  36   +  34  
       import org.apache.commons.compress.archivers.ArchiveInputStream;
      -  37   +  35  
       import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
      -  38   +  36  
       import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
      -  39   +  37  
       import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
      -  40   +  38  
       import org.apache.commons.compress.archivers.zip.ZipFile;
      -  41   +  39  
       import org.apache.commons.compress.compressors.CompressorInputStream;
      -  42   +  40  
       import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
      -  43   +  41  
       import org.apache.commons.compress.compressors.bzip2.BZip2Utils;
      -  44   +  42  
       import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
      -  45   +  43  
       import org.apache.commons.compress.compressors.gzip.GzipUtils;
      -  46   +  44  
       import org.apache.commons.compress.utils.IOUtils;
      -  47   +  45  
       
      -  48   +  46  
       import org.owasp.dependencycheck.Engine;
      -  49   +  47  
       import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
      -  50   +  48  
       import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException;
      -  51   +  49  
       import org.owasp.dependencycheck.dependency.Dependency;
      -  52   +  50  
       import org.owasp.dependencycheck.exception.InitializationException;
      -  53   +  51  
       import org.owasp.dependencycheck.utils.FileFilterBuilder;
      -  54   +  52  
       import org.owasp.dependencycheck.utils.FileUtils;
      -  55   +  53  
       import org.owasp.dependencycheck.utils.Settings;
      -  56   +  54  
       
      -  57   +  55  
       import org.slf4j.Logger;
      -  58   +  56  
       import org.slf4j.LoggerFactory;
      -  59   +  57  
       
      -  60   +  58  
       /**
      -  61   +  59  
        * <p>
      -  62   +  60  
        * An analyzer that extracts files from archives and ensures any supported files
      -  63   +  61  
        * contained within the archive are added to the dependency list.</p>
      -  64   +  62  
        *
      -  65   +  63  
        * @author Jeremy Long
      -  66   +  64  
        */
      -  67  6
       public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
      +  65  8
       public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
      +  66   +
       
      +  67   +
           /**
       68   -
       
      -  69   -
           /**
      -  70  
            * The logger.
      +  69   +
            */
      +  70  1
           private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveAnalyzer.class);
       71   -
            */
      -  72  1
           private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveAnalyzer.class);
      -  73  
           /**
      -  74   +  72  
            * The count of directories created during analysis. This is used for
      -  75   +  73  
            * creating temporary directories.
      +  74   +
            */
      +  75  1
           private static int dirCount = 0;
       76   -
            */
      -  77  1
           private static int dirCount = 0;
      -  78  
           /**
      -  79   +  77  
            * The parent directory for the individual directories per archive.
      +  78   +
            */
      +  79  8
           private File tempFileLocation = null;
       80   -
            */
      -  81  6
           private File tempFileLocation = null;
      -  82  
           /**
      -  83   +  81  
            * The max scan depth that the analyzer will recursively extract nested
      -  84   +  82  
            * archives.
      +  83   +
            */
      +  84  1
           private static final int MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3);
       85   -
            */
      -  86  1
           private static final int MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3);
      -  87  
           /**
      -  88   +  86  
            * Tracks the current scan/extraction depth for nested archives.
      +  87   +
            */
      +  88  8
           private int scanDepth = 0;
       89   -
            */
      -  90  6
           private int scanDepth = 0;
      -  91  
       
      -  92   +  90  
           //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
      -  93   +  91  
           /**
      -  94   +  92  
            * The name of the analyzer.
      -  95   +  93  
            */
      -  96   +  94  
           private static final String ANALYZER_NAME = "Archive Analyzer";
      -  97   +  95  
           /**
      -  98   +  96  
            * The phase that this analyzer is intended to run in.
      +  97   +
            */
      +  98  1
           private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL;
       99   -
            */
      -  100  1
           private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL;
      -  101  
           /**
      -  102   +  100  
            * The set of things we can handle with Zip methods
      +  101   +
            */
      +  102  1
           private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg");
       103   -
            */
      -  104  1
           private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg");
      -  105  
           /**
      -  106   +  104  
            * The set of file extensions supported by this analyzer. Note for
      -  107   +  105  
            * developers, any additions to this list will need to be explicitly handled
      -  108   +  106  
            * in {@link #extractFiles(File, File, Engine)}.
      +  107   +
            */
      +  108  1
           private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz", "bz2", "tbz2");
       109   -
            */
      -  110  1
           private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz", "bz2", "tbz2");
      +
       
      +  110   +
           /**
       111   -
       
      -  112   -
           /**
      -  113  
            * Detects files with extensions to remove from the engine's collection of
      -  114   +  112  
            * dependencies.
      -  115   +  113  
            */
      -  116  1
           private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance().addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2")
      -  117  1
                   .build();
      -  118   +  114  1
           private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance().addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2")
      +  115  1
                   .build();
      +  116  
       
      -  119   +  117  
           static {
      -  120  1
               final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
      -  121  1
               if (additionalZipExt != null) {
      -  122  0
                   final String[] ext = additionalZipExt.split("\\s*,\\s*");
      -  123  0
                   Collections.addAll(ZIPPABLES, ext);
      +  118  1
               final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
      +  119  1
               if (additionalZipExt != null) {
      +  120  0
                   final String[] ext = additionalZipExt.split("\\s*,\\s*");
      +  121  0
                   Collections.addAll(ZIPPABLES, ext);
      +  122   +
               }
      +  123  1
               EXTENSIONS.addAll(ZIPPABLES);
       124   -
               }
      -  125  1
               EXTENSIONS.addAll(ZIPPABLES);
      +
           }
      +  125   +
       
       126   -
           }
      +
           /**
       127   -
       
      -  128   -
           /**
      -  129  
            * The file filter used to filter supported files.
      +  128   +
            */
      +  129  1
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build();
       130   -
            */
      -  131  1
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build();
      +
       
      +  131   +
           @Override
       132   -
       
      -  133   -
           @Override
      -  134  
           protected FileFilter getFileFilter() {
      -  135  859
               return FILTER;
      +  133  862
               return FILTER;
      +  134   +
           }
      +  135   +
       
       136   -
           }
      +
           /**
       137   -
       
      -  138   -
           /**
      -  139  
            * Detects files with .zip extension.
      +  138   +
            */
      +  139  1
           private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build();
       140   -
            */
      -  141  1
           private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build();
      +
       
      +  141   +
           /**
       142   -
       
      -  143   -
           /**
      -  144  
            * Returns the name of the analyzer.
      -  145   +  143  
            *
      -  146   +  144  
            * @return the name of the analyzer.
      +  145   +
            */
      +  146   +
           @Override
       147   -
            */
      -  148   -
           @Override
      -  149  
           public String getName() {
      -  150  16
               return ANALYZER_NAME;
      +  148  24
               return ANALYZER_NAME;
      +  149   +
           }
      +  150   +
       
       151   -
           }
      +
           /**
       152   -
       
      -  153   -
           /**
      -  154  
            * Returns the phase that the analyzer is intended to run in.
      -  155   +  153  
            *
      -  156   +  154  
            * @return the phase that the analyzer is intended to run in.
      +  155   +
            */
      +  156   +
           @Override
       157   -
            */
      -  158   -
           @Override
      -  159  
           public AnalysisPhase getAnalysisPhase() {
      -  160  4
               return ANALYSIS_PHASE;
      -  161   +  158  6
               return ANALYSIS_PHASE;
      +  159  
           }
      -  162   +  160  
           //</editor-fold>
      +  161   +
       
      +  162   +
           /**
       163   -
       
      -  164   -
           /**
      -  165  
            * Returns the key used in the properties file to reference the analyzer's
      -  166   +  164  
            * enabled property.
      -  167   +  165  
            *
      -  168   +  166  
            * @return the analyzer's enabled property setting key
      +  167   +
            */
      +  168   +
           @Override
       169   -
            */
      -  170   -
           @Override
      -  171  
           protected String getAnalyzerEnabledSettingKey() {
      -  172  6
               return Settings.KEYS.ANALYZER_ARCHIVE_ENABLED;
      +  170  8
               return Settings.KEYS.ANALYZER_ARCHIVE_ENABLED;
      +  171   +
           }
      +  172   +
       
       173   -
           }
      +
           /**
       174   -
       
      -  175   -
           /**
      -  176  
            * The initialize method does nothing for this Analyzer.
      -  177   +  175  
            *
      -  178   +  176  
            * @throws InitializationException is thrown if there is an exception
      -  179   +  177  
            * deleting or creating temporary files
      +  178   +
            */
      +  179   +
           @Override
       180   -
            */
      -  181   -
           @Override
      -  182  
           public void initializeFileTypeAnalyzer() throws InitializationException {
      -  183   +  181  
               try {
      -  184  1
                   final File baseDir = Settings.getTempDirectory();
      -  185  1
                   tempFileLocation = File.createTempFile("check", "tmp", baseDir);
      -  186  1
                   if (!tempFileLocation.delete()) {
      -  187  0
                       setEnabled(false);
      -  188  0
                       final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
      -  189  0
                       throw new InitializationException(msg);
      -  190   +  182  1
                   final File baseDir = Settings.getTempDirectory();
      +  183  1
                   tempFileLocation = File.createTempFile("check", "tmp", baseDir);
      +  184  1
                   if (!tempFileLocation.delete()) {
      +  185  0
                       setEnabled(false);
      +  186  0
                       final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
      +  187  0
                       throw new InitializationException(msg);
      +  188  
                   }
      -  191  1
                   if (!tempFileLocation.mkdirs()) {
      -  192  0
                       setEnabled(false);
      -  193  0
                       final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
      -  194  0
                       throw new InitializationException(msg);
      -  195   +  189  1
                   if (!tempFileLocation.mkdirs()) {
      +  190  0
                       setEnabled(false);
      +  191  0
                       final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
      +  192  0
                       throw new InitializationException(msg);
      +  193  
                   }
      -  196  0
               } catch (IOException ex) {
      -  197  0
                   setEnabled(false);
      -  198  0
                   throw new InitializationException("Unable to create a temporary file", ex);
      -  199  1
               }
      -  200  1
           }
      +  194  0
               } catch (IOException ex) {
      +  195  0
                   setEnabled(false);
      +  196  0
                   throw new InitializationException("Unable to create a temporary file", ex);
      +  197  1
               }
      +  198  1
           }
      +  199   +
       
      +  200   +
           /**
       201   -
       
      -  202   -
           /**
      -  203  
            * The close method deletes any temporary files and directories created
      -  204   +  202  
            * during analysis.
      -  205   +  203  
            *
      -  206   +  204  
            * @throws Exception thrown if there is an exception deleting temporary
      -  207   +  205  
            * files
      +  206   +
            */
      +  207   +
           @Override
       208   -
            */
      -  209   -
           @Override
      -  210  
           public void close() throws Exception {
      -  211  2
               if (tempFileLocation != null && tempFileLocation.exists()) {
      -  212  1
                   LOGGER.debug("Attempting to delete temporary files");
      -  213  1
                   final boolean success = FileUtils.delete(tempFileLocation);
      -  214  1
                   if (!success && tempFileLocation.exists()) {
      -  215  0
                       final String[] l = tempFileLocation.list();
      -  216  0
                       if (l != null && l.length > 0) {
      -  217  0
                           LOGGER.warn("Failed to delete some temporary files, see the log for more details");
      +  209  2
               if (tempFileLocation != null && tempFileLocation.exists()) {
      +  210  1
                   LOGGER.debug("Attempting to delete temporary files");
      +  211  1
                   final boolean success = FileUtils.delete(tempFileLocation);
      +  212  1
                   if (!success && tempFileLocation.exists()) {
      +  213  0
                       final String[] l = tempFileLocation.list();
      +  214  0
                       if (l != null && l.length > 0) {
      +  215  0
                           LOGGER.warn("Failed to delete some temporary files, see the log for more details");
      +  216   +
                       }
      +  217   +
                   }
       218   -
                       }
      -  219   -
                   }
      +
               }
      +  219  2
           }
       220   -
               }
      -  221  2
           }
      +
       
      +  221   +
           /**
       222   -
       
      +
            * Does not support parallel processing as it both modifies and iterates
       223   -
           /**
      +
            * over the engine's list of dependencies.
       224   -
            * Analyzes a given dependency. If the dependency is an archive, such as a
      +
            *
       225   -
            * WAR or EAR, the contents are extracted, scanned, and added to the list of
      +
            * @see #analyzeFileType(Dependency, Engine)
       226   -
            * dependencies within the engine.
      +
            * @see #findMoreDependencies(Engine, File)
       227   -
            *
      +
            */
       228   -
            * @param dependency the dependency to analyze
      -  229   -
            * @param engine the engine scanning
      -  230   -
            * @throws AnalysisException thrown if there is an analysis exception
      -  231   -
            */
      -  232  
           @Override
      +  229   +
           public boolean supportsParallelProcessing() {
      +  230  2
               return false;
      +  231   +
           }
      +  232   +
       
       233   -
           public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
      -  234  2
               final File f = new File(dependency.getActualFilePath());
      -  235  2
               final File tmpDir = getNextTempDirectory();
      -  236  2
               extractFiles(f, tmpDir, engine);
      +
           /**
      +  234   +
            * Analyzes a given dependency. If the dependency is an archive, such as a
      +  235   +
            * WAR or EAR, the contents are extracted, scanned, and added to the list of
      +  236   +
            * dependencies within the engine.
       237   -
       
      +
            *
       238   -
               //make a copy
      -  239  2
               final Set<Dependency> dependencySet = findMoreDependencies(engine, tmpDir);
      -  240  2
               if (!dependencySet.isEmpty()) {
      -  241  0
                   for (Dependency d : dependencySet) {
      +
            * @param dependency the dependency to analyze
      +  239   +
            * @param engine the engine scanning
      +  240   +
            * @throws AnalysisException thrown if there is an analysis exception
      +  241   +
            */
       242   -
                       //fix the dependency's display name and path
      -  243  0
                       final String displayPath = String.format("%s%s",
      -  244  0
                               dependency.getFilePath(),
      -  245  0
                               d.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
      -  246  0
                       final String displayName = String.format("%s: %s",
      -  247  0
                               dependency.getFileName(),
      -  248  0
                               d.getFileName());
      -  249  0
                       d.setFilePath(displayPath);
      -  250  0
                       d.setFileName(displayName);
      -  251   +
           @Override
      +  243   +
           public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
      +  244  2
               final File f = new File(dependency.getActualFilePath());
      +  245  2
               final File tmpDir = getNextTempDirectory();
      +  246  2
               extractFiles(f, tmpDir, engine);
      +  247  
       
      -  252   -
                       //TODO - can we get more evidence from the parent? EAR contains module name, etc.
      -  253   -
                       //analyze the dependency (i.e. extract files) if it is a supported type.
      -  254  0
                       if (this.accept(d.getActualFile()) && scanDepth < MAX_SCAN_DEPTH) {
      -  255  0
                           scanDepth += 1;
      -  256  0
                           analyze(d, engine);
      -  257  0
                           scanDepth -= 1;
      -  258   -
                       }
      -  259  0
                   }
      -  260   -
               }
      -  261  2
               if (REMOVE_FROM_ANALYSIS.accept(dependency.getActualFile())) {
      -  262  0
                   addDisguisedJarsToDependencies(dependency, engine);
      -  263  0
                   engine.getDependencies().remove(dependency);
      +  248   +
               //make a copy
      +  249  2
               final List<Dependency> dependencySet = findMoreDependencies(engine, tmpDir);
      +  250   +
       
      +  251  2
               if (!dependencySet.isEmpty()) {
      +  252  0
                   for (Dependency d : dependencySet) {
      +  253  0
                       if (d.getFilePath().startsWith(tmpDir.getAbsolutePath())) {
      +  254   +
                           //fix the dependency's display name and path
      +  255  0
                           final String displayPath = String.format("%s%s",
      +  256  0
                                   dependency.getFilePath(),
      +  257  0
                                   d.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
      +  258  0
                           final String displayName = String.format("%s: %s",
      +  259  0
                                   dependency.getFileName(),
      +  260  0
                                   d.getFileName());
      +  261  0
                           d.setFilePath(displayPath);
      +  262  0
                           d.setFileName(displayName);
      +  263  0
                           d.setProjectReferences(dependency.getProjectReferences());
       264   -
               }
      -  265  2
               Collections.sort(engine.getDependencies());
      -  266  2
           }
      -  267  
       
      -  268   -
           /**
      -  269   -
            * If a zip file was identified as a possible JAR, this method will add the
      -  270   -
            * zip to the list of dependencies.
      +  265   +
                           //TODO - can we get more evidence from the parent? EAR contains module name, etc.
      +  266   +
                           //analyze the dependency (i.e. extract files) if it is a supported type.
      +  267  0
                           if (this.accept(d.getActualFile()) && scanDepth < MAX_SCAN_DEPTH) {
      +  268  0
                               scanDepth += 1;
      +  269  0
                               analyze(d, engine);
      +  270  0
                               scanDepth -= 1;
       271   -
            *
      -  272   -
            * @param dependency the zip file
      -  273   -
            * @param engine the engine
      -  274   -
            * @throws AnalysisException thrown if there is an issue
      -  275   -
            */
      -  276   -
           private void addDisguisedJarsToDependencies(Dependency dependency, Engine engine) throws AnalysisException {
      -  277  0
               if (ZIP_FILTER.accept(dependency.getActualFile()) && isZipFileActuallyJarFile(dependency)) {
      -  278  0
                   final File tdir = getNextTempDirectory();
      -  279  0
                   final String fileName = dependency.getFileName();
      -  280   -
       
      -  281  0
                   LOGGER.info("The zip file '{}' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName);
      -  282   -
       
      -  283  0
                   final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar");
      -  284   -
                   try {
      -  285  0
                       org.apache.commons.io.FileUtils.copyFile(tdir, tmpLoc);
      -  286  0
                       final Set<Dependency> dependencySet = findMoreDependencies(engine, tmpLoc);
      -  287  0
                       if (!dependencySet.isEmpty()) {
      -  288  0
                           if (dependencySet.size() != 1) {
      -  289  0
                               LOGGER.info("Deep copy of ZIP to JAR file resulted in more than one dependency?");
      -  290  
                           }
      -  291  0
                           for (Dependency d : dependencySet) {
      -  292   -
                               //fix the dependency's display name and path
      -  293  0
                               d.setFilePath(dependency.getFilePath());
      -  294  0
                               d.setDisplayFileName(dependency.getFileName());
      -  295  0
                           }
      +  272  0
                       } else {
      +  273  0
                           for (Dependency sub : dependencySet) {
      +  274  0
                               if (sub.getFilePath().startsWith(tmpDir.getAbsolutePath())) {
      +  275  0
                                   final String displayPath = String.format("%s%s",
      +  276  0
                                           dependency.getFilePath(),
      +  277  0
                                           sub.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
      +  278  0
                                   final String displayName = String.format("%s: %s",
      +  279  0
                                           dependency.getFileName(),
      +  280  0
                                           sub.getFileName());
      +  281  0
                                   sub.setFilePath(displayPath);
      +  282  0
                                   sub.setFileName(displayName);
      +  283   +
                               }
      +  284  0
                           }
      +  285   +
                       }
      +  286  0
                   }
      +  287   +
               }
      +  288  2
               if (REMOVE_FROM_ANALYSIS.accept(dependency.getActualFile())) {
      +  289  0
                   addDisguisedJarsToDependencies(dependency, engine);
      +  290  0
                   engine.getDependencies().remove(dependency);
      +  291   +
               }
      +  292  2
               Collections.sort(engine.getDependencies());
      +  293  2
           }
      +  294   +
       
      +  295   +
           /**
       296   -
                       }
      -  297  0
                   } catch (IOException ex) {
      -  298  0
                       LOGGER.debug("Unable to perform deep copy on '{}'", dependency.getActualFile().getPath(), ex);
      -  299  0
                   }
      +
            * If a zip file was identified as a possible JAR, this method will add the
      +  297   +
            * zip to the list of dependencies.
      +  298   +
            *
      +  299   +
            * @param dependency the zip file
       300   -
               }
      -  301  0
           }
      +
            * @param engine the engine
      +  301   +
            * @throws AnalysisException thrown if there is an issue
       302   -
           /**
      +
            */
       303   -
            * An empty dependency set.
      -  304   -
            */
      -  305  1
           private static final Set<Dependency> EMPTY_DEPENDENCY_SET = Collections.emptySet();
      -  306   -
       
      +
           private void addDisguisedJarsToDependencies(Dependency dependency, Engine engine) throws AnalysisException {
      +  304  0
               if (ZIP_FILTER.accept(dependency.getActualFile()) && isZipFileActuallyJarFile(dependency)) {
      +  305  0
                   final File tdir = getNextTempDirectory();
      +  306  0
                   final String fileName = dependency.getFileName();
       307   -
           /**
      -  308   -
            * Scan the given file/folder, and return any new dependencies found.
      -  309   -
            *
      +
       
      +  308  0
                   LOGGER.info("The zip file '{}' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName);
      +  309  0
                   final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar");
       310   -
            * @param engine used to scan
      +
                   //store the archives sha1 and change it so that the engine doesn't think the zip and jar file are the same
       311   -
            * @param file target of scanning
      -  312   -
            * @return any dependencies that weren't known to the engine before
      +
                   // and add it is a related dependency.
      +  312  0
                   final String archiveSha1 = dependency.getSha1sum();
       313   -
            */
      -  314   -
           private static Set<Dependency> findMoreDependencies(Engine engine, File file) {
      -  315  2
               final List<Dependency> before = new ArrayList<Dependency>(engine.getDependencies());
      -  316  2
               engine.scan(file);
      -  317  2
               final List<Dependency> after = engine.getDependencies();
      -  318  2
               final boolean sizeChanged = before.size() != after.size();
      +
                   try {
      +  314  0
                       dependency.setSha1sum("");
      +  315  0
                       org.apache.commons.io.FileUtils.copyFile(dependency.getActualFile(), tmpLoc);
      +  316  0
                       final List<Dependency> dependencySet = findMoreDependencies(engine, tmpLoc);
      +  317  0
                       if (!dependencySet.isEmpty()) {
      +  318  0
                           for (Dependency d : dependencySet) {
       319   -
               final Set<Dependency> newDependencies;
      -  320  2
               if (sizeChanged) {
      -  321   -
                   //get the new dependencies
      -  322  0
                   newDependencies = new HashSet<Dependency>(after);
      -  323  0
                   newDependencies.removeAll(before);
      -  324   -
               } else {
      -  325  2
                   newDependencies = EMPTY_DEPENDENCY_SET;
      -  326   -
               }
      -  327  2
               return newDependencies;
      +
                               //fix the dependency's display name and path
      +  320  0
                               if (d.getActualFile().equals(tmpLoc)) {
      +  321  0
                                   d.setFilePath(dependency.getFilePath());
      +  322  0
                                   d.setDisplayFileName(dependency.getFileName());
      +  323   +
                               } else {
      +  324  0
                                   for (Dependency sub : d.getRelatedDependencies()) {
      +  325  0
                                       if (sub.getActualFile().equals(tmpLoc)) {
      +  326  0
                                           sub.setFilePath(dependency.getFilePath());
      +  327  0
                                           sub.setDisplayFileName(dependency.getFileName());
       328   -
           }
      -  329   -
       
      -  330   -
           /**
      -  331   -
            * Retrieves the next temporary directory to extract an archive too.
      -  332   -
            *
      -  333   -
            * @return a directory
      -  334   -
            * @throws AnalysisException thrown if unable to create temporary directory
      -  335   -
            */
      -  336   -
           private File getNextTempDirectory() throws AnalysisException {
      -  337  2
               dirCount += 1;
      -  338  2
               final File directory = new File(tempFileLocation, String.valueOf(dirCount));
      -  339   -
               //getting an exception for some directories not being able to be created; might be because the directory already exists?
      -  340  2
               if (directory.exists()) {
      -  341  0
                   return getNextTempDirectory();
      -  342   -
               }
      -  343  2
               if (!directory.mkdirs()) {
      -  344  0
                   final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath());
      -  345  0
                   throw new AnalysisException(msg);
      -  346   -
               }
      -  347  2
               return directory;
      -  348   -
           }
      -  349   -
       
      -  350   -
           /**
      -  351   -
            * Extracts the contents of an archive into the specified directory.
      -  352   -
            *
      -  353   -
            * @param archive an archive file such as a WAR or EAR
      -  354   -
            * @param destination a directory to extract the contents to
      -  355   -
            * @param engine the scanning engine
      -  356   -
            * @throws AnalysisException thrown if the archive is not found
      -  357   -
            */
      -  358   -
           private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException {
      -  359  2
               if (archive != null && destination != null) {
      -  360  2
                   String archiveExt = FileUtils.getFileExtension(archive.getName());
      -  361  2
                   if (archiveExt == null) {
      -  362  0
                       return;
      -  363   -
                   }
      -  364  2
                   archiveExt = archiveExt.toLowerCase();
      -  365   -
       
      -  366   -
                   FileInputStream fis;
      -  367   -
                   try {
      -  368  2
                       fis = new FileInputStream(archive);
      -  369  0
                   } catch (FileNotFoundException ex) {
      -  370  0
                       LOGGER.debug("", ex);
      -  371  0
                       throw new AnalysisException("Archive file was not found.", ex);
      -  372  2
                   }
      -  373   -
                   try {
      -  374  2
                       if (ZIPPABLES.contains(archiveExt)) {
      -  375  2
                           final BufferedInputStream in = new BufferedInputStream(fis);
      -  376  2
                           ensureReadableJar(archiveExt, in);
      -  377  2
                           extractArchive(new ZipArchiveInputStream(in), destination, engine);
      -  378  2
                       } else if ("tar".equals(archiveExt)) {
      -  379  0
                           extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
      -  380  0
                       } else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
      -  381  0
                           final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName());
      -  382  0
                           final File f = new File(destination, uncompressedName);
      -  383  0
                           if (engine.accept(f)) {
      -  384  0
                               decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), f);
      -  385   -
                           }
      -  386  0
                       } else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) {
      -  387  0
                           final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName());
      -  388  0
                           final File f = new File(destination, uncompressedName);
      -  389  0
                           if (engine.accept(f)) {
      -  390  0
                               decompressFile(new BZip2CompressorInputStream(new BufferedInputStream(fis)), f);
      -  391   -
                           }
      -  392   -
                       }
      -  393  0
                   } catch (ArchiveExtractionException ex) {
      -  394  0
                       LOGGER.warn("Exception extracting archive '{}'.", archive.getName());
      -  395  0
                       LOGGER.debug("", ex);
      -  396  0
                   } catch (IOException ex) {
      -  397  0
                       LOGGER.warn("Exception reading archive '{}'.", archive.getName());
      -  398  0
                       LOGGER.debug("", ex);
      -  399   -
                   } finally {
      -  400  2
                       close(fis);
      -  401  2
                   }
      -  402   -
               }
      -  403  2
           }
      -  404   -
       
      -  405   -
           /**
      -  406   -
            * Checks if the file being scanned is a JAR that begins with '#!/bin' which
      -  407   -
            * indicates it is a fully executable jar. If a fully executable JAR is
      -  408   -
            * identified the input stream will be advanced to the start of the actual
      -  409   -
            * JAR file ( skipping the script).
      -  410   -
            *
      -  411   -
            * @see
      -  412   -
            * <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing
      -  413   -
            * Spring Boot Applications</a>
      -  414   -
            * @param archiveExt the file extension
      -  415   -
            * @param in the input stream
      -  416   -
            * @throws IOException thrown if there is an error reading the stream
      -  417   -
            */
      -  418   -
           private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException {
      -  419  2
               if ("jar".equals(archiveExt) && in.markSupported()) {
      -  420  2
                   in.mark(7);
      -  421  2
                   final byte[] b = new byte[7];
      -  422  2
                   final int read = in.read(b);
      -  423  2
                   if (read == 7
      -  424   -
                           && b[0] == '#'
      -  425   -
                           && b[1] == '!'
      -  426   -
                           && b[2] == '/'
      -  427   -
                           && b[3] == 'b'
      -  428   -
                           && b[4] == 'i'
      -  429   -
                           && b[5] == 'n'
      -  430   -
                           && b[6] == '/') {
      -  431  0
                       boolean stillLooking = true;
      -  432   -
                       int chr, nxtChr;
      -  433  0
                       while (stillLooking && (chr = in.read()) != -1) {
      -  434  0
                           if (chr == '\n' || chr == '\r') {
      -  435  0
                               in.mark(4);
      -  436  0
                               if ((chr = in.read()) != -1) {
      -  437  0
                                   if (chr == 'P' && (chr = in.read()) != -1) {
      -  438  0
                                       if (chr == 'K' && (chr = in.read()) != -1) {
      -  439  0
                                           if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) {
      -  440  0
                                               if (nxtChr == chr + 1) {
      -  441  0
                                                   stillLooking = false;
      -  442  0
                                                   in.reset();
      -  443   -
                                               }
      -  444   -
                                           }
      -  445  
                                       }
      -  446   -
                                   }
      -  447   +  329  0
                                   }
      +  330  
                               }
      -  448   -
                           }
      -  449   +  331  0
                           }
      +  332  
                       }
      -  450  0
                   } else {
      -  451  2
                       in.reset();
      -  452   -
                   }
      -  453   +  333  0
                   } catch (IOException ex) {
      +  334  0
                       LOGGER.debug("Unable to perform deep copy on '{}'", dependency.getActualFile().getPath(), ex);
      +  335   +
                   } finally {
      +  336  0
                       dependency.setSha1sum(archiveSha1);
      +  337  0
                   }
      +  338  
               }
      -  454  2
           }
      -  455   +  339  0
           }
      +  340  
       
      -  456   +  341  
           /**
      -  457   -
            * Extracts files from an archive.
      -  458   +  342   +
            * Scan the given file/folder, and return any new dependencies found.
      +  343  
            *
      -  459   -
            * @param input the archive to extract files from
      -  460   -
            * @param destination the location to write the files too
      -  461   -
            * @param engine the dependency-check engine
      -  462   -
            * @throws ArchiveExtractionException thrown if there is an exception
      -  463   -
            * extracting files from the archive
      -  464   +  344   +
            * @param engine used to scan
      +  345   +
            * @param file target of scanning
      +  346   +
            * @return any dependencies that weren't known to the engine before
      +  347  
            */
      -  465   -
           private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException {
      -  466   -
               ArchiveEntry entry;
      -  467   -
               try {
      -  468  887
                   while ((entry = input.getNextEntry()) != null) {
      -  469  885
                       final File file = new File(destination, entry.getName());
      -  470  885
                       if (entry.isDirectory()) {
      -  471  36
                           if (!file.exists() && !file.mkdirs()) {
      -  472  0
                               final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath());
      -  473  0
                               throw new AnalysisException(msg);
      -  474   -
                           }
      -  475  849
                       } else if (engine.accept(file)) {
      -  476  0
                           extractAcceptedFile(input, file);
      -  477   -
                       }
      -  478  885
                   }
      -  479  0
               } catch (Throwable ex) {
      -  480  0
                   throw new ArchiveExtractionException(ex);
      -  481   -
               } finally {
      -  482  2
                   close(input);
      -  483  2
               }
      -  484  2
           }
      -  485   -
       
      -  486   -
           /**
      -  487   -
            * Extracts a file from an archive.
      -  488   -
            *
      -  489   -
            * @param input the archives input stream
      -  490   -
            * @param file the file to extract
      -  491   -
            * @throws AnalysisException thrown if there is an error
      -  492   -
            */
      -  493   -
           private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException {
      -  494  0
               LOGGER.debug("Extracting '{}'", file.getPath());
      -  495  0
               FileOutputStream fos = null;
      -  496   -
               try {
      -  497  0
                   final File parent = file.getParentFile();
      -  498  0
                   if (!parent.isDirectory() && !parent.mkdirs()) {
      -  499  0
                       final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath());
      -  500  0
                       throw new AnalysisException(msg);
      -  501   -
                   }
      -  502  0
                   fos = new FileOutputStream(file);
      -  503  0
                   IOUtils.copy(input, fos);
      -  504  0
               } catch (FileNotFoundException ex) {
      -  505  0
                   LOGGER.debug("", ex);
      -  506  0
                   final String msg = String.format("Unable to find file '%s'.", file.getName());
      -  507  0
                   throw new AnalysisException(msg, ex);
      -  508  0
               } catch (IOException ex) {
      -  509  0
                   LOGGER.debug("", ex);
      -  510  0
                   final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
      -  511  0
                   throw new AnalysisException(msg, ex);
      -  512   -
               } finally {
      -  513  0
                   close(fos);
      -  514  0
               }
      -  515  0
           }
      -  516   -
       
      -  517   -
           /**
      -  518   -
            * Decompresses a file.
      -  519   -
            *
      -  520   -
            * @param inputStream the compressed file
      -  521   -
            * @param outputFile the location to write the decompressed file
      -  522   -
            * @throws ArchiveExtractionException thrown if there is an exception
      -  523   -
            * decompressing the file
      -  524   -
            */
      -  525   -
           private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
      -  526  0
               LOGGER.debug("Decompressing '{}'", outputFile.getPath());
      -  527  0
               FileOutputStream out = null;
      -  528   -
               try {
      -  529  0
                   out = new FileOutputStream(outputFile);
      -  530  0
                   IOUtils.copy(inputStream, out);
      -  531  0
               } catch (FileNotFoundException ex) {
      -  532  0
                   LOGGER.debug("", ex);
      -  533  0
                   throw new ArchiveExtractionException(ex);
      -  534  0
               } catch (IOException ex) {
      -  535  0
                   LOGGER.debug("", ex);
      -  536  0
                   throw new ArchiveExtractionException(ex);
      -  537   -
               } finally {
      -  538  0
                   close(out);
      -  539  0
               }
      -  540  0
           }
      -  541   -
       
      -  542   -
           /**
      -  543   -
            * Close the given {@link Closeable} instance, ignoring nulls, and logging
      -  544   -
            * any thrown {@link IOException}.
      -  545   -
            *
      -  546   -
            * @param closeable to be closed
      -  547   -
            */
      -  548   -
           private static void close(Closeable closeable) {
      -  549  4
               if (null != closeable) {
      -  550   -
                   try {
      -  551  4
                       closeable.close();
      -  552  0
                   } catch (IOException ex) {
      -  553  0
                       LOGGER.trace("", ex);
      -  554  4
                   }
      -  555   -
               }
      -  556  4
           }
      -  557   -
       
      -  558   -
           /**
      -  559   -
            * Attempts to determine if a zip file is actually a JAR file.
      -  560   -
            *
      -  561   -
            * @param dependency the dependency to check
      -  562   -
            * @return true if the dependency appears to be a JAR file; otherwise false
      -  563   -
            */
      -  564   -
           private boolean isZipFileActuallyJarFile(Dependency dependency) {
      -  565  0
               boolean isJar = false;
      -  566  0
               ZipFile zip = null;
      -  567   -
               try {
      -  568  0
                   zip = new ZipFile(dependency.getActualFilePath());
      -  569  0
                   if (zip.getEntry("META-INF/MANIFEST.MF") != null
      -  570  0
                           || zip.getEntry("META-INF/maven") != null) {
      -  571  0
                       final Enumeration<ZipArchiveEntry> entries = zip.getEntries();
      -  572  0
                       while (entries.hasMoreElements()) {
      -  573  0
                           final ZipArchiveEntry entry = entries.nextElement();
      -  574  0
                           if (!entry.isDirectory()) {
      -  575  0
                               final String name = entry.getName().toLowerCase();
      -  576  0
                               if (name.endsWith(".class")) {
      -  577  0
                                   isJar = true;
      -  578  0
                                   break;
      -  579   -
                               }
      -  580   -
                           }
      -  581  0
                       }
      -  582   -
                   }
      -  583  0
               } catch (IOException ex) {
      -  584  0
                   LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex);
      -  585   -
               } finally {
      -  586  0
                   ZipFile.closeQuietly(zip);
      -  587  0
               }
      -  588   -
       
      -  589  0
               return isJar;
      -  590   +  348   +
           private static List<Dependency> findMoreDependencies(Engine engine, File file) {
      +  349  2
               final List<Dependency> added = engine.scan(file);
      +  350  2
               return added;
      +  351  
           }
      -  591   +  352   +
       
      +  353   +
           /**
      +  354   +
            * Retrieves the next temporary directory to extract an archive too.
      +  355   +
            *
      +  356   +
            * @return a directory
      +  357   +
            * @throws AnalysisException thrown if unable to create temporary directory
      +  358   +
            */
      +  359   +
           private File getNextTempDirectory() throws AnalysisException {
      +  360  2
               dirCount += 1;
      +  361  2
               final File directory = new File(tempFileLocation, String.valueOf(dirCount));
      +  362   +
               //getting an exception for some directories not being able to be created; might be because the directory already exists?
      +  363  2
               if (directory.exists()) {
      +  364  0
                   return getNextTempDirectory();
      +  365   +
               }
      +  366  2
               if (!directory.mkdirs()) {
      +  367  0
                   final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath());
      +  368  0
                   throw new AnalysisException(msg);
      +  369   +
               }
      +  370  2
               return directory;
      +  371   +
           }
      +  372   +
       
      +  373   +
           /**
      +  374   +
            * Extracts the contents of an archive into the specified directory.
      +  375   +
            *
      +  376   +
            * @param archive an archive file such as a WAR or EAR
      +  377   +
            * @param destination a directory to extract the contents to
      +  378   +
            * @param engine the scanning engine
      +  379   +
            * @throws AnalysisException thrown if the archive is not found
      +  380   +
            */
      +  381   +
           private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException {
      +  382  2
               if (archive != null && destination != null) {
      +  383  2
                   String archiveExt = FileUtils.getFileExtension(archive.getName());
      +  384  2
                   if (archiveExt == null) {
      +  385  0
                       return;
      +  386   +
                   }
      +  387  2
                   archiveExt = archiveExt.toLowerCase();
      +  388   +
       
      +  389   +
                   final FileInputStream fis;
      +  390   +
                   try {
      +  391  2
                       fis = new FileInputStream(archive);
      +  392  0
                   } catch (FileNotFoundException ex) {
      +  393  0
                       LOGGER.debug("", ex);
      +  394  0
                       throw new AnalysisException("Archive file was not found.", ex);
      +  395  2
                   }
      +  396  2
                   BufferedInputStream in = null;
      +  397  2
                   ZipArchiveInputStream zin = null;
      +  398  2
                   TarArchiveInputStream tin = null;
      +  399  2
                   GzipCompressorInputStream gin = null;
      +  400  2
                   BZip2CompressorInputStream bzin = null;
      +  401   +
                   try {
      +  402  2
                       if (ZIPPABLES.contains(archiveExt)) {
      +  403  2
                           in = new BufferedInputStream(fis);
      +  404  2
                           ensureReadableJar(archiveExt, in);
      +  405  2
                           zin = new ZipArchiveInputStream(in);
      +  406  2
                           extractArchive(zin, destination, engine);
      +  407  0
                       } else if ("tar".equals(archiveExt)) {
      +  408  0
                           in = new BufferedInputStream(fis);
      +  409  0
                           tin = new TarArchiveInputStream(in);
      +  410  0
                           extractArchive(tin, destination, engine);
      +  411  0
                       } else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
      +  412  0
                           final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName());
      +  413  0
                           final File f = new File(destination, uncompressedName);
      +  414  0
                           if (engine.accept(f)) {
      +  415  0
                               in = new BufferedInputStream(fis);
      +  416  0
                               gin = new GzipCompressorInputStream(in);
      +  417  0
                               decompressFile(gin, f);
      +  418   +
                           }
      +  419  0
                       } else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) {
      +  420  0
                           final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName());
      +  421  0
                           final File f = new File(destination, uncompressedName);
      +  422  0
                           if (engine.accept(f)) {
      +  423  0
                               in = new BufferedInputStream(fis);
      +  424  0
                               bzin = new BZip2CompressorInputStream(in);
      +  425  0
                               decompressFile(bzin, f);
      +  426   +
                           }
      +  427   +
                       }
      +  428  0
                   } catch (ArchiveExtractionException ex) {
      +  429  0
                       LOGGER.warn("Exception extracting archive '{}'.", archive.getName());
      +  430  0
                       LOGGER.debug("", ex);
      +  431  0
                   } catch (IOException ex) {
      +  432  0
                       LOGGER.warn("Exception reading archive '{}'.", archive.getName());
      +  433  0
                       LOGGER.debug("", ex);
      +  434   +
                   } finally {
      +  435   +
                       //overly verbose and not needed... but keeping it anyway due to
      +  436   +
                       //having issue with file handles being left open
      +  437  2
                       close(fis);
      +  438  2
                       close(in);
      +  439  2
                       close(zin);
      +  440  2
                       close(tin);
      +  441  2
                       close(gin);
      +  442  2
                       close(bzin);
      +  443  2
                   }
      +  444   +
               }
      +  445  2
           }
      +  446   +
       
      +  447   +
           /**
      +  448   +
            * Checks if the file being scanned is a JAR that begins with '#!/bin' which
      +  449   +
            * indicates it is a fully executable jar. If a fully executable JAR is
      +  450   +
            * identified the input stream will be advanced to the start of the actual
      +  451   +
            * JAR file ( skipping the script).
      +  452   +
            *
      +  453   +
            * @see
      +  454   +
            * <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing
      +  455   +
            * Spring Boot Applications</a>
      +  456   +
            * @param archiveExt the file extension
      +  457   +
            * @param in the input stream
      +  458   +
            * @throws IOException thrown if there is an error reading the stream
      +  459   +
            */
      +  460   +
           private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException {
      +  461  2
               if ("jar".equals(archiveExt) && in.markSupported()) {
      +  462  2
                   in.mark(7);
      +  463  2
                   final byte[] b = new byte[7];
      +  464  2
                   final int read = in.read(b);
      +  465  2
                   if (read == 7
      +  466   +
                           && b[0] == '#'
      +  467   +
                           && b[1] == '!'
      +  468   +
                           && b[2] == '/'
      +  469   +
                           && b[3] == 'b'
      +  470   +
                           && b[4] == 'i'
      +  471   +
                           && b[5] == 'n'
      +  472   +
                           && b[6] == '/') {
      +  473  0
                       boolean stillLooking = true;
      +  474   +
                       int chr, nxtChr;
      +  475  0
                       while (stillLooking && (chr = in.read()) != -1) {
      +  476  0
                           if (chr == '\n' || chr == '\r') {
      +  477  0
                               in.mark(4);
      +  478  0
                               if ((chr = in.read()) != -1) {
      +  479  0
                                   if (chr == 'P' && (chr = in.read()) != -1) {
      +  480  0
                                       if (chr == 'K' && (chr = in.read()) != -1) {
      +  481  0
                                           if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) {
      +  482  0
                                               if (nxtChr == chr + 1) {
      +  483  0
                                                   stillLooking = false;
      +  484  0
                                                   in.reset();
      +  485   +
                                               }
      +  486   +
                                           }
      +  487   +
                                       }
      +  488   +
                                   }
      +  489   +
                               }
      +  490   +
                           }
      +  491   +
                       }
      +  492  0
                   } else {
      +  493  2
                       in.reset();
      +  494   +
                   }
      +  495   +
               }
      +  496  2
           }
      +  497   +
       
      +  498   +
           /**
      +  499   +
            * Extracts files from an archive.
      +  500   +
            *
      +  501   +
            * @param input the archive to extract files from
      +  502   +
            * @param destination the location to write the files too
      +  503   +
            * @param engine the dependency-check engine
      +  504   +
            * @throws ArchiveExtractionException thrown if there is an exception
      +  505   +
            * extracting files from the archive
      +  506   +
            */
      +  507   +
           private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException {
      +  508   +
               ArchiveEntry entry;
      +  509   +
               try {
      +  510  887
                   while ((entry = input.getNextEntry()) != null) {
      +  511  885
                       final File file = new File(destination, entry.getName());
      +  512  885
                       if (entry.isDirectory()) {
      +  513  36
                           if (!file.exists() && !file.mkdirs()) {
      +  514  0
                               final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath());
      +  515  0
                               throw new AnalysisException(msg);
      +  516   +
                           }
      +  517  849
                       } else if (engine.accept(file)) {
      +  518  0
                           extractAcceptedFile(input, file);
      +  519   +
                       }
      +  520  885
                   }
      +  521  0
               } catch (Throwable ex) {
      +  522  0
                   throw new ArchiveExtractionException(ex);
      +  523   +
               } finally {
      +  524  2
                   close(input);
      +  525  2
               }
      +  526  2
           }
      +  527   +
       
      +  528   +
           /**
      +  529   +
            * Extracts a file from an archive.
      +  530   +
            *
      +  531   +
            * @param input the archives input stream
      +  532   +
            * @param file the file to extract
      +  533   +
            * @throws AnalysisException thrown if there is an error
      +  534   +
            */
      +  535   +
           private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException {
      +  536  0
               LOGGER.debug("Extracting '{}'", file.getPath());
      +  537  0
               FileOutputStream fos = null;
      +  538   +
               try {
      +  539  0
                   final File parent = file.getParentFile();
      +  540  0
                   if (!parent.isDirectory() && !parent.mkdirs()) {
      +  541  0
                       final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath());
      +  542  0
                       throw new AnalysisException(msg);
      +  543   +
                   }
      +  544  0
                   fos = new FileOutputStream(file);
      +  545  0
                   IOUtils.copy(input, fos);
      +  546  0
               } catch (FileNotFoundException ex) {
      +  547  0
                   LOGGER.debug("", ex);
      +  548  0
                   final String msg = String.format("Unable to find file '%s'.", file.getName());
      +  549  0
                   throw new AnalysisException(msg, ex);
      +  550  0
               } catch (IOException ex) {
      +  551  0
                   LOGGER.debug("", ex);
      +  552  0
                   final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
      +  553  0
                   throw new AnalysisException(msg, ex);
      +  554   +
               } finally {
      +  555  0
                   close(fos);
      +  556  0
               }
      +  557  0
           }
      +  558   +
       
      +  559   +
           /**
      +  560   +
            * Decompresses a file.
      +  561   +
            *
      +  562   +
            * @param inputStream the compressed file
      +  563   +
            * @param outputFile the location to write the decompressed file
      +  564   +
            * @throws ArchiveExtractionException thrown if there is an exception
      +  565   +
            * decompressing the file
      +  566   +
            */
      +  567   +
           private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
      +  568  0
               LOGGER.debug("Decompressing '{}'", outputFile.getPath());
      +  569  0
               FileOutputStream out = null;
      +  570   +
               try {
      +  571  0
                   out = new FileOutputStream(outputFile);
      +  572  0
                   IOUtils.copy(inputStream, out);
      +  573  0
               } catch (FileNotFoundException ex) {
      +  574  0
                   LOGGER.debug("", ex);
      +  575  0
                   throw new ArchiveExtractionException(ex);
      +  576  0
               } catch (IOException ex) {
      +  577  0
                   LOGGER.debug("", ex);
      +  578  0
                   throw new ArchiveExtractionException(ex);
      +  579   +
               } finally {
      +  580  0
                   close(out);
      +  581  0
               }
      +  582  0
           }
      +  583   +
       
      +  584   +
           /**
      +  585   +
            * Close the given {@link Closeable} instance, ignoring nulls, and logging
      +  586   +
            * any thrown {@link IOException}.
      +  587   +
            *
      +  588   +
            * @param closeable to be closed
      +  589   +
            */
      +  590   +
           private static void close(Closeable closeable) {
      +  591  14
               if (null != closeable) {
      +  592   +
                   try {
      +  593  8
                       closeable.close();
      +  594  0
                   } catch (IOException ex) {
      +  595  0
                       LOGGER.trace("", ex);
      +  596  8
                   }
      +  597   +
               }
      +  598  14
           }
      +  599   +
       
      +  600   +
           /**
      +  601   +
            * Attempts to determine if a zip file is actually a JAR file.
      +  602   +
            *
      +  603   +
            * @param dependency the dependency to check
      +  604   +
            * @return true if the dependency appears to be a JAR file; otherwise false
      +  605   +
            */
      +  606   +
           private boolean isZipFileActuallyJarFile(Dependency dependency) {
      +  607  0
               boolean isJar = false;
      +  608  0
               ZipFile zip = null;
      +  609   +
               try {
      +  610  0
                   zip = new ZipFile(dependency.getActualFilePath());
      +  611  0
                   if (zip.getEntry("META-INF/MANIFEST.MF") != null
      +  612  0
                           || zip.getEntry("META-INF/maven") != null) {
      +  613  0
                       final Enumeration<ZipArchiveEntry> entries = zip.getEntries();
      +  614  0
                       while (entries.hasMoreElements()) {
      +  615  0
                           final ZipArchiveEntry entry = entries.nextElement();
      +  616  0
                           if (!entry.isDirectory()) {
      +  617  0
                               final String name = entry.getName().toLowerCase();
      +  618  0
                               if (name.endsWith(".class")) {
      +  619  0
                                   isJar = true;
      +  620  0
                                   break;
      +  621   +
                               }
      +  622   +
                           }
      +  623  0
                       }
      +  624   +
                   }
      +  625  0
               } catch (IOException ex) {
      +  626  0
                   LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex);
      +  627   +
               } finally {
      +  628  0
                   ZipFile.closeQuietly(zip);
      +  629  0
               }
      +  630   +
       
      +  631  0
               return isJar;
      +  632   +
           }
      +  633  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AssemblyAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AssemblyAnalyzer.html index ab1eb6994..6985e708f 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AssemblyAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AssemblyAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      AssemblyAnalyzer
      31%
      47/147
      21%
      10/46
      7
      AssemblyAnalyzer
      32%
      48/148
      21%
      10/46
      7
       
      @@ -129,7 +129,7 @@
        *
       56  
        */
      -  57  11
       public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
      +  57  13
       public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
       58  
       
       59   @@ -160,460 +160,451 @@
            * The temp value for GrokAssembly.exe
       73  
            */
      -  74  11
           private File grokAssemblyExe = null;
      +  74  13
           private File grokAssemblyExe = null;
       75  
           /**
       76   -
            * The DocumentBuilder for parsing the XML
      +
            * Logger
       77  
            */
      -  78   -
           private DocumentBuilder builder;
      +  78  1
           private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class);
       79   -
           /**
      +
       
       80   -
            * Logger
      +
           /**
       81   -
            */
      -  82  1
           private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class);
      -  83   -
       
      -  84   -
           /**
      -  85  
            * Builds the beginnings of a List for ProcessBuilder
      -  86   +  82  
            *
      -  87   +  83  
            * @return the list of arguments to begin populating the ProcessBuilder
      -  88   +  84  
            */
      -  89   +  85  
           protected List<String> buildArgumentList() {
      -  90   +  86  
               // Use file.separator as a wild guess as to whether this is Windows
      -  91  10
               final List<String> args = new ArrayList<String>();
      -  92  10
               if (!SystemUtils.IS_OS_WINDOWS) {
      -  93  0
                   if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
      -  94  0
                       args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
      -  95  0
                   } else if (isInPath("mono")) {
      -  96  0
                       args.add("mono");
      -  97   +  87  10
               final List<String> args = new ArrayList<String>();
      +  88  10
               if (!SystemUtils.IS_OS_WINDOWS) {
      +  89  0
                   if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
      +  90  0
                       args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
      +  91  0
                   } else if (isInPath("mono")) {
      +  92  0
                       args.add("mono");
      +  93  
                   } else {
      -  98  0
                       return null;
      +  94  0
                       return null;
      +  95   +
                   }
      +  96   +
               }
      +  97  10
               args.add(grokAssemblyExe.getPath());
      +  98  10
               return args;
       99   -
                   }
      +
           }
       100   -
               }
      -  101  10
               args.add(grokAssemblyExe.getPath());
      -  102  10
               return args;
      -  103   -
           }
      -  104  
       
      -  105   +  101  
           /**
      -  106   +  102  
            * Performs the analysis on a single Dependency.
      -  107   +  103  
            *
      -  108   +  104  
            * @param dependency the dependency to analyze
      -  109   +  105  
            * @param engine the engine to perform the analysis under
      -  110   +  106  
            * @throws AnalysisException if anything goes sideways
      -  111   +  107  
            */
      -  112   +  108  
           @Override
      -  113   +  109  
           public void analyzeFileType(Dependency dependency, Engine engine)
      -  114   +  110  
                   throws AnalysisException {
      -  115  0
               if (grokAssemblyExe == null) {
      -  116  0
                   LOGGER.warn("GrokAssembly didn't get deployed");
      -  117  0
                   return;
      -  118   +  111  0
               if (grokAssemblyExe == null) {
      +  112  0
                   LOGGER.warn("GrokAssembly didn't get deployed");
      +  113  0
                   return;
      +  114  
               }
      -  119   +  115  
       
      -  120  0
               final List<String> args = buildArgumentList();
      -  121  0
               if (args == null) {
      -  122  0
                   LOGGER.warn("Assembly Analyzer was unable to execute");
      -  123  0
                   return;
      +  116  0
               final List<String> args = buildArgumentList();
      +  117  0
               if (args == null) {
      +  118  0
                   LOGGER.warn("Assembly Analyzer was unable to execute");
      +  119  0
                   return;
      +  120   +
               }
      +  121  0
               args.add(dependency.getActualFilePath());
      +  122  0
               final ProcessBuilder pb = new ProcessBuilder(args);
      +  123  0
               Document doc = null;
       124   -
               }
      -  125  0
               args.add(dependency.getActualFilePath());
      -  126  0
               final ProcessBuilder pb = new ProcessBuilder(args);
      -  127  0
               Document doc = null;
      -  128  
               try {
      -  129  0
                   final Process proc = pb.start();
      +  125  0
                   final Process proc = pb.start();
      +  126   +
       
      +  127  0
                   final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
      +  128  0
                   doc = builder.parse(proc.getInputStream());
      +  129   +
       
       130   -
       
      -  131  0
                   doc = builder.parse(proc.getInputStream());
      -  132   -
       
      -  133  
                   // Try evacuating the error stream
      -  134  0
                   final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8");
      -  135  0
                   if (null != errorStream && !errorStream.isEmpty()) {
      -  136  0
                       LOGGER.warn("Error from GrokAssembly: {}", errorStream);
      +  131  0
                   final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8");
      +  132  0
                   if (null != errorStream && !errorStream.isEmpty()) {
      +  133  0
                       LOGGER.warn("Error from GrokAssembly: {}", errorStream);
      +  134   +
                   }
      +  135   +
       
      +  136  0
                   int rc = 0;
       137   -
                   }
      -  138   -
       
      -  139  0
                   int rc = 0;
      -  140  
                   try {
      -  141  0
                       rc = proc.waitFor();
      -  142  0
                   } catch (InterruptedException ie) {
      -  143  0
                       return;
      -  144  0
                   }
      -  145  0
                   if (rc == 3) {
      -  146  0
                       LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check",
      -  147  0
                               dependency.getActualFilePath());
      -  148  0
                       return;
      -  149  0
                   } else if (rc != 0) {
      -  150  0
                       LOGGER.warn("Return code {} from GrokAssembly", rc);
      +  138  0
                       rc = proc.waitFor();
      +  139  0
                   } catch (InterruptedException ie) {
      +  140  0
                       return;
      +  141  0
                   }
      +  142  0
                   if (rc == 3) {
      +  143  0
                       LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check",
      +  144  0
                               dependency.getActualFilePath());
      +  145  0
                       return;
      +  146  0
                   } else if (rc != 0) {
      +  147  0
                       LOGGER.warn("Return code {} from GrokAssembly", rc);
      +  148   +
                   }
      +  149   +
       
      +  150  0
                   final XPath xpath = XPathFactory.newInstance().newXPath();
       151   -
                   }
      +
       
       152   -
       
      -  153  0
                   final XPath xpath = XPathFactory.newInstance().newXPath();
      -  154   -
       
      -  155  
                   // First, see if there was an error
      -  156  0
                   final String error = xpath.evaluate("/assembly/error", doc);
      -  157  0
                   if (error != null && !error.isEmpty()) {
      -  158  0
                       throw new AnalysisException(error);
      -  159   +  153  0
                   final String error = xpath.evaluate("/assembly/error", doc);
      +  154  0
                   if (error != null && !error.isEmpty()) {
      +  155  0
                       throw new AnalysisException(error);
      +  156  
                   }
      -  160   +  157  
       
      -  161  0
                   final String version = xpath.evaluate("/assembly/version", doc);
      -  162  0
                   if (version != null) {
      -  163  0
                       dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version",
      -  164   +  158  0
                   final String version = xpath.evaluate("/assembly/version", doc);
      +  159  0
                   if (version != null) {
      +  160  0
                       dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version",
      +  161  
                               version, Confidence.HIGHEST));
      -  165   +  162  
                   }
      -  166   +  163  
       
      -  167  0
                   final String vendor = xpath.evaluate("/assembly/company", doc);
      -  168  0
                   if (vendor != null) {
      -  169  0
                       dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor",
      -  170   +  164  0
                   final String vendor = xpath.evaluate("/assembly/company", doc);
      +  165  0
                   if (vendor != null) {
      +  166  0
                       dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor",
      +  167  
                               vendor, Confidence.HIGH));
      -  171   +  168  
                   }
      -  172   +  169  
       
      -  173  0
                   final String product = xpath.evaluate("/assembly/product", doc);
      -  174  0
                   if (product != null) {
      -  175  0
                       dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product",
      -  176   +  170  0
                   final String product = xpath.evaluate("/assembly/product", doc);
      +  171  0
                   if (product != null) {
      +  172  0
                       dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product",
      +  173  
                               product, Confidence.HIGH));
      -  177   +  174  
                   }
      -  178   +  175  
       
      -  179  0
               } catch (IOException ioe) {
      -  180  0
                   throw new AnalysisException(ioe);
      -  181  0
               } catch (SAXException saxe) {
      -  182  0
                   throw new AnalysisException("Couldn't parse GrokAssembly result", saxe);
      -  183  0
               } catch (XPathExpressionException xpe) {
      -  184   +  176  0
               } catch (ParserConfigurationException pce) {
      +  177  0
                   throw new AnalysisException("Error initializing the assembly analyzer", pce);
      +  178  0
               } catch (IOException ioe) {
      +  179  0
                   throw new AnalysisException(ioe);
      +  180  0
               } catch (SAXException saxe) {
      +  181  0
                   throw new AnalysisException("Couldn't parse GrokAssembly result", saxe);
      +  182  0
               } catch (XPathExpressionException xpe) {
      +  183  
                   // This shouldn't happen
      -  185  0
                   throw new AnalysisException(xpe);
      -  186  0
               }
      -  187  0
           }
      +  184  0
                   throw new AnalysisException(xpe);
      +  185  0
               }
      +  186  0
           }
      +  187   +
       
       188   -
       
      +
           /**
       189   -
           /**
      -  190  
            * Initialize the analyzer. In this case, extract GrokAssembly.exe to a
      -  191   +  190  
            * temporary location.
      +  191   +
            *
       192   -
            *
      -  193  
            * @throws InitializationException thrown if anything goes wrong
      +  193   +
            */
       194   -
            */
      +
           @Override
       195   -
           @Override
      -  196  
           public void initializeFileTypeAnalyzer() throws InitializationException {
      -  197   +  196  
               final File tempFile;
      -  198   +  197  
               try {
      -  199  5
                   tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
      -  200  0
               } catch (IOException ex) {
      -  201  0
                   setEnabled(false);
      -  202  0
                   throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex);
      -  203  5
               }
      -  204  5
               FileOutputStream fos = null;
      -  205  5
               InputStream is = null;
      -  206   +  198  5
                   tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
      +  199  0
               } catch (IOException ex) {
      +  200  0
                   setEnabled(false);
      +  201  0
                   throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex);
      +  202  5
               }
      +  203  5
               FileOutputStream fos = null;
      +  204  5
               InputStream is = null;
      +  205  
               try {
      -  207  5
                   fos = new FileOutputStream(tempFile);
      -  208  5
                   is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe");
      -  209  5
                   IOUtils.copy(is, fos);
      -  210   +  206  5
                   fos = new FileOutputStream(tempFile);
      +  207  5
                   is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe");
      +  208  5
                   IOUtils.copy(is, fos);
      +  209  
       
      -  211  5
                   grokAssemblyExe = tempFile;
      -  212  5
                   LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath());
      -  213  0
               } catch (IOException ioe) {
      -  214  0
                   this.setEnabled(false);
      -  215  0
                   LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage());
      -  216  0
                   throw new InitializationException("Could not extract GrokAssembly.exe", ioe);
      -  217   +  210  5
                   grokAssemblyExe = tempFile;
      +  211  5
                   LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath());
      +  212  0
               } catch (IOException ioe) {
      +  213  0
                   this.setEnabled(false);
      +  214  0
                   LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage());
      +  215  0
                   throw new InitializationException("Could not extract GrokAssembly.exe", ioe);
      +  216  
               } finally {
      -  218  5
                   if (fos != null) {
      -  219   +  217  5
                   if (fos != null) {
      +  218  
                       try {
      -  220  5
                           fos.close();
      -  221  0
                       } catch (Throwable e) {
      -  222  0
                           LOGGER.debug("Error closing output stream");
      -  223  5
                       }
      -  224   +  219  5
                           fos.close();
      +  220  0
                       } catch (Throwable e) {
      +  221  0
                           LOGGER.debug("Error closing output stream");
      +  222  5
                       }
      +  223  
                   }
      -  225  5
                   if (is != null) {
      -  226   +  224  5
                   if (is != null) {
      +  225  
                       try {
      -  227  5
                           is.close();
      -  228  0
                       } catch (Throwable e) {
      -  229  0
                           LOGGER.debug("Error closing input stream");
      -  230  5
                       }
      +  226  5
                           is.close();
      +  227  0
                       } catch (Throwable e) {
      +  228  0
                           LOGGER.debug("Error closing input stream");
      +  229  5
                       }
      +  230   +
                   }
       231   -
                   }
      +
               }
       232   -
               }
      +
       
       233   -
       
      -  234  
               // Now, need to see if GrokAssembly actually runs from this location.
      -  235  5
               final List<String> args = buildArgumentList();
      +  234  5
               final List<String> args = buildArgumentList();
      +  235   +
               //TODO this creates an "unreported" error - if someone doesn't look
       236   -
               //TODO this creaes an "unreported" error - if someone doesn't look
      -  237  
               // at the command output this could easily be missed (especially in an
      +  237   +
               // Ant or Maven build.
       238   -
               // Ant or Mmaven build.
      -  239  
               //
      -  240   +  239  
               // We need to create a non-fatal warning error type that will
      -  241   +  240  
               // get added to the report.
      -  242   +  241  
               //TOOD this idea needs to get replicated to the bundle audit analyzer.
      -  243  5
               if (args == null) {
      -  244  0
                   setEnabled(false);
      -  245  0
                   LOGGER.error("----------------------------------------------------");
      -  246  0
                   LOGGER.error(".NET Assembly Analyzer could not be initialized and at least one "
      +  242  5
               if (args == null) {
      +  243  0
                   setEnabled(false);
      +  244  0
                   LOGGER.error("----------------------------------------------------");
      +  245  0
                   LOGGER.error(".NET Assembly Analyzer could not be initialized and at least one "
      +  246   +
                           + "'exe' or 'dll' was scanned. The 'mono' executable could not be found on "
       247   -
                           + "'exe' or 'dll' was scanned. The 'mono' executale could not be found on "
      -  248  
                           + "the path; either disable the Assembly Analyzer or configure the path mono.");
      -  249  0
                   LOGGER.error("----------------------------------------------------");
      -  250  0
                   return;
      -  251   +  248  0
                   LOGGER.error("----------------------------------------------------");
      +  249  0
                   return;
      +  250  
               }
      -  252   +  251  
               try {
      -  253  5
                   final ProcessBuilder pb = new ProcessBuilder(args);
      -  254  5
                   final Process p = pb.start();
      -  255   +  252  5
                   final ProcessBuilder pb = new ProcessBuilder(args);
      +  253  5
                   final Process p = pb.start();
      +  254  
                   // Try evacuating the error stream
      -  256  5
                   IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM);
      -  257   +  255  5
                   IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM);
      +  256  
       
      -  258  5
                   final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream());
      -  259  5
                   final XPath xpath = XPathFactory.newInstance().newXPath();
      -  260  5
                   final String error = xpath.evaluate("/assembly/error", doc);
      -  261  5
                   if (p.waitFor() != 1 || error == null || error.isEmpty()) {
      -  262  0
                       LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details.");
      -  263  0
                       LOGGER.debug("GrokAssembly.exe is not working properly");
      -  264  0
                       grokAssemblyExe = null;
      -  265  0
                       setEnabled(false);
      -  266  0
                       throw new InitializationException("Could not execute .NET AssemblyAnalyzer");
      -  267   +  257  5
                   final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      +  258  5
                   factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +  259  5
                   final DocumentBuilder builder = factory.newDocumentBuilder();
      +  260  5
                   final Document doc = builder.parse(p.getInputStream());
      +  261  5
                   final XPath xpath = XPathFactory.newInstance().newXPath();
      +  262  5
                   final String error = xpath.evaluate("/assembly/error", doc);
      +  263  5
                   if (p.waitFor() != 1 || error == null || error.isEmpty()) {
      +  264  0
                       LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details.");
      +  265  0
                       LOGGER.debug("GrokAssembly.exe is not working properly");
      +  266  0
                       grokAssemblyExe = null;
      +  267  0
                       setEnabled(false);
      +  268  0
                       throw new InitializationException("Could not execute .NET AssemblyAnalyzer");
      +  269  
                   }
      -  268  0
               } catch (InitializationException e) {
      -  269  0
                   setEnabled(false);
      -  270  0
                   throw e;
      -  271  0
               } catch (Throwable e) {
      -  272  0
                   LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
      -  273   +  270  0
               } catch (InitializationException e) {
      +  271  0
                   setEnabled(false);
      +  272  0
                   throw e;
      +  273  0
               } catch (Throwable e) {
      +  274  0
                   LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
      +  275  
                           + "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.");
      -  274  0
                   LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage());
      -  275  0
                   setEnabled(false);
      -  276  0
                   throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e);
      -  277  5
               }
      -  278   -
               try {
      -  279  5
                   builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
      -  280  0
               } catch (ParserConfigurationException ex) {
      -  281  0
                   setEnabled(false);
      -  282  0
                   throw new InitializationException("Error initializing the assembly analyzer", ex);
      -  283  5
               }
      -  284  5
           }
      -  285   +  276  0
                   LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage());
      +  277  0
                   setEnabled(false);
      +  278  0
                   throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e);
      +  279  5
               }
      +  280  5
           }
      +  281  
       
      -  286   +  282  
           /**
      -  287   +  283  
            * Removes resources used from the local file system.
      -  288   +  284  
            *
      -  289   +  285  
            * @throws Exception thrown if there is a problem closing the analyzer
      -  290   +  286  
            */
      -  291   +  287  
           @Override
      -  292   +  288  
           public void close() throws Exception {
      -  293  7
               super.close();
      +  289  7
               super.close();
      +  290   +
               try {
      +  291  7
                   if (grokAssemblyExe != null && !grokAssemblyExe.delete()) {
      +  292  0
                       LOGGER.debug("Unable to delete temporary GrokAssembly.exe; attempting delete on exit");
      +  293  0
                       grokAssemblyExe.deleteOnExit();
       294   -
               try {
      -  295  7
                   if (grokAssemblyExe != null && !grokAssemblyExe.delete()) {
      -  296  0
                       LOGGER.debug("Unable to delete temporary GrokAssembly.exe; attempting delete on exit");
      -  297  0
                       grokAssemblyExe.deleteOnExit();
      -  298  
                   }
      -  299  0
               } catch (SecurityException se) {
      -  300  0
                   LOGGER.debug("Can't delete temporary GrokAssembly.exe");
      -  301  0
                   grokAssemblyExe.deleteOnExit();
      -  302  7
               }
      -  303  7
           }
      -  304   +  295  0
               } catch (SecurityException se) {
      +  296  0
                   LOGGER.debug("Can't delete temporary GrokAssembly.exe");
      +  297  0
                   grokAssemblyExe.deleteOnExit();
      +  298  7
               }
      +  299  7
           }
      +  300  
       
      -  305   +  301  
           /**
      -  306   +  302  
            * The File Filter used to filter supported extensions.
      +  303   +
            */
      +  304  2
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(
      +  305  1
                   SUPPORTED_EXTENSIONS).build();
      +  306   +
       
       307   -
            */
      -  308  2
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(
      -  309  1
                   SUPPORTED_EXTENSIONS).build();
      -  310   -
       
      -  311  
           @Override
      -  312   +  308  
           protected FileFilter getFileFilter() {
      -  313  864
               return FILTER;
      -  314   +  309  867
               return FILTER;
      +  310  
           }
      -  315   +  311  
       
      -  316   +  312  
           /**
      -  317   +  313  
            * Gets this analyzer's name.
      -  318   +  314  
            *
      -  319   +  315  
            * @return the analyzer name
      -  320   +  316  
            */
      -  321   +  317  
           @Override
      -  322   +  318  
           public String getName() {
      -  323  16
               return ANALYZER_NAME;
      -  324   +  319  22
               return ANALYZER_NAME;
      +  320  
           }
      -  325   +  321  
       
      -  326   +  322  
           /**
      -  327   +  323  
            * Returns the phase this analyzer runs under.
      -  328   +  324  
            *
      -  329   +  325  
            * @return the phase this runs under
      -  330   +  326  
            */
      -  331   +  327  
           @Override
      -  332   +  328  
           public AnalysisPhase getAnalysisPhase() {
      -  333  4
               return ANALYSIS_PHASE;
      -  334   +  329  6
               return ANALYSIS_PHASE;
      +  330  
           }
      -  335   +  331  
       
      -  336   +  332  
           /**
      -  337   +  333  
            * Returns the key used in the properties file to reference the analyzer's
      -  338   +  334  
            * enabled property.
      -  339   +  335  
            *
      -  340   +  336  
            * @return the analyzer's enabled property setting key
      -  341   +  337  
            */
      -  342   +  338  
           @Override
      -  343   +  339  
           protected String getAnalyzerEnabledSettingKey() {
      -  344  11
               return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED;
      -  345   +  340  13
               return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED;
      +  341  
           }
      -  346   +  342  
       
      -  347   +  343  
           /**
      -  348   +  344  
            * Tests to see if a file is in the system path. <b>Note</b> - the current
      -  349   +  345  
            * implementation only works on non-windows platforms. For purposes of the
      -  350   +  346  
            * AssemblyAnalyzer this is okay as this is only needed on Mac/*nix.
      -  351   +  347  
            *
      -  352   +  348  
            * @param file the executable to look for
      -  353   +  349  
            * @return <code>true</code> if the file exists; otherwise
      -  354   +  350  
            * <code>false</code>
      -  355   +  351  
            */
      -  356   +  352  
           private boolean isInPath(String file) {
      -  357  0
               final ProcessBuilder pb = new ProcessBuilder("which", file);
      -  358   +  353  0
               final ProcessBuilder pb = new ProcessBuilder("which", file);
      +  354  
               try {
      -  359  0
                   final Process proc = pb.start();
      -  360  0
                   final int retCode = proc.waitFor();
      -  361  0
                   if (retCode == 0) {
      -  362  0
                       return true;
      -  363   +  355  0
                   final Process proc = pb.start();
      +  356  0
                   final int retCode = proc.waitFor();
      +  357  0
                   if (retCode == 0) {
      +  358  0
                       return true;
      +  359  
                   }
      -  364  0
               } catch (IOException ex) {
      -  365  0
                   LOGGER.debug("Path seach failed for " + file);
      -  366  0
               } catch (InterruptedException ex) {
      -  367  0
                   LOGGER.debug("Path seach failed for " + file);
      -  368  0
               }
      -  369  0
               return false;
      -  370   +  360  0
               } catch (IOException ex) {
      +  361  0
                   LOGGER.debug("Path seach failed for " + file);
      +  362  0
               } catch (InterruptedException ex) {
      +  363  0
                   LOGGER.debug("Path seach failed for " + file);
      +  364  0
               }
      +  365  0
               return false;
      +  366  
           }
      -  371   +  367  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AutoconfAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AutoconfAnalyzer.html index e63c62d14..330847119 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AutoconfAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.AutoconfAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      AutoconfAnalyzer
      90%
      64/71
      76%
      26/34
      3.222
      AutoconfAnalyzer
      94%
      64/68
      76%
      26/34
      3.222
       
      @@ -84,438 +84,429 @@  33  
       import java.nio.charset.Charset;
       34   -
       import java.util.ArrayList;
      -  35   -
       import java.util.List;
      -  36  
       import java.util.regex.Matcher;
      -  37   +  35  
       import java.util.regex.Pattern;
      -  38   +  36  
       import org.owasp.dependencycheck.exception.InitializationException;
      -  39   +  37  
       
      -  40   +  38  
       /**
      -  41   +  39  
        * Used to analyze Autoconf input files named configure.ac or configure.in.
      -  42   +  40  
        * Files simply named "configure" are also analyzed, assuming they are generated
      -  43   +  41  
        * by Autoconf, and contain certain special package descriptor variables.
      -  44   +  42  
        *
      -  45   +  43  
        * @author Dale Visser
      -  46   +  44  
        * @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project
      -  47   +  45  
        * - Free Software Foundation (FSF)</a>
      -  48   +  46  
        */
      -  49   +  47  
       @Experimental
      -  50  12
       public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
      +  48  14
       public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
      +  49   +
       
      +  50   +
           /**
       51   -
       
      -  52   -
           /**
      -  53  
            * Autoconf output filename.
      -  54   +  52  
            */
      -  55   +  53  
           private static final String CONFIGURE = "configure";
      +  54   +
       
      +  55   +
           /**
       56   -
       
      +
            * Autoconf input filename.
       57   -
           /**
      +
            */
       58   -
            * Autoconf input filename.
      -  59   -
            */
      -  60  
           private static final String CONFIGURE_IN = "configure.in";
      +  59   +
       
      +  60   +
           /**
       61   -
       
      -  62   -
           /**
      -  63  
            * Autoconf input filename.
      -  64   +  62  
            */
      -  65   +  63  
           private static final String CONFIGURE_AC = "configure.ac";
      +  64   +
       
      +  65   +
           /**
       66   -
       
      -  67   -
           /**
      -  68  
            * The name of the analyzer.
      -  69   +  67  
            */
      -  70   +  68  
           private static final String ANALYZER_NAME = "Autoconf Analyzer";
      +  69   +
       
      +  70   +
           /**
       71   -
       
      -  72   -
           /**
      -  73  
            * The phase that this analyzer is intended to run in.
      +  72   +
            */
      +  73  1
           private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
       74   -
            */
      -  75  1
           private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
      +
       
      +  75   +
           /**
       76   -
       
      -  77   -
           /**
      -  78  
            * The set of file extensions supported by this analyzer.
      +  77   +
            */
      +  78  1
           private static final String[] EXTENSIONS = {"ac", "in"};
       79   -
            */
      -  80  1
           private static final String[] EXTENSIONS = {"ac", "in"};
      +
       
      +  80   +
           /**
       81   -
       
      -  82   -
           /**
      -  83  
            * Matches AC_INIT variables in the output configure script.
      +  82   +
            */
      +  83  1
           private static final Pattern PACKAGE_VAR = Pattern.compile(
       84   -
            */
      -  85  1
           private static final Pattern PACKAGE_VAR = Pattern.compile(
      -  86  
                   "PACKAGE_(.+?)='(.*?)'", Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
      +  85   +
       
      +  86   +
           /**
       87   -
       
      -  88   -
           /**
      -  89  
            * Matches AC_INIT statement in configure.ac file.
      -  90   +  88  
            */
      -  91   +  89  
           private static final Pattern AC_INIT_PATTERN;
      -  92   +  90  
       
      -  93   +  91  
           static {
      -  94   +  92  
               // each instance of param or sep_param has a capture group
      -  95  1
               final String param = "\\[{0,2}(.+?)\\]{0,2}";
      -  96  1
               final String sepParam = "\\s*,\\s*" + param;
      -  97   +  93  1
               final String param = "\\[{0,2}(.+?)\\]{0,2}";
      +  94  1
               final String sepParam = "\\s*,\\s*" + param;
      +  95  
               // Group 1: Package
      -  98   +  96  
               // Group 2: Version
      -  99   +  97  
               // Group 3: optional
      -  100   +  98  
               // Group 4: Bug report address (if it exists)
      -  101   +  99  
               // Group 5: optional
      -  102   +  100  
               // Group 6: Tarname (if it exists)
      -  103   +  101  
               // Group 7: optional
      -  104   +  102  
               // Group 8: URL (if it exists)
      -  105  1
               AC_INIT_PATTERN = Pattern.compile(String.format(
      -  106   +  103  1
               AC_INIT_PATTERN = Pattern.compile(String.format(
      +  104  
                       "AC_INIT\\(%s%s(%s)?(%s)?(%s)?\\s*\\)", param, sepParam,
      -  107   +  105  
                       sepParam, sepParam, sepParam), Pattern.DOTALL
      -  108   +  106  
                       | Pattern.CASE_INSENSITIVE);
      +  107   +
           }
      +  108   +
       
       109   -
           }
      +
           /**
       110   -
       
      -  111   -
           /**
      -  112  
            * The file filter used to determine which files this analyzer supports.
      -  113   +  111  
            */
      -  114  2
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(CONFIGURE).addExtensions(
      -  115  1
                   EXTENSIONS).build();
      +  112  2
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(CONFIGURE).addExtensions(
      +  113  1
                   EXTENSIONS).build();
      +  114   +
       
      +  115   +
           /**
       116   -
       
      -  117   -
           /**
      -  118  
            * Returns the FileFilter
      -  119   +  117  
            *
      -  120   +  118  
            * @return the FileFilter
      +  119   +
            */
      +  120   +
           @Override
       121   -
            */
      -  122   -
           @Override
      -  123  
           protected FileFilter getFileFilter() {
      -  124  862
               return FILTER;
      +  122  865
               return FILTER;
      +  123   +
           }
      +  124   +
       
       125   -
           }
      +
           /**
       126   -
       
      -  127   -
           /**
      -  128  
            * Returns the name of the analyzer.
      -  129   +  127  
            *
      -  130   +  128  
            * @return the name of the analyzer.
      +  129   +
            */
      +  130   +
           @Override
       131   -
            */
      -  132   -
           @Override
      -  133  
           public String getName() {
      -  134  15
               return ANALYZER_NAME;
      +  132  21
               return ANALYZER_NAME;
      +  133   +
           }
      +  134   +
       
       135   -
           }
      +
           /**
       136   -
       
      -  137   -
           /**
      -  138  
            * Returns the phase that the analyzer is intended to run in.
      -  139   +  137  
            *
      -  140   +  138  
            * @return the phase that the analyzer is intended to run in.
      +  139   +
            */
      +  140   +
           @Override
       141   -
            */
      -  142   -
           @Override
      -  143  
           public AnalysisPhase getAnalysisPhase() {
      -  144  4
               return ANALYSIS_PHASE;
      +  142  6
               return ANALYSIS_PHASE;
      +  143   +
           }
      +  144   +
       
       145   -
           }
      +
           /**
       146   -
       
      -  147   -
           /**
      -  148  
            * Returns the key used in the properties file to reference the analyzer's
      -  149   +  147  
            * enabled property.
      -  150   +  148  
            *
      -  151   +  149  
            * @return the analyzer's enabled property setting key
      +  150   +
            */
      +  151   +
           @Override
       152   -
            */
      -  153   -
           @Override
      -  154  
           protected String getAnalyzerEnabledSettingKey() {
      -  155  12
               return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED;
      +  153  14
               return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED;
      +  154   +
           }
      +  155   +
       
       156   -
           }
      +
           @Override
       157   -
       
      -  158   -
           @Override
      -  159  
           protected void analyzeFileType(Dependency dependency, Engine engine)
      -  160   +  158  
                   throws AnalysisException {
      -  161  4
               final File actualFile = dependency.getActualFile();
      -  162  4
               final String name = actualFile.getName();
      -  163  4
               if (name.startsWith(CONFIGURE)) {
      -  164  4
                   final File parent = actualFile.getParentFile();
      -  165  4
                   final String parentName = parent.getName();
      -  166  4
                   dependency.setDisplayFileName(parentName + "/" + name);
      -  167  4
                   final boolean isOutputScript = CONFIGURE.equals(name);
      -  168  4
                   if (isOutputScript || CONFIGURE_AC.equals(name)
      -  169  0
                           || CONFIGURE_IN.equals(name)) {
      -  170  4
                       final String contents = getFileContents(actualFile);
      -  171  4
                       if (!contents.isEmpty()) {
      -  172  4
                           if (isOutputScript) {
      -  173  2
                               extractConfigureScriptEvidence(dependency, name,
      -  174   +  159  4
               final File actualFile = dependency.getActualFile();
      +  160  4
               final String name = actualFile.getName();
      +  161  4
               if (name.startsWith(CONFIGURE)) {
      +  162  4
                   final File parent = actualFile.getParentFile();
      +  163  4
                   final String parentName = parent.getName();
      +  164  4
                   dependency.setDisplayFileName(parentName + "/" + name);
      +  165  4
                   final boolean isOutputScript = CONFIGURE.equals(name);
      +  166  4
                   if (isOutputScript || CONFIGURE_AC.equals(name)
      +  167  0
                           || CONFIGURE_IN.equals(name)) {
      +  168  4
                       final String contents = getFileContents(actualFile);
      +  169  4
                       if (!contents.isEmpty()) {
      +  170  4
                           if (isOutputScript) {
      +  171  2
                               extractConfigureScriptEvidence(dependency, name,
      +  172  
                                       contents);
      -  175   +  173  
                           } else {
      -  176  2
                               gatherEvidence(dependency, name, contents);
      -  177   +  174  2
                               gatherEvidence(dependency, name, contents);
      +  175  
                           }
      -  178   +  176  
                       }
      -  179   +  177  
                   }
      -  180  4
               } else {
      -  181   -
                   // copy, alter and set in case some other thread is iterating over
      -  182  0
                   final List<Dependency> dependencies = new ArrayList<Dependency>(
      -  183  0
                           engine.getDependencies());
      -  184  0
                   dependencies.remove(dependency);
      -  185  0
                   engine.setDependencies(dependencies);
      -  186   +  178  4
               } else {
      +  179  0
                   engine.getDependencies().remove(dependency);
      +  180  
               }
      -  187  4
           }
      -  188   +  181  4
           }
      +  182  
       
      -  189   +  183  
           /**
      -  190   +  184  
            * Extracts evidence from the configuration.
      -  191   +  185  
            *
      -  192   +  186  
            * @param dependency the dependency being analyzed
      -  193   +  187  
            * @param name the name of the source of evidence
      -  194   +  188  
            * @param contents the contents to analyze for evidence
      -  195   +  189  
            */
      -  196   +  190  
           private void extractConfigureScriptEvidence(Dependency dependency,
      -  197   +  191  
                   final String name, final String contents) {
      -  198  2
               final Matcher matcher = PACKAGE_VAR.matcher(contents);
      -  199  20
               while (matcher.find()) {
      -  200  18
                   final String variable = matcher.group(1);
      -  201  18
                   final String value = matcher.group(2);
      -  202  18
                   if (!value.isEmpty()) {
      -  203  14
                       if (variable.endsWith("NAME")) {
      -  204  4
                           dependency.getProductEvidence().addEvidence(name, variable,
      +  192  2
               final Matcher matcher = PACKAGE_VAR.matcher(contents);
      +  193  20
               while (matcher.find()) {
      +  194  18
                   final String variable = matcher.group(1);
      +  195  18
                   final String value = matcher.group(2);
      +  196  18
                   if (!value.isEmpty()) {
      +  197  14
                       if (variable.endsWith("NAME")) {
      +  198  4
                           dependency.getProductEvidence().addEvidence(name, variable,
      +  199   +
                                   value, Confidence.HIGHEST);
      +  200  10
                       } else if ("VERSION".equals(variable)) {
      +  201  2
                           dependency.getVersionEvidence().addEvidence(name, variable,
      +  202   +
                                   value, Confidence.HIGHEST);
      +  203  8
                       } else if ("BUGREPORT".equals(variable)) {
      +  204  1
                           dependency.getVendorEvidence().addEvidence(name, variable,
       205   -
                                   value, Confidence.HIGHEST);
      -  206  10
                       } else if ("VERSION".equals(variable)) {
      -  207  2
                           dependency.getVersionEvidence().addEvidence(name, variable,
      +
                                   value, Confidence.HIGH);
      +  206  7
                       } else if ("URL".equals(variable)) {
      +  207  1
                           dependency.getVendorEvidence().addEvidence(name, variable,
       208   -
                                   value, Confidence.HIGHEST);
      -  209  8
                       } else if ("BUGREPORT".equals(variable)) {
      -  210  1
                           dependency.getVendorEvidence().addEvidence(name, variable,
      -  211  
                                   value, Confidence.HIGH);
      -  212  7
                       } else if ("URL".equals(variable)) {
      -  213  1
                           dependency.getVendorEvidence().addEvidence(name, variable,
      +  209   +
                       }
      +  210   +
                   }
      +  211  18
               }
      +  212  2
           }
      +  213   +
       
       214   -
                                   value, Confidence.HIGH);
      +
           /**
       215   -
                       }
      -  216   -
                   }
      -  217  18
               }
      -  218  2
           }
      -  219   -
       
      -  220   -
           /**
      -  221  
            * Retrieves the contents of a given file.
      -  222   +  216  
            *
      -  223   +  217  
            * @param actualFile the file to read
      -  224   +  218  
            * @return the contents of the file
      -  225   +  219  
            * @throws AnalysisException thrown if there is an IO Exception
      -  226   +  220  
            */
      -  227   +  221  
           private String getFileContents(final File actualFile)
      -  228   +  222  
                   throws AnalysisException {
      -  229   +  223  
               try {
      -  230  4
                   return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
      -  231  0
               } catch (IOException e) {
      -  232  0
                   throw new AnalysisException(
      -  233   +  224  4
                   return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
      +  225  0
               } catch (IOException e) {
      +  226  0
                   throw new AnalysisException(
      +  227  
                           "Problem occurred while reading dependency file.", e);
      -  234   +  228  
               }
      -  235   +  229  
           }
      -  236   +  230  
       
      -  237   +  231  
           /**
      -  238   +  232  
            * Gathers evidence from a given file
      -  239   +  233  
            *
      -  240   +  234  
            * @param dependency the dependency to add evidence to
      -  241   +  235  
            * @param name the source of the evidence
      -  242   +  236  
            * @param contents the evidence to analyze
      -  243   +  237  
            */
      -  244   +  238  
           private void gatherEvidence(Dependency dependency, final String name,
      -  245   +  239  
                   String contents) {
      -  246  2
               final Matcher matcher = AC_INIT_PATTERN.matcher(contents);
      -  247  2
               if (matcher.find()) {
      -  248  2
                   final EvidenceCollection productEvidence = dependency
      -  249  2
                           .getProductEvidence();
      -  250  2
                   productEvidence.addEvidence(name, "Package", matcher.group(1),
      -  251   +  240  2
               final Matcher matcher = AC_INIT_PATTERN.matcher(contents);
      +  241  2
               if (matcher.find()) {
      +  242  2
                   final EvidenceCollection productEvidence = dependency
      +  243  2
                           .getProductEvidence();
      +  244  2
                   productEvidence.addEvidence(name, "Package", matcher.group(1),
      +  245  
                           Confidence.HIGHEST);
      -  252  4
                   dependency.getVersionEvidence().addEvidence(name,
      -  253  2
                           "Package Version", matcher.group(2), Confidence.HIGHEST);
      -  254  2
                   final EvidenceCollection vendorEvidence = dependency
      -  255  2
                           .getVendorEvidence();
      -  256  2
                   if (null != matcher.group(3)) {
      -  257  4
                       vendorEvidence.addEvidence(name, "Bug report address",
      -  258  2
                               matcher.group(4), Confidence.HIGH);
      -  259   +  246  4
                   dependency.getVersionEvidence().addEvidence(name,
      +  247  2
                           "Package Version", matcher.group(2), Confidence.HIGHEST);
      +  248  2
                   final EvidenceCollection vendorEvidence = dependency
      +  249  2
                           .getVendorEvidence();
      +  250  2
                   if (null != matcher.group(3)) {
      +  251  4
                       vendorEvidence.addEvidence(name, "Bug report address",
      +  252  2
                               matcher.group(4), Confidence.HIGH);
      +  253  
                   }
      -  260  2
                   if (null != matcher.group(5)) {
      -  261  1
                       productEvidence.addEvidence(name, "Tarname", matcher.group(6),
      -  262   +  254  2
                   if (null != matcher.group(5)) {
      +  255  1
                       productEvidence.addEvidence(name, "Tarname", matcher.group(6),
      +  256  
                               Confidence.HIGH);
      -  263   +  257  
                   }
      -  264  2
                   if (null != matcher.group(7)) {
      -  265  1
                       final String url = matcher.group(8);
      -  266  1
                       if (UrlStringUtils.isUrl(url)) {
      -  267  1
                           vendorEvidence.addEvidence(name, "URL", url,
      -  268   +  258  2
                   if (null != matcher.group(7)) {
      +  259  1
                       final String url = matcher.group(8);
      +  260  1
                       if (UrlStringUtils.isUrl(url)) {
      +  261  1
                           vendorEvidence.addEvidence(name, "URL", url,
      +  262  
                                   Confidence.HIGH);
      -  269   +  263  
                       }
      -  270   +  264  
                   }
      -  271   +  265  
               }
      -  272  2
           }
      -  273   +  266  2
           }
      +  267  
       
      -  274   +  268  
           /**
      -  275   +  269  
            * Initializes the file type analyzer.
      -  276   +  270  
            *
      -  277   +  271  
            * @throws InitializationException thrown if there is an exception during
      -  278   +  272  
            * initialization
      -  279   +  273  
            */
      -  280   +  274  
           @Override
      -  281   +  275  
           protected void initializeFileTypeAnalyzer() throws InitializationException {
      -  282   +  276  
               // No initialization needed.
      -  283  6
           }
      -  284   +  277  6
           }
      +  278  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CMakeAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CMakeAnalyzer.html index 94f697257..d76b99c63 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CMakeAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CMakeAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      CMakeAnalyzer
      91%
      65/71
      80%
      8/10
      2.143
      CMakeAnalyzer
      94%
      71/75
      80%
      8/10
      2.625
       
      @@ -131,7 +131,7 @@
        */
       57  
       @Experimental
      -  58  11
       public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
      +  58  15
       public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
       59  
       
       60   @@ -194,256 +194,266 @@
            * Detects files that can be analyzed.
       91  
            */
      -  92  1
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(".cmake")
      +  92  2
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(".cmake")
       93  1
                   .addFilenames("CMakeLists.txt").build();
       94  
       
       95  
           /**
       96   -
            * A reference to SHA1 message digest.
      -  97   -
            */
      -  98  1
           private static MessageDigest sha1 = null;
      -  99   -
       
      -  100   -
           static {
      -  101   -
               try {
      -  102  1
                   sha1 = MessageDigest.getInstance("SHA1");
      -  103  0
               } catch (NoSuchAlgorithmException e) {
      -  104  0
                   LOGGER.error(e.getMessage());
      -  105  1
               }
      -  106  1
           }
      -  107   -
       
      -  108   -
           /**
      -  109  
            * Returns the name of the CMake analyzer.
      -  110   +  97  
            *
      -  111   +  98  
            * @return the name of the analyzer
      -  112   -
            *
      -  113   +  99  
            */
      -  114   +  100  
           @Override
      -  115   +  101  
           public String getName() {
      -  116  15
               return "CMake Analyzer";
      -  117   +  102  21
               return "CMake Analyzer";
      +  103  
           }
      -  118   +  104  
       
      -  119   +  105  
           /**
      -  120   +  106  
            * Tell that we are used for information collection.
      -  121   +  107  
            *
      -  122   +  108  
            * @return INFORMATION_COLLECTION
      -  123   +  109  
            */
      -  124   +  110  
           @Override
      -  125   +  111  
           public AnalysisPhase getAnalysisPhase() {
      -  126  4
               return AnalysisPhase.INFORMATION_COLLECTION;
      -  127   +  112  6
               return AnalysisPhase.INFORMATION_COLLECTION;
      +  113  
           }
      -  128   +  114  
       
      -  129   +  115  
           /**
      -  130   +  116  
            * Returns the set of supported file extensions.
      -  131   +  117  
            *
      -  132   +  118  
            * @return the set of supported file extensions
      -  133   +  119  
            */
      -  134   +  120  
           @Override
      -  135   +  121  
           protected FileFilter getFileFilter() {
      -  136  861
               return FILTER;
      -  137   +  122  864
               return FILTER;
      +  123  
           }
      -  138   +  124  
       
      -  139   +  125  
           /**
      -  140   -
            * No-op initializer implementation.
      -  141   +  126   +
            * Initializes the analyzer.
      +  127  
            *
      -  142   -
            * @throws InitializationException never thrown
      -  143   +  128   +
            * @throws InitializationException thrown if an exception occurs getting an
      +  129   +
            * instance of SHA1
      +  130  
            */
      -  144   +  131  
           @Override
      -  145   +  132  
           protected void initializeFileTypeAnalyzer() throws InitializationException {
      -  146   -
               // Nothing to do here.
      -  147  5
           }
      -  148   -
       
      -  149   -
           /**
      -  150   -
            * Analyzes python packages and adds evidence to the dependency.
      -  151   -
            *
      -  152   -
            * @param dependency the dependency being analyzed
      -  153   -
            * @param engine the engine being used to perform the scan
      -  154   -
            * @throws AnalysisException thrown if there is an unrecoverable error
      -  155   -
            * analyzing the dependency
      -  156   -
            */
      -  157   -
           @Override
      -  158   -
           protected void analyzeFileType(Dependency dependency, Engine engine)
      -  159   -
                   throws AnalysisException {
      -  160  3
               final File file = dependency.getActualFile();
      -  161  3
               final String parentName = file.getParentFile().getName();
      -  162  3
               final String name = file.getName();
      -  163  3
               dependency.setDisplayFileName(String.format("%s%c%s", parentName, File.separatorChar, name));
      -  164   -
               String contents;
      -  165   +  133  
               try {
      -  166  3
                   contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
      -  167  0
               } catch (IOException e) {
      -  168  0
                   throw new AnalysisException(
      -  169   -
                           "Problem occurred while reading dependency file.", e);
      -  170  3
               }
      -  171   +  134  7
                   getSha1MessageDigest();
      +  135  1
               } catch (IllegalStateException ex) {
      +  136  1
                   setEnabled(false);
      +  137  1
                   throw new InitializationException("Unable to create SHA1 MessageDigest", ex);
      +  138  6
               }
      +  139  6
           }
      +  140  
       
      -  172  3
               if (StringUtils.isNotBlank(contents)) {
      -  173  3
                   final Matcher m = PROJECT.matcher(contents);
      -  174  3
                   int count = 0;
      -  175  5
                   while (m.find()) {
      -  176  2
                       count++;
      -  177  4
                       LOGGER.debug(String.format(
      -  178   -
                               "Found project command match with %d groups: %s",
      -  179  2
                               m.groupCount(), m.group(0)));
      -  180  2
                       final String group = m.group(1);
      -  181  2
                       LOGGER.debug("Group 1: " + group);
      -  182  2
                       dependency.getProductEvidence().addEvidence(name, "Project",
      -  183   -
                               group, Confidence.HIGH);
      -  184  2
                   }
      -  185  3
                   LOGGER.debug("Found {} matches.", count);
      -  186  3
                   analyzeSetVersionCommand(dependency, engine, contents);
      -  187   -
               }
      -  188  3
           }
      -  189   -
       
      -  190   +  141  
           /**
      -  191   -
            * Extracts the version information from the contents. If more then one
      -  192   -
            * version is found additional dependencies are added to the dependency
      -  193   -
            * list.
      -  194   +  142   +
            * Analyzes python packages and adds evidence to the dependency.
      +  143  
            *
      -  195   +  144  
            * @param dependency the dependency being analyzed
      -  196   -
            * @param engine the dependency-check engine
      -  197   -
            * @param contents the version information
      -  198   +  145   +
            * @param engine the engine being used to perform the scan
      +  146   +
            * @throws AnalysisException thrown if there is an unrecoverable error
      +  147   +
            * analyzing the dependency
      +  148  
            */
      -  199   -
           @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
      -  200   -
                   value = "DM_DEFAULT_ENCODING",
      -  201   -
                   justification = "Default encoding is only used if UTF-8 is not available")
      -  202   -
           private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) {
      -  203  3
               Dependency currentDep = dependency;
      -  204   -
       
      -  205  3
               final Matcher m = SET_VERSION.matcher(contents);
      -  206  3
               int count = 0;
      -  207  8
               while (m.find()) {
      -  208  5
                   count++;
      -  209  10
                   LOGGER.debug("Found project command match with {} groups: {}",
      -  210  5
                           m.groupCount(), m.group(0));
      -  211  5
                   String product = m.group(1);
      -  212  5
                   final String version = m.group(2);
      -  213  5
                   LOGGER.debug("Group 1: " + product);
      -  214  5
                   LOGGER.debug("Group 2: " + version);
      -  215  5
                   final String aliasPrefix = "ALIASOF_";
      -  216  5
                   if (product.startsWith(aliasPrefix)) {
      -  217  5
                       product = product.replaceFirst(aliasPrefix, "");
      -  218   -
                   }
      -  219  5
                   if (count > 1) {
      -  220   -
                       //TODO - refactor so we do not assign to the parameter (checkstyle)
      -  221  4
                       currentDep = new Dependency(dependency.getActualFile());
      -  222  4
                       currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product));
      -  223  4
                       final String filePath = String.format("%s:%s", dependency.getFilePath(), product);
      -  224  4
                       currentDep.setFilePath(filePath);
      -  225   -
       
      -  226   -
                       byte[] path;
      -  227   -
                       try {
      -  228  4
                           path = filePath.getBytes("UTF-8");
      -  229  0
                       } catch (UnsupportedEncodingException ex) {
      -  230  0
                           path = filePath.getBytes();
      -  231  4
                       }
      -  232  4
                       currentDep.setSha1sum(Checksum.getHex(sha1.digest(path)));
      -  233  4
                       engine.getDependencies().add(currentDep);
      -  234   -
                   }
      -  235  5
                   final String source = currentDep.getDisplayFileName();
      -  236  5
                   currentDep.getProductEvidence().addEvidence(source, "Product",
      -  237   -
                           product, Confidence.MEDIUM);
      -  238  5
                   currentDep.getVersionEvidence().addEvidence(source, "Version",
      -  239   -
                           version, Confidence.MEDIUM);
      -  240  5
               }
      -  241  3
               LOGGER.debug(String.format("Found %d matches.", count));
      -  242  3
           }
      -  243   -
       
      -  244   +  149  
           @Override
      -  245   +  150   +
           protected void analyzeFileType(Dependency dependency, Engine engine)
      +  151   +
                   throws AnalysisException {
      +  152  3
               final File file = dependency.getActualFile();
      +  153  3
               final String parentName = file.getParentFile().getName();
      +  154  3
               final String name = file.getName();
      +  155  3
               dependency.setDisplayFileName(String.format("%s%c%s", parentName, File.separatorChar, name));
      +  156   +
               String contents;
      +  157   +
               try {
      +  158  3
                   contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
      +  159  0
               } catch (IOException e) {
      +  160  0
                   throw new AnalysisException(
      +  161   +
                           "Problem occurred while reading dependency file.", e);
      +  162  3
               }
      +  163   +
       
      +  164  3
               if (StringUtils.isNotBlank(contents)) {
      +  165  3
                   final Matcher m = PROJECT.matcher(contents);
      +  166  3
                   int count = 0;
      +  167  5
                   while (m.find()) {
      +  168  2
                       count++;
      +  169  4
                       LOGGER.debug(String.format(
      +  170   +
                               "Found project command match with %d groups: %s",
      +  171  2
                               m.groupCount(), m.group(0)));
      +  172  2
                       final String group = m.group(1);
      +  173  2
                       LOGGER.debug("Group 1: " + group);
      +  174  2
                       dependency.getProductEvidence().addEvidence(name, "Project",
      +  175   +
                               group, Confidence.HIGH);
      +  176  2
                   }
      +  177  3
                   LOGGER.debug("Found {} matches.", count);
      +  178  3
                   analyzeSetVersionCommand(dependency, engine, contents);
      +  179   +
               }
      +  180  3
           }
      +  181   +
       
      +  182   +
           /**
      +  183   +
            * Extracts the version information from the contents. If more then one
      +  184   +
            * version is found additional dependencies are added to the dependency
      +  185   +
            * list.
      +  186   +
            *
      +  187   +
            * @param dependency the dependency being analyzed
      +  188   +
            * @param engine the dependency-check engine
      +  189   +
            * @param contents the version information
      +  190   +
            */
      +  191   +
           @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
      +  192   +
                   value = "DM_DEFAULT_ENCODING",
      +  193   +
                   justification = "Default encoding is only used if UTF-8 is not available")
      +  194   +
           private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) {
      +  195  3
               Dependency currentDep = dependency;
      +  196   +
       
      +  197  3
               final Matcher m = SET_VERSION.matcher(contents);
      +  198  3
               int count = 0;
      +  199  8
               while (m.find()) {
      +  200  5
                   count++;
      +  201  10
                   LOGGER.debug("Found project command match with {} groups: {}",
      +  202  5
                           m.groupCount(), m.group(0));
      +  203  5
                   String product = m.group(1);
      +  204  5
                   final String version = m.group(2);
      +  205  5
                   LOGGER.debug("Group 1: " + product);
      +  206  5
                   LOGGER.debug("Group 2: " + version);
      +  207  5
                   final String aliasPrefix = "ALIASOF_";
      +  208  5
                   if (product.startsWith(aliasPrefix)) {
      +  209  5
                       product = product.replaceFirst(aliasPrefix, "");
      +  210   +
                   }
      +  211  5
                   if (count > 1) {
      +  212   +
                       //TODO - refactor so we do not assign to the parameter (checkstyle)
      +  213  4
                       currentDep = new Dependency(dependency.getActualFile());
      +  214  4
                       currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product));
      +  215  4
                       final String filePath = String.format("%s:%s", dependency.getFilePath(), product);
      +  216  4
                       currentDep.setFilePath(filePath);
      +  217   +
       
      +  218   +
                       byte[] path;
      +  219   +
                       try {
      +  220  4
                           path = filePath.getBytes("UTF-8");
      +  221  0
                       } catch (UnsupportedEncodingException ex) {
      +  222  0
                           path = filePath.getBytes();
      +  223  4
                       }
      +  224  4
                       final MessageDigest sha1 = getSha1MessageDigest();
      +  225  4
                       currentDep.setSha1sum(Checksum.getHex(sha1.digest(path)));
      +  226  4
                       engine.getDependencies().add(currentDep);
      +  227   +
                   }
      +  228  5
                   final String source = currentDep.getDisplayFileName();
      +  229  5
                   currentDep.getProductEvidence().addEvidence(source, "Product",
      +  230   +
                           product, Confidence.MEDIUM);
      +  231  5
                   currentDep.getVersionEvidence().addEvidence(source, "Version",
      +  232   +
                           version, Confidence.MEDIUM);
      +  233  5
               }
      +  234  3
               LOGGER.debug(String.format("Found %d matches.", count));
      +  235  3
           }
      +  236   +
       
      +  237   +
           @Override
      +  238  
           protected String getAnalyzerEnabledSettingKey() {
      -  246  11
               return Settings.KEYS.ANALYZER_CMAKE_ENABLED;
      -  247   +  239  15
               return Settings.KEYS.ANALYZER_CMAKE_ENABLED;
      +  240  
           }
      +  241   +
       
      +  242   +
           /**
      +  243   +
            * Returns the sha1 message digest.
      +  244   +
            *
      +  245   +
            * @return the sha1 message digest
      +  246   +
            */
      +  247   +
           private MessageDigest getSha1MessageDigest() {
       248   +
               try {
      +  249  11
                   return MessageDigest.getInstance("SHA1");
      +  250  1
               } catch (NoSuchAlgorithmException e) {
      +  251  1
                   LOGGER.error(e.getMessage());
      +  252  1
                   throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e);
      +  253   +
               }
      +  254   +
           }
      +  255  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CPEAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CPEAnalyzer.html index 9f62c32ee..a7966a866 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CPEAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CPEAnalyzer.html @@ -12,7 +12,7 @@
       
      - + @@ -74,1317 +74,1319 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - - - + - + - + + + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - - - + - - - - - - - - - - - - - - - - - - + - + - - - + + + - - - - - + + + - + - - - - - - - - - - - - - - + + + + + + - + - - - + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + + + + + - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - + + - - - - - - - + + + + + + - + - + - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - + - + - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - + + + + + - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Classes in this File Line Coverage Branch Coverage Complexity
      CPEAnalyzer
      80%
      191/238
      76%
      103/134
      4.679
      CPEAnalyzer
      80%
      191/238
      76%
      102/134
      4.679
      CPEAnalyzer$IdentifierConfidence
      100%
      4/4
      N/A
      4.679
      CPEAnalyzer$IdentifierMatch
      36%
      14/38
      0%
      0/20
      4.679
       27  
       import java.util.StringTokenizer;
       28  
       import org.apache.commons.lang3.builder.CompareToBuilder;
       import java.util.concurrent.TimeUnit;
       29  
       import org.apache.lucene.document.Document;
       import org.apache.commons.lang3.builder.CompareToBuilder;
       30  
       import org.apache.lucene.index.CorruptIndexException;
       import org.apache.lucene.document.Document;
       31  
       import org.apache.lucene.queryparser.classic.ParseException;
       import org.apache.lucene.index.CorruptIndexException;
       32  
       import org.apache.lucene.search.ScoreDoc;
       import org.apache.lucene.queryparser.classic.ParseException;
       33  
       import org.apache.lucene.search.TopDocs;
       import org.apache.lucene.search.ScoreDoc;
       34  
       import org.owasp.dependencycheck.Engine;
       import org.apache.lucene.search.TopDocs;
       35  
       import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
       import org.owasp.dependencycheck.Engine;
       36  
       import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex;
       import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
       37  
       import org.owasp.dependencycheck.data.cpe.Fields;
       import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex;
       38  
       import org.owasp.dependencycheck.data.cpe.IndexEntry;
       import org.owasp.dependencycheck.data.cpe.Fields;
       39  
       import org.owasp.dependencycheck.data.cpe.IndexException;
       import org.owasp.dependencycheck.data.cpe.IndexEntry;
       40  
       import org.owasp.dependencycheck.data.lucene.LuceneUtils;
       import org.owasp.dependencycheck.data.cpe.IndexException;
       41  
       import org.owasp.dependencycheck.data.nvdcve.CveDB;
       import org.owasp.dependencycheck.data.lucene.LuceneUtils;
       42  
       import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
       import org.owasp.dependencycheck.data.nvdcve.CveDB;
       43  
       import org.owasp.dependencycheck.dependency.Confidence;
       import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
       44  
       import org.owasp.dependencycheck.dependency.Dependency;
       import org.owasp.dependencycheck.dependency.Confidence;
       45  
       import org.owasp.dependencycheck.dependency.Evidence;
       import org.owasp.dependencycheck.dependency.Dependency;
       46  
       import org.owasp.dependencycheck.dependency.EvidenceCollection;
       import org.owasp.dependencycheck.dependency.Evidence;
       47  
       import org.owasp.dependencycheck.dependency.Identifier;
       import org.owasp.dependencycheck.dependency.EvidenceCollection;
       48  
       import org.owasp.dependencycheck.dependency.VulnerableSoftware;
       import org.owasp.dependencycheck.dependency.Identifier;
       49  
       import org.owasp.dependencycheck.exception.InitializationException;
       import org.owasp.dependencycheck.dependency.VulnerableSoftware;
       50  
       import org.owasp.dependencycheck.utils.DependencyVersion;
       import org.owasp.dependencycheck.exception.InitializationException;
       51  
       import org.owasp.dependencycheck.utils.DependencyVersionUtil;
       import org.owasp.dependencycheck.utils.DependencyVersion;
       52  
       import org.slf4j.Logger;
       import org.owasp.dependencycheck.utils.DependencyVersionUtil;
       53  
       import org.slf4j.LoggerFactory;
       import org.slf4j.Logger;
       54  
       
       import org.slf4j.LoggerFactory;
       55  
       /**
       
       56  
        * CPEAnalyzer is a utility class that takes a project dependency and attempts
       /**
       57  
        * to discern if there is an associated CPE. It uses the evidence contained
        * CPEAnalyzer is a utility class that takes a project dependency and attempts
       58  
        * within the dependency to search the Lucene index.
        * to discern if there is an associated CPE. It uses the evidence contained
       59  
        *
        * within the dependency to search the Lucene index.
       60  
        * @author Jeremy Long
        *
       61  
        * @author Jeremy Long
       62  
        */
       62  6
       public class CPEAnalyzer implements Analyzer {
       63  
       
       63  8
       public class CPEAnalyzer extends AbstractAnalyzer {
       64  
           /**
       
       65  
            * The Logger.
           /**
       66  
            * The Logger.
       67  
            */
       67  1
           private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class);
       68  
           /**
       68  1
           private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class);
       69  
            * The maximum number of query results to return.
           /**
       70  
            */
            * The maximum number of query results to return.
       71  
           static final int MAX_QUERY_RESULTS = 25;
            */
       72  
           /**
           static final int MAX_QUERY_RESULTS = 25;
       73  
            * The weighting boost to give terms when constructing the Lucene query.
           /**
       74  
            */
            * The weighting boost to give terms when constructing the Lucene query.
       75  
           static final String WEIGHTING_BOOST = "^5";
            */
       76  
           /**
           static final String WEIGHTING_BOOST = "^5";
       77  
            * A string representation of a regular expression defining characters
           /**
       78  
            * utilized within the CPE Names.
            * A string representation of a regular expression defining characters
       79  
            */
            * utilized within the CPE Names.
       80  
           static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]";
            */
       81  
           /**
           static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]";
       82  
            * A string representation of a regular expression used to remove all but
           /**
       83  
            * alpha characters.
            * A string representation of a regular expression used to remove all but
       84  
            */
            * alpha characters.
       85  
           static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*";
            */
       86  
           /**
           static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*";
       87  
            * The additional size to add to a new StringBuilder to account for extra
           /**
       88  
            * data that will be written into the string.
            * The additional size to add to a new StringBuilder to account for extra
       89  
            */
            * data that will be written into the string.
       90  
           static final int STRING_BUILDER_BUFFER = 20;
            */
       91  
           /**
           static final int STRING_BUILDER_BUFFER = 20;
       92  
            * The CPE in memory index.
           /**
       93  
            */
            * The CPE in memory index.
       94  
           private CpeMemoryIndex cpe;
            */
       95  
           /**
           private CpeMemoryIndex cpe;
       96  
            * The CVE Database.
           /**
       97  
            */
            * The CVE Database.
       98  
           private CveDB cve;
            */
       99  
       
           private CveDB cve;
       100  
           /**
       
       101  
            * The URL to perform a search of the NVD CVE data at NIST.
           /**
       102  
            */
            * The URL to perform a search of the NVD CVE data at NIST.
       103  
           public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s";
            */
       104  
       
           public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s";
       105  
           /**
       
       106  
            * Returns the name of this analyzer.
           /**
       107  
            *
            * Returns the name of this analyzer.
       108  
            * @return the name of this analyzer.
            *
       109  
            */
            * @return the name of this analyzer.
       110  
           @Override
            */
       111  
           @Override
       112  
           public String getName() {
       112  16
               return "CPE Analyzer";
       113  
           }
       113  26
               return "CPE Analyzer";
       114  
       
       115  
           /**
       116  
            * Returns the analysis phase that this analyzer should run in.
       117  
            *
       118  
            * @return the analysis phase that this analyzer should run in.
       119  
            */
       120  
           @Override
       121  
           public AnalysisPhase getAnalysisPhase() {
       122  4
               return AnalysisPhase.IDENTIFIER_ANALYSIS;
       123  
           }
       124  
       115  
       
       125  
       116  
           /**
       126  
            * Creates the CPE Lucene Index.
       127  
       117  
            * Returns the analysis phase that this analyzer should run in.
       118  
            *
       128  
            * @throws InitializationException is thrown if there is an issue opening
       129  
            * the index.
       130  
       119  
            * @return the analysis phase that this analyzer should run in.
       120  
            */
       131  
       121  
           @Override
       132  
           public void initialize() throws InitializationException {
       133  
               try {
       134  2
                   this.open();
       135  0
               } catch (IOException ex) {
       136  0
                   LOGGER.debug("Exception initializing the Lucene Index", ex);
       137  0
                   throw new InitializationException("An exception occurred initializing the Lucene Index", ex);
       138  0
               } catch (DatabaseException ex) {
       139  0
                   LOGGER.debug("Exception accessing the database", ex);
       140  0
                   throw new InitializationException("An exception occurred accessing the database", ex);
       141  2
               }
       142  2
           }
       143  
       122  
           public AnalysisPhase getAnalysisPhase() {
       123  6
               return AnalysisPhase.IDENTIFIER_ANALYSIS;
       124  
           }
       125  
       
       144  
       126  
           /**
       145  
            * Opens the data source.
       146  
       127  
            * Creates the CPE Lucene Index.
       128  
            *
       147  
            * @throws IOException when the Lucene directory to be queried does not
       148  
            * exist or is corrupt.
       149  
            * @throws DatabaseException when the database throws an exception. This
       150  
            * usually occurs when the database is in use by another process.
       151  
       129  
            * @throws InitializationException is thrown if there is an issue opening
       130  
            * the index.
       131  
            */
       132  
           @Override
       133  
           public void initialize() throws InitializationException {
       134  
               try {
       135  2
                   this.open();
       136  0
               } catch (IOException ex) {
       137  0
                   LOGGER.debug("Exception initializing the Lucene Index", ex);
       138  0
                   throw new InitializationException("An exception occurred initializing the Lucene Index", ex);
       139  0
               } catch (DatabaseException ex) {
       140  0
                   LOGGER.debug("Exception accessing the database", ex);
       141  0
                   throw new InitializationException("An exception occurred accessing the database", ex);
       142  2
               }
       143  2
           }
       144  
       
       145  
           /**
       146  
            * Opens the data source.
       147  
            *
       148  
            * @throws IOException when the Lucene directory to be queried does not
       149  
            * exist or is corrupt.
       150  
            * @throws DatabaseException when the database throws an exception. This
       151  
            * usually occurs when the database is in use by another process.
       152  
            */
       153  
           public void open() throws IOException, DatabaseException {
       153  2
               if (!isOpen()) {
       154  2
                   cve = new CveDB();
       155  2
                   cve.open();
       156  2
                   cpe = CpeMemoryIndex.getInstance();
       157  
       154  2
               if (!isOpen()) {
       155  2
                   cve = new CveDB();
       156  2
                   cve.open();
       157  2
                   cpe = CpeMemoryIndex.getInstance();
       158  
                   try {
       158  2
                       LOGGER.info("Creating the CPE Index");
       159  2
                       final long creationStart = System.currentTimeMillis();
       160  2
                       cpe.open(cve);
       161  2
                       LOGGER.info("CPE Index Created ({} ms)", System.currentTimeMillis() - creationStart);
       162  0
                   } catch (IndexException ex) {
       163  0
                       LOGGER.debug("IndexException", ex);
       164  0
                       throw new DatabaseException(ex);
       165  2
                   }
       166  
       161  2
                       final long creationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - creationStart);
       162  2
                       LOGGER.info("Created CPE Index ({} seconds)", creationSeconds);
       163  0
                   } catch (IndexException ex) {
       164  0
                       LOGGER.debug("IndexException", ex);
       165  0
                       throw new DatabaseException(ex);
       166  2
                   }
       167  
               }
       167  2
           }
       168  
       
       168  2
           }
       169  
           /**
       
       170  
            * Closes the data sources.
           /**
       171  
            */
            * Closes the data sources.
       172  
           @Override
            */
       173  
           public void close() {
       174  2
               if (cpe != null) {
       175  2
                   cpe.close();
       176  2
                   cpe = null;
       177  
               }
       178  2
               if (cve != null) {
       179  2
                   cve.close();
       180  2
                   cve = null;
       181  
               }
       182  2
           }
       183  
       
       184  
           public boolean isOpen() {
       185  2
               return cpe != null && cpe.isOpen();
       186  
           }
       187  
       
       188  
           /**
       189  
            * Searches the data store of CPE entries, trying to identify the CPE for
       190  
            * the given dependency based on the evidence contained within. The
       191  
            * dependency passed in is updated with any identified CPE values.
       192  
            *
       193  
            * @param dependency the dependency to search for CPE entries on.
       194  
            * @throws CorruptIndexException is thrown when the Lucene index is corrupt.
       195  
            * @throws IOException is thrown when an IOException occurs.
       196  
            * @throws ParseException is thrown when the Lucene query cannot be parsed.
       197  
            */
       198  
           protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
       199  
               //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit
       200  4
               String vendors = "";
       201  4
               String products = "";
       202  17
               for (Confidence confidence : Confidence.values()) {
       203  14
                   if (dependency.getVendorEvidence().contains(confidence)) {
       204  9
                       vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
       205  9
                       LOGGER.debug("vendor search: {}", vendors);
       206  
                   }
       207  14
                   if (dependency.getProductEvidence().contains(confidence)) {
       208  8
                       products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence);
       209  8
                       LOGGER.debug("product search: {}", products);
       210  
                   }
       211  14
                   if (!vendors.isEmpty() && !products.isEmpty()) {
       212  22
                       final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(),
       213  11
                               dependency.getProductEvidence().getWeighting());
       214  11
                       if (entries == null) {
       215  0
                           continue;
       216  
                       }
       217  11
                       boolean identifierAdded = false;
       218  11
                       for (IndexEntry e : entries) {
       219  18
                           LOGGER.debug("Verifying entry: {}", e);
       220  18
                           if (verifyEntry(e, dependency)) {
       221  3
                               final String vendor = e.getVendor();
       222  3
                               final String product = e.getProduct();
       223  3
                               LOGGER.debug("identified vendor/product: {}/{}", vendor, product);
       224  3
                               identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence);
       225  
                           }
       226  18
                       }
       227  11
                       if (identifierAdded) {
       228  1
                           break;
       229  
                       }
       230  
                   }
       231  
               }
       232  4
           }
       233  
       
       234  
           /**
       235  
            * Returns the text created by concatenating the text and the values from
       236  
            * the EvidenceCollection (filtered for a specific confidence). This
       237  
            * attempts to prevent duplicate terms from being added.<br/<br/> Note, if
       238  
            * the evidence is longer then 200 characters it will be truncated.
       239  
            *
       240  
            * @param text the base text.
       241  
            * @param ec an EvidenceCollection
       242  
            * @param confidenceFilter a Confidence level to filter the evidence by.
       243  
            * @return the new evidence text
       244  
            */
       245  
           private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) {
       246  17
               final String txt = (text == null) ? "" : text;
       247  17
               final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size()));
       248  17
               sb.append(' ').append(txt).append(' ');
       249  17
               for (Evidence e : ec.iterator(confidenceFilter)) {
       250  36
                   String value = e.getValue();
       251  
       
       252  
                   //hack to get around the fact that lucene does a really good job of recognizing domains and not
       253  
                   // splitting them. TODO - put together a better lucene analyzer specific to the domain.
       254  36
                   if (value.startsWith("http://")) {
       255  2
                       value = value.substring(7).replaceAll("\\.", " ");
       256  
                   }
       257  36
                   if (value.startsWith("https://")) {
       258  1
                       value = value.substring(8).replaceAll("\\.", " ");
       259  
                   }
       260  36
                   if (sb.indexOf(" " + value + " ") < 0) {
       261  34
                       sb.append(value).append(' ');
       262  
                   }
       263  36
               }
       264  17
               return sb.toString().trim();
       265  
           }
       266  
       
       267  
           /**
       268  
            * <p>
       269  
            * Searches the Lucene CPE index to identify possible CPE entries associated
       270  
            * with the supplied vendor, product, and version.</p>
       271  
            *
       272  
            * <p>
       273  
            * If either the vendorWeightings or productWeightings lists have been
       274  
            * populated this data is used to add weighting factors to the search.</p>
       275  
            *
       276  
            * @param vendor the text used to search the vendor field
       277  
            * @param product the text used to search the product field
       278  
            * @param vendorWeightings a list of strings to use to add weighting factors
       279  
            * to the vendor field
       280  
            * @param productWeightings Adds a list of strings that will be used to add
       281  
            * weighting factors to the product search
       282  
            * @return a list of possible CPE values
       283  
            */
       284  
           protected List<IndexEntry> searchCPE(String vendor, String product,
       285  
                   Set<String> vendorWeightings, Set<String> productWeightings) {
       286  
       
       287  11
               final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS);
       288  
       
       289  11
               final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings);
       290  11
               if (searchString == null) {
       291  0
                   return ret;
       292  
               }
       293  
               try {
       294  11
                   final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS);
       295  74
                   for (ScoreDoc d : docs.scoreDocs) {
       296  63
                       if (d.score >= 0.08) {
       297  18
                           final Document doc = cpe.getDocument(d.doc);
       298  18
                           final IndexEntry entry = new IndexEntry();
       299  18
                           entry.setVendor(doc.get(Fields.VENDOR));
       300  18
                           entry.setProduct(doc.get(Fields.PRODUCT));
       301  18
                           entry.setSearchScore(d.score);
       302  18
                           if (!ret.contains(entry)) {
       303  18
                               ret.add(entry);
       304  
                           }
       305  
                       }
       306  
                   }
       307  11
                   return ret;
       308  0
               } catch (ParseException ex) {
       309  0
                   LOGGER.warn("An error occurred querying the CPE data. See the log for more details.");
       310  0
                   LOGGER.info("Unable to parse: {}", searchString, ex);
       311  0
               } catch (IOException ex) {
       312  0
                   LOGGER.warn("An error occurred reading CPE data. See the log for more details.");
       313  0
                   LOGGER.info("IO Error with search string: {}", searchString, ex);
       314  0
               }
       315  0
               return null;
       316  
           }
       317  
       
       318  
           /**
       319  
            * <p>
       320  
            * Builds a Lucene search string by properly escaping data and constructing
       321  
            * a valid search query.</p>
       322  
            *
       323  
            * <p>
       324  
            * If either the possibleVendor or possibleProducts lists have been
       325  
            * populated this data is used to add weighting factors to the search string
       326  
            * generated.</p>
       327  
            *
       328  
            * @param vendor text to search the vendor field
       329  
            * @param product text to search the product field
       330  
            * @param vendorWeighting a list of strings to apply to the vendor to boost
       331  
            * the terms weight
       332  
            * @param productWeightings a list of strings to apply to the product to
       333  
            * boost the terms weight
       334  
            * @return the Lucene query
       335  
            */
       336  
           protected String buildSearch(String vendor, String product,
       337  
                   Set<String> vendorWeighting, Set<String> productWeightings) {
       338  11
               final String v = vendor; //.replaceAll("[^\\w\\d]", " ");
       339  11
               final String p = product; //.replaceAll("[^\\w\\d]", " ");
       340  11
               final StringBuilder sb = new StringBuilder(v.length() + p.length()
       341  11
                       + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER);
       342  
       
       343  11
               if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) {
       344  0
                   return null;
       345  
               }
       346  11
               sb.append(" AND ");
       347  11
               if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) {
       348  0
                   return null;
       349  
               }
       350  11
               return sb.toString();
       351  
           }
       352  
       
       353  
           /**
       354  
            * This method constructs a Lucene query for a given field. The searchText
       355  
            * is split into separate words and if the word is within the list of
       356  
            * weighted words then an additional weighting is applied to the term as it
       357  
            * is appended into the query.
       358  
            *
       359  
            * @param sb a StringBuilder that the query text will be appended to.
       360  
            * @param field the field within the Lucene index that the query is
       361  
            * searching.
       362  
            * @param searchText text used to construct the query.
       363  
            * @param weightedText a list of terms that will be considered higher
       364  
            * importance when searching.
       365  
            * @return if the append was successful.
       366  
            */
       367  
           private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) {
       368  22
               sb.append(' ').append(field).append(":( ");
       369  
       
       370  22
               final String cleanText = cleanseText(searchText);
       371  
       
       372  22
               if (cleanText.isEmpty()) {
       373  0
                   return false;
       374  
               }
       375  
       
       376  22
               if (weightedText == null || weightedText.isEmpty()) {
       377  14
                   LuceneUtils.appendEscapedLuceneQuery(sb, cleanText);
       378  
               } else {
       379  8
                   final StringTokenizer tokens = new StringTokenizer(cleanText);
       380  102
                   while (tokens.hasMoreElements()) {
       381  94
                       final String word = tokens.nextToken();
       382  94
                       StringBuilder temp = null;
       383  94
                       for (String weighted : weightedText) {
       384  223
                           final String weightedStr = cleanseText(weighted);
       385  223
                           if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) {
       386  7
                               temp = new StringBuilder(word.length() + 2);
       387  7
                               LuceneUtils.appendEscapedLuceneQuery(temp, word);
       388  7
                               temp.append(WEIGHTING_BOOST);
       389  7
                               if (!word.equalsIgnoreCase(weightedStr)) {
       390  0
                                   temp.append(' ');
       391  0
                                   LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr);
       392  0
                                   temp.append(WEIGHTING_BOOST);
       393  
                               }
       394  
                               break;
       395  
                           }
       396  216
                       }
       397  94
                       sb.append(' ');
       398  94
                       if (temp == null) {
       399  87
                           LuceneUtils.appendEscapedLuceneQuery(sb, word);
       400  
                       } else {
       401  7
                           sb.append(temp);
       402  
                       }
       403  94
                   }
       404  
               }
       405  22
               sb.append(" ) ");
       406  22
               return true;
       407  
           }
       408  
       
       409  
           /**
       410  
            * Removes characters from the input text that are not used within the CPE
       411  
            * index.
       412  
            *
       413  
            * @param text is the text to remove the characters from.
       414  
            * @return the text having removed some characters.
       415  
            */
       416  
           private String cleanseText(String text) {
       417  245
               return text.replaceAll(CLEANSE_CHARACTER_RX, " ");
       418  
           }
       419  
       
       420  
           /**
       421  
            * Compares two strings after lower casing them and removing the non-alpha
       422  
            * characters.
       423  
            *
       424  
            * @param l string one to compare.
       425  
            * @param r string two to compare.
       426  
            * @return whether or not the two strings are similar.
       427  
            */
       428  
           private boolean equalsIgnoreCaseAndNonAlpha(String l, String r) {
       429  223
               if (l == null || r == null) {
       430  0
                   return false;
       431  
               }
       432  
       
       433  223
               final String left = l.replaceAll(CLEANSE_NONALPHA_RX, "");
       434  223
               final String right = r.replaceAll(CLEANSE_NONALPHA_RX, "");
       435  223
               return left.equalsIgnoreCase(right);
       436  
           }
       437  
       
       438  
           /**
       439  
            * Ensures that the CPE Identified matches the dependency. This validates
       440  
            * that the product, vendor, and version information for the CPE are
       441  
            * contained within the dependencies evidence.
       442  
            *
       443  
            * @param entry a CPE entry.
       444  
            * @param dependency the dependency that the CPE entries could be for.
       445  
            * @return whether or not the entry is valid.
       446  
            */
       447  
           private boolean verifyEntry(final IndexEntry entry, final Dependency dependency) {
       448  18
               boolean isValid = false;
       449  
       
       450  
               //TODO - does this nullify some of the fuzzy matching that happens in the lucene search?
       451  
               // for instance CPE some-component and in the evidence we have SomeComponent.
       452  18
               if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct())
       453  4
                       && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) {
       454  
                   //&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion())
       455  3
                   isValid = true;
       456  
               }
       457  18
               return isValid;
       458  
           }
       459  
       
       460  
           /**
       461  
            * Used to determine if the EvidenceCollection contains a specific string.
       462  
            *
       463  
            * @param ec an EvidenceCollection
       464  
            * @param text the text to search for
       465  
            * @return whether or not the EvidenceCollection contains the string
       466  
            */
       467  
           private boolean collectionContainsString(EvidenceCollection ec, String text) {
       468  
               //TODO - likely need to change the split... not sure if this will work for CPE with special chars
       469  22
               if (text == null) {
       470  0
                   return false;
       471  
               }
       472  22
               final String[] words = text.split("[\\s_-]");
       473  22
               final List<String> list = new ArrayList<String>();
       474  22
               String tempWord = null;
       475  75
               for (String word : words) {
       476  
                   /*
       477  
                    single letter words should be concatenated with the next word.
       478  
                    so { "m", "core", "sample" } -> { "mcore", "sample" }
       479  
                    */
       480  53
                   if (tempWord != null) {
       481  2
                       list.add(tempWord + word);
       482  2
                       tempWord = null;
       483  51
                   } else if (word.length() <= 2) {
       484  2
                       tempWord = word;
       485  
                   } else {
       486  49
                       list.add(word);
       487  
                   }
       488  
               }
       489  22
               if (tempWord != null) {
       490  0
                   if (!list.isEmpty()) {
       491  0
                       final String tmp = list.get(list.size() - 1) + tempWord;
       492  0
                       list.add(tmp);
       493  0
                   } else {
       494  0
                       list.add(tempWord);
       495  
                   }
       496  
               }
       497  22
               if (list.isEmpty()) {
       498  0
                   return false;
       499  
               }
       500  22
               boolean contains = true;
       501  22
               for (String word : list) {
       502  51
                   contains &= ec.containsUsedString(word);
       503  51
               }
       504  22
               return contains;
       505  
           }
       506  
       
       507  
           /**
       508  
            * Analyzes a dependency and attempts to determine if there are any CPE
       509  
            * identifiers for this dependency.
       510  
            *
       511  
            * @param dependency The Dependency to analyze.
       512  
            * @param engine The analysis engine
       513  
            * @throws AnalysisException is thrown if there is an issue analyzing the
       514  
            * dependency.
       515  
            */
       516  
           @Override
       517  
           public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException {
       518  
               try {
       519  4
                   determineCPE(dependency);
       520  0
               } catch (CorruptIndexException ex) {
       521  0
                   throw new AnalysisException("CPE Index is corrupt.", ex);
       522  0
               } catch (IOException ex) {
       523  0
                   throw new AnalysisException("Failure opening the CPE Index.", ex);
       524  0
               } catch (ParseException ex) {
       525  0
                   throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex);
       526  4
               }
       527  4
           }
       528  
       174  
           public void close() {
       175  2
               if (cpe != null) {
       176  2
                   cpe.close();
       177  2
                   cpe = null;
       178  
               }
       179  2
               if (cve != null) {
       180  2
                   cve.close();
       181  2
                   cve = null;
       182  
               }
       183  2
           }
       184  
       
       529  
       185  
           public boolean isOpen() {
       186  2
               return cpe != null && cpe.isOpen();
       187  
           }
       188  
       
       189  
           /**
       530  
            * Retrieves a list of CPE values from the CveDB based on the vendor and
       531  
            * product passed in. The list is then validated to find only CPEs that are
       532  
            * valid for the given dependency. It is possible that the CPE identified is
       533  
            * a best effort "guess" based on the vendor, product, and version
       534  
            * information.
       535  
       190  
            * Searches the data store of CPE entries, trying to identify the CPE for
       191  
            * the given dependency based on the evidence contained within. The
       192  
            * dependency passed in is updated with any identified CPE values.
       193  
            *
       536  
            * @param dependency the Dependency being analyzed
       537  
            * @param vendor the vendor for the CPE being analyzed
       538  
            * @param product the product for the CPE being analyzed
       539  
            * @param currentConfidence the current confidence being used during
       540  
            * analysis
       541  
            * @return <code>true</code> if an identifier was added to the dependency;
       542  
            * otherwise <code>false</code>
       543  
            * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
       544  
       194  
            * @param dependency the dependency to search for CPE entries on.
       195  
            * @throws CorruptIndexException is thrown when the Lucene index is corrupt.
       196  
            * @throws IOException is thrown when an IOException occurs.
       197  
            * @throws ParseException is thrown when the Lucene query cannot be parsed.
       198  
            */
       545  
           protected boolean determineIdentifiers(Dependency dependency, String vendor, String product,
       546  
                   Confidence currentConfidence) throws UnsupportedEncodingException {
       547  3
               final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
       548  3
               DependencyVersion bestGuess = new DependencyVersion("-");
       549  3
               Confidence bestGuessConf = null;
       550  3
               boolean hasBroadMatch = false;
       551  3
               final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
       552  
       
       553  
               //TODO the following algorithm incorrectly identifies things as a lower version
       554  
               // if there lower confidence evidence when the current (highest) version number
       555  
               // is newer then anything in the NVD.
       556  15
               for (Confidence conf : Confidence.values()) {
       557  12
                   for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
       558  12
                       final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
       559  12
                       if (evVer == null) {
       560  3
                           continue;
       561  
       199  
           protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
       200  
               //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit
       201  4
               String vendors = "";
       202  4
               String products = "";
       203  17
               for (Confidence confidence : Confidence.values()) {
       204  14
                   if (dependency.getVendorEvidence().contains(confidence)) {
       205  9
                       vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence);
       206  9
                       LOGGER.debug("vendor search: {}", vendors);
       207  
                   }
       208  14
                   if (dependency.getProductEvidence().contains(confidence)) {
       209  8
                       products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence);
       210  8
                       LOGGER.debug("product search: {}", products);
       211  
                   }
       212  14
                   if (!vendors.isEmpty() && !products.isEmpty()) {
       213  22
                       final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(),
       214  11
                               dependency.getProductEvidence().getWeighting());
       215  11
                       if (entries == null) {
       216  0
                           continue;
       217  
                       }
       562  9
                       for (VulnerableSoftware vs : cpes) {
       563  
                           DependencyVersion dbVer;
       564  327
                           if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) {
       565  96
                               dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate());
       566  
                           } else {
       567  231
                               dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
       568  
       218  11
                       boolean identifierAdded = false;
       219  11
                       for (IndexEntry e : entries) {
       220  20
                           LOGGER.debug("Verifying entry: {}", e);
       221  20
                           if (verifyEntry(e, dependency)) {
       222  4
                               final String vendor = e.getVendor();
       223  4
                               final String product = e.getProduct();
       224  4
                               LOGGER.debug("identified vendor/product: {}/{}", vendor, product);
       225  4
                               identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence);
       226  
                           }
       569  327
                           if (dbVer == null) { //special case, no version specified - everything is vulnerable
       570  0
                               hasBroadMatch = true;
       571  0
                               final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
       572  0
                               final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf);
       573  0
                               collected.add(match);
       574  0
                           } else if (evVer.equals(dbVer)) { //yeah! exact match
       575  6
                               final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
       576  6
                               final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
       577  6
                               collected.add(match);
       578  
       227  20
                       }
       228  11
                       if (identifierAdded) {
       229  1
                           break;
       230  
                       }
       231  
                   }
       232  
               }
       233  4
           }
       234  
       
       579  
                               //TODO the following isn't quite right is it? need to think about this guessing game a bit more.
       580  6
                           } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
       581  315
                                   && evVer.matchesAtLeastThreeLevels(dbVer)) {
       582  48
                               if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
       583  2
                                   if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
       584  2
                                       bestGuess = dbVer;
       585  2
                                       bestGuessConf = conf;
       586  
                                   }
       587  
       235  
           /**
       236  
            * Returns the text created by concatenating the text and the values from
       237  
            * the EvidenceCollection (filtered for a specific confidence). This
       238  
            * attempts to prevent duplicate terms from being added.<br/<br/> Note, if
       239  
            * the evidence is longer then 200 characters it will be truncated.
       240  
            *
       241  
            * @param text the base text.
       242  
            * @param ec an EvidenceCollection
       243  
            * @param confidenceFilter a Confidence level to filter the evidence by.
       244  
            * @return the new evidence text
       245  
            */
       246  
           private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) {
       247  17
               final String txt = (text == null) ? "" : text;
       248  17
               final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size()));
       249  17
               sb.append(' ').append(txt).append(' ');
       250  17
               for (Evidence e : ec.iterator(confidenceFilter)) {
       251  36
                   String value = e.getValue();
       252  
       
       253  
                   //hack to get around the fact that lucene does a really good job of recognizing domains and not
       254  
                   // splitting them. TODO - put together a better lucene analyzer specific to the domain.
       255  36
                   if (value.startsWith("http://")) {
       256  2
                       value = value.substring(7).replaceAll("\\.", " ");
       257  
                   }
       258  36
                   if (value.startsWith("https://")) {
       259  1
                       value = value.substring(8).replaceAll("\\.", " ");
       260  
                   }
       261  36
                   if (sb.indexOf(" " + value + " ") < 0) {
       262  34
                       sb.append(value).append(' ');
       263  
                   }
       264  36
               }
       265  17
               return sb.toString().trim();
       266  
           }
       267  
       
       268  
           /**
       269  
            * <p>
       270  
            * Searches the Lucene CPE index to identify possible CPE entries associated
       271  
            * with the supplied vendor, product, and version.</p>
       272  
            *
       273  
            * <p>
       274  
            * If either the vendorWeightings or productWeightings lists have been
       275  
            * populated this data is used to add weighting factors to the search.</p>
       276  
            *
       277  
            * @param vendor the text used to search the vendor field
       278  
            * @param product the text used to search the product field
       279  
            * @param vendorWeightings a list of strings to use to add weighting factors
       280  
            * to the vendor field
       281  
            * @param productWeightings Adds a list of strings that will be used to add
       282  
            * weighting factors to the product search
       283  
            * @return a list of possible CPE values
       284  
            */
       285  
           protected List<IndexEntry> searchCPE(String vendor, String product,
       286  
                   Set<String> vendorWeightings, Set<String> productWeightings) {
       287  
       
       288  11
               final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS);
       289  
       
       290  11
               final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings);
       291  11
               if (searchString == null) {
       292  0
                   return ret;
       293  
               }
       294  
               try {
       295  11
                   final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS);
       296  75
                   for (ScoreDoc d : docs.scoreDocs) {
       297  64
                       if (d.score >= 0.08) {
       298  20
                           final Document doc = cpe.getDocument(d.doc);
       299  20
                           final IndexEntry entry = new IndexEntry();
       300  20
                           entry.setVendor(doc.get(Fields.VENDOR));
       301  20
                           entry.setProduct(doc.get(Fields.PRODUCT));
       302  20
                           entry.setSearchScore(d.score);
       303  20
                           if (!ret.contains(entry)) {
       304  20
                               ret.add(entry);
       305  
                           }
       306  
                       }
       307  
                   }
       308  11
                   return ret;
       309  0
               } catch (ParseException ex) {
       310  0
                   LOGGER.warn("An error occurred querying the CPE data. See the log for more details.");
       311  0
                   LOGGER.info("Unable to parse: {}", searchString, ex);
       312  0
               } catch (IOException ex) {
       313  0
                   LOGGER.warn("An error occurred reading CPE data. See the log for more details.");
       314  0
                   LOGGER.info("IO Error with search string: {}", searchString, ex);
       315  0
               }
       316  0
               return null;
       317  
           }
       318  
       
       319  
           /**
       320  
            * <p>
       321  
            * Builds a Lucene search string by properly escaping data and constructing
       322  
            * a valid search query.</p>
       323  
            *
       324  
            * <p>
       325  
            * If either the possibleVendor or possibleProducts lists have been
       326  
            * populated this data is used to add weighting factors to the search string
       327  
            * generated.</p>
       328  
            *
       329  
            * @param vendor text to search the vendor field
       330  
            * @param product text to search the product field
       331  
            * @param vendorWeighting a list of strings to apply to the vendor to boost
       332  
            * the terms weight
       333  
            * @param productWeightings a list of strings to apply to the product to
       334  
            * boost the terms weight
       335  
            * @return the Lucene query
       336  
            */
       337  
           protected String buildSearch(String vendor, String product,
       338  
                   Set<String> vendorWeighting, Set<String> productWeightings) {
       339  11
               final String v = vendor; //.replaceAll("[^\\w\\d]", " ");
       340  11
               final String p = product; //.replaceAll("[^\\w\\d]", " ");
       341  11
               final StringBuilder sb = new StringBuilder(v.length() + p.length()
       342  11
                       + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER);
       343  
       
       344  11
               if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) {
       345  0
                   return null;
       346  
               }
       347  11
               sb.append(" AND ");
       348  11
               if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) {
       349  0
                   return null;
       350  
               }
       351  11
               return sb.toString();
       352  
           }
       353  
       
       354  
           /**
       355  
            * This method constructs a Lucene query for a given field. The searchText
       356  
            * is split into separate words and if the word is within the list of
       357  
            * weighted words then an additional weighting is applied to the term as it
       358  
            * is appended into the query.
       359  
            *
       360  
            * @param sb a StringBuilder that the query text will be appended to.
       361  
            * @param field the field within the Lucene index that the query is
       362  
            * searching.
       363  
            * @param searchText text used to construct the query.
       364  
            * @param weightedText a list of terms that will be considered higher
       365  
            * importance when searching.
       366  
            * @return if the append was successful.
       367  
            */
       368  
           private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) {
       369  22
               sb.append(' ').append(field).append(":( ");
       370  
       
       371  22
               final String cleanText = cleanseText(searchText);
       372  
       
       373  22
               if (cleanText.isEmpty()) {
       374  0
                   return false;
       375  
               }
       376  
       
       377  22
               if (weightedText == null || weightedText.isEmpty()) {
       378  14
                   LuceneUtils.appendEscapedLuceneQuery(sb, cleanText);
       379  
               } else {
       380  8
                   final StringTokenizer tokens = new StringTokenizer(cleanText);
       381  103
                   while (tokens.hasMoreElements()) {
       382  95
                       final String word = tokens.nextToken();
       383  95
                       StringBuilder temp = null;
       384  95
                       for (String weighted : weightedText) {
       385  225
                           final String weightedStr = cleanseText(weighted);
       386  225
                           if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) {
       387  7
                               temp = new StringBuilder(word.length() + 2);
       388  7
                               LuceneUtils.appendEscapedLuceneQuery(temp, word);
       389  7
                               temp.append(WEIGHTING_BOOST);
       390  7
                               if (!word.equalsIgnoreCase(weightedStr)) {
       391  0
                                   temp.append(' ');
       392  0
                                   LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr);
       393  0
                                   temp.append(WEIGHTING_BOOST);
       394  
                               }
       588  
       395  
                               break;
       396  
                           }
       589  327
                       }
       590  9
                       if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
       591  1
                           if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) {
       592  1
                               bestGuess = evVer;
       593  1
                               bestGuessConf = conf;
       594  
                           }
       595  
                       }
       596  9
                   }
       597  
               }
       598  3
               final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
       599  3
               String url = null;
       600  3
               if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess.
       601  0
                   final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product);
       602  0
                   url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8"));
       603  
               }
       604  3
               if (bestGuessConf == null) {
       605  0
                   bestGuessConf = Confidence.LOW;
       606  
               }
       607  3
               final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf);
       608  3
               collected.add(match);
       609  
       
       610  3
               Collections.sort(collected);
       611  3
               final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence();
       612  3
               final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence();
       613  3
               boolean identifierAdded = false;
       614  3
               for (IdentifierMatch m : collected) {
       615  9
                   if (bestIdentifierQuality.equals(m.getConfidence())
       616  7
                           && bestEvidenceQuality.equals(m.getEvidenceConfidence())) {
       617  3
                       final Identifier i = m.getIdentifier();
       618  3
                       if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) {
       619  1
                           i.setConfidence(Confidence.LOW);
       620  
       397  218
                       }
       398  95
                       sb.append(' ');
       399  95
                       if (temp == null) {
       400  88
                           LuceneUtils.appendEscapedLuceneQuery(sb, word);
       401  
                       } else {
       621  2
                           i.setConfidence(bestEvidenceQuality);
       622  
       402  7
                           sb.append(temp);
       403  
                       }
       623  3
                       dependency.addIdentifier(i);
       624  3
                       identifierAdded = true;
       625  
                   }
       626  9
               }
       627  3
               return identifierAdded;
       628  
       404  95
                   }
       405  
               }
       406  22
               sb.append(" ) ");
       407  22
               return true;
       408  
           }
       629  
       409  
       
       630  
       410  
           /**
       631  
            * The confidence whether the identifier is an exact match, or a best guess.
       632  
       411  
            * Removes characters from the input text that are not used within the CPE
       412  
            * index.
       413  
            *
       414  
            * @param text is the text to remove the characters from.
       415  
            * @return the text having removed some characters.
       416  
            */
       633  4
           private enum IdentifierConfidence {
       634  
       
       635  
               /**
       636  
                * An exact match for the CPE.
       637  
                */
       638  1
               EXACT_MATCH,
       639  
               /**
       640  
                * A best guess for the CPE.
       641  
                */
       642  1
               BEST_GUESS,
       643  
               /**
       644  
                * The entire vendor/product group must be added (without a guess at
       645  
                * version) because there is a CVE with a VS that only specifies
       646  
                * vendor/product.
       647  
                */
       648  1
               BROAD_MATCH
       649  
       417  
           private String cleanseText(String text) {
       418  247
               return text.replaceAll(CLEANSE_CHARACTER_RX, " ");
       419  
           }
       650  
       420  
       
       651  
       421  
           /**
       652  
            * A simple object to hold an identifier and carry information about the
       653  
            * confidence in the identifier.
       654  
       422  
            * Compares two strings after lower casing them and removing the non-alpha
       423  
            * characters.
       424  
            *
       425  
            * @param l string one to compare.
       426  
            * @param r string two to compare.
       427  
            * @return whether or not the two strings are similar.
       428  
            */
       655  6
           private static class IdentifierMatch implements Comparable<IdentifierMatch> {
       656  
       
       657  
               /**
       658  
                * Constructs an IdentifierMatch.
       659  
                *
       660  
                * @param type the type of identifier (such as CPE)
       661  
                * @param value the value of the identifier
       662  
                * @param url the URL of the identifier
       663  
                * @param identifierConfidence the confidence in the identifier: best
       664  
                * guess or exact match
       665  
                * @param evidenceConfidence the confidence of the evidence used to find
       666  
                * the identifier
       667  
                */
       668  9
               IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) {
       669  9
                   this.identifier = new Identifier(type, value, url);
       670  9
                   this.confidence = identifierConfidence;
       671  9
                   this.evidenceConfidence = evidenceConfidence;
       672  9
               }
       673  
               //<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier">
       674  
               /**
       675  
                * The confidence in the evidence used to identify this match.
       676  
                */
       677  
               private Confidence evidenceConfidence;
       678  
       
       679  
               /**
       680  
                * Get the value of evidenceConfidence
       681  
                *
       682  
                * @return the value of evidenceConfidence
       683  
                */
       684  
               public Confidence getEvidenceConfidence() {
       685  10
                   return evidenceConfidence;
       686  
       429  
           private boolean equalsIgnoreCaseAndNonAlpha(String l, String r) {
       430  225
               if (l == null || r == null) {
       431  0
                   return false;
       432  
               }
       687  
       433  
       
       688  
               /**
       689  
                * Set the value of evidenceConfidence
       690  
                *
       691  
                * @param evidenceConfidence new value of evidenceConfidence
       692  
                */
       693  
               public void setEvidenceConfidence(Confidence evidenceConfidence) {
       694  0
                   this.evidenceConfidence = evidenceConfidence;
       695  0
               }
       696  
               /**
       697  
                * The confidence whether this is an exact match, or a best guess.
       698  
                */
       699  
               private IdentifierConfidence confidence;
       700  
       434  225
               final String left = l.replaceAll(CLEANSE_NONALPHA_RX, "");
       435  225
               final String right = r.replaceAll(CLEANSE_NONALPHA_RX, "");
       436  225
               return left.equalsIgnoreCase(right);
       437  
           }
       438  
       
       701  
               /**
       702  
                * Get the value of confidence.
       703  
                *
       704  
                * @return the value of confidence
       705  
                */
       706  
               public IdentifierConfidence getConfidence() {
       707  12
                   return confidence;
       708  
       439  
           /**
       440  
            * Ensures that the CPE Identified matches the dependency. This validates
       441  
            * that the product, vendor, and version information for the CPE are
       442  
            * contained within the dependencies evidence.
       443  
            *
       444  
            * @param entry a CPE entry.
       445  
            * @param dependency the dependency that the CPE entries could be for.
       446  
            * @return whether or not the entry is valid.
       447  
            */
       448  
           private boolean verifyEntry(final IndexEntry entry, final Dependency dependency) {
       449  20
               boolean isValid = false;
       450  
       
       451  
               //TODO - does this nullify some of the fuzzy matching that happens in the lucene search?
       452  
               // for instance CPE some-component and in the evidence we have SomeComponent.
       453  20
               if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct())
       454  4
                       && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) {
       455  
                   //&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion())
       456  4
                   isValid = true;
       457  
               }
       709  
       458  20
               return isValid;
       459  
           }
       460  
       
       710  
               /**
       711  
                * Set the value of confidence.
       712  
                *
       713  
                * @param confidence new value of confidence
       714  
                */
       715  
               public void setConfidence(IdentifierConfidence confidence) {
       716  0
                   this.confidence = confidence;
       717  0
               }
       718  
               /**
       719  
                * The CPE identifier.
       720  
                */
       721  
               private Identifier identifier;
       722  
       
       723  
               /**
       724  
                * Get the value of identifier.
       725  
                *
       726  
                * @return the value of identifier
       727  
                */
       728  
               public Identifier getIdentifier() {
       729  3
                   return identifier;
       730  
       461  
           /**
       462  
            * Used to determine if the EvidenceCollection contains a specific string.
       463  
            *
       464  
            * @param ec an EvidenceCollection
       465  
            * @param text the text to search for
       466  
            * @return whether or not the EvidenceCollection contains the string
       467  
            */
       468  
           private boolean collectionContainsString(EvidenceCollection ec, String text) {
       469  
               //TODO - likely need to change the split... not sure if this will work for CPE with special chars
       470  24
               if (text == null) {
       471  0
                   return false;
       472  
               }
       731  
       
       732  
               /**
       733  
                * Set the value of identifier.
       734  
                *
       735  
                * @param identifier new value of identifier
       736  
                */
       737  
               public void setIdentifier(Identifier identifier) {
       738  0
                   this.identifier = identifier;
       739  0
               }
       740  
               //</editor-fold>
       741  
               //<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals">
       742  
       
       743  
               /**
       744  
                * Standard toString() implementation.
       745  
                *
       746  
                * @return the string representation of the object
       747  
                */
       748  
               @Override
       749  
               public String toString() {
       750  0
                   return "IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence
       751  
                           + ", confidence=" + confidence + ", identifier=" + identifier + '}';
       752  
               }
       753  
       
       754  
               /**
       755  
                * Standard hashCode() implementation.
       756  
                *
       757  
                * @return the hashCode
       758  
                */
       759  
               @Override
       760  
               public int hashCode() {
       761  0
                   int hash = 5;
       762  0
                   hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0);
       763  0
                   hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0);
       764  0
                   hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0);
       765  0
                   return hash;
       766  
               }
       767  
       
       768  
               /**
       769  
                * Standard equals implementation.
       770  
                *
       771  
                * @param obj the object to compare
       772  
                * @return true if the objects are equal, otherwise false
       773  
                */
       774  
               @Override
       775  
               public boolean equals(Object obj) {
       776  0
                   if (obj == null) {
       777  0
                       return false;
       778  
                   }
       779  0
                   if (getClass() != obj.getClass()) {
       780  0
                       return false;
       781  
                   }
       782  0
                   final IdentifierMatch other = (IdentifierMatch) obj;
       783  0
                   if (this.evidenceConfidence != other.evidenceConfidence) {
       784  0
                       return false;
       785  
                   }
       786  0
                   if (this.confidence != other.confidence) {
       787  0
                       return false;
       788  
                   }
       789  0
                   if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) {
       790  0
                       return false;
       791  
                   }
       792  0
                   return true;
       793  
               }
       794  
               //</editor-fold>
       795  
       
       796  
               /**
       797  
                * Standard implementation of compareTo that compares identifier
       798  
                * confidence, evidence confidence, and then the identifier.
       799  
                *
       800  
                * @param o the IdentifierMatch to compare to
       801  
                * @return the natural ordering of IdentifierMatch
       802  
                */
       803  
               @Override
       804  
               public int compareTo(IdentifierMatch o) {
       805  12
                   return new CompareToBuilder()
       806  6
                           .append(confidence, o.confidence)
       807  6
                           .append(evidenceConfidence, o.evidenceConfidence)
       808  6
                           .append(identifier, o.identifier)
       809  6
                           .toComparison();
       810  
       473  24
               final String[] words = text.split("[\\s_-]");
       474  24
               final List<String> list = new ArrayList<String>();
       475  24
               String tempWord = null;
       476  85
               for (String word : words) {
       477  
                   /*
       811  
                   int conf = this.confidence.compareTo(o.confidence);
       812  
                   if (conf == 0) {
       813  
                       conf = this.evidenceConfidence.compareTo(o.evidenceConfidence);
       814  
                       if (conf == 0) {
       815  
                           conf = identifier.compareTo(o.identifier);
       816  
                       }
       817  
                   }
       818  
                   return conf;
       819  
       478  
                    single letter words should be concatenated with the next word.
       479  
                    so { "m", "core", "sample" } -> { "mcore", "sample" }
       480  
                    */
       820  
       481  61
                   if (tempWord != null) {
       482  2
                       list.add(tempWord + word);
       483  2
                       tempWord = null;
       484  59
                   } else if (word.length() <= 2) {
       485  2
                       tempWord = word;
       486  
                   } else {
       487  57
                       list.add(word);
       488  
                   }
       489  
               }
       821  
       490  24
               if (tempWord != null) {
       491  0
                   if (!list.isEmpty()) {
       492  0
                       final String tmp = list.get(list.size() - 1) + tempWord;
       493  0
                       list.add(tmp);
       494  0
                   } else {
       495  0
                       list.add(tempWord);
       496  
                   }
       497  
               }
       498  24
               if (list.isEmpty()) {
       499  0
                   return false;
       500  
               }
       501  24
               boolean contains = true;
       502  24
               for (String word : list) {
       503  59
                   contains &= ec.containsUsedString(word);
       504  59
               }
       505  24
               return contains;
       506  
           }
       507  
       
       508  
           /**
       509  
            * Analyzes a dependency and attempts to determine if there are any CPE
       510  
            * identifiers for this dependency.
       511  
            *
       512  
            * @param dependency The Dependency to analyze.
       513  
            * @param engine The analysis engine
       514  
            * @throws AnalysisException is thrown if there is an issue analyzing the
       515  
            * dependency.
       516  
            */
       517  
           @Override
       518  
           public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException {
       519  
               try {
       520  4
                   determineCPE(dependency);
       521  0
               } catch (CorruptIndexException ex) {
       522  0
                   throw new AnalysisException("CPE Index is corrupt.", ex);
       523  0
               } catch (IOException ex) {
       524  0
                   throw new AnalysisException("Failure opening the CPE Index.", ex);
       525  0
               } catch (ParseException ex) {
       526  0
                   throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex);
       527  4
               }
       528  4
           }
       529  
       
       530  
           /**
       531  
            * Retrieves a list of CPE values from the CveDB based on the vendor and
       532  
            * product passed in. The list is then validated to find only CPEs that are
       533  
            * valid for the given dependency. It is possible that the CPE identified is
       534  
            * a best effort "guess" based on the vendor, product, and version
       535  
            * information.
       536  
            *
       537  
            * @param dependency the Dependency being analyzed
       538  
            * @param vendor the vendor for the CPE being analyzed
       539  
            * @param product the product for the CPE being analyzed
       540  
            * @param currentConfidence the current confidence being used during
       541  
            * analysis
       542  
            * @return <code>true</code> if an identifier was added to the dependency;
       543  
            * otherwise <code>false</code>
       544  
            * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
       545  
            */
       546  
           protected boolean determineIdentifiers(Dependency dependency, String vendor, String product,
       547  
                   Confidence currentConfidence) throws UnsupportedEncodingException {
       548  4
               final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product);
       549  4
               DependencyVersion bestGuess = new DependencyVersion("-");
       550  4
               Confidence bestGuessConf = null;
       551  4
               boolean hasBroadMatch = false;
       552  4
               final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
       553  
       
       554  
               //TODO the following algorithm incorrectly identifies things as a lower version
       555  
               // if there lower confidence evidence when the current (highest) version number
       556  
               // is newer then anything in the NVD.
       557  20
               for (Confidence conf : Confidence.values()) {
       558  16
                   for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
       559  16
                       final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
       560  16
                       if (evVer == null) {
       561  4
                           continue;
       562  
                       }
       563  12
                       for (VulnerableSoftware vs : cpes) {
       564  
                           DependencyVersion dbVer;
       565  390
                           if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) {
       566  96
                               dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate());
       567  
                           } else {
       568  294
                               dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
       569  
                           }
       570  390
                           if (dbVer == null) { //special case, no version specified - everything is vulnerable
       571  0
                               hasBroadMatch = true;
       572  0
                               final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
       573  0
                               final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf);
       574  0
                               collected.add(match);
       575  0
                           } else if (evVer.equals(dbVer)) { //yeah! exact match
       576  6
                               final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
       577  6
                               final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
       578  6
                               collected.add(match);
       579  
       
       580  
                               //TODO the following isn't quite right is it? need to think about this guessing game a bit more.
       581  6
                           } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
       582  378
                                   && evVer.matchesAtLeastThreeLevels(dbVer)) {
       583  48
                               if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
       584  2
                                   if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
       585  2
                                       bestGuess = dbVer;
       586  2
                                       bestGuessConf = conf;
       587  
                                   }
       588  
                               }
       589  
                           }
       590  390
                       }
       591  12
                       if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
       592  2
                           if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) {
       593  2
                               bestGuess = evVer;
       594  2
                               bestGuessConf = conf;
       595  
                           }
       596  
                       }
       597  12
                   }
       598  
               }
       599  4
               final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString());
       600  4
               String url = null;
       601  4
               if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess.
       602  0
                   final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product);
       603  0
                   url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8"));
       604  
               }
       605  4
               if (bestGuessConf == null) {
       606  0
                   bestGuessConf = Confidence.LOW;
       607  
               }
       608  4
               final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf);
       609  4
               collected.add(match);
       610  
       
       611  4
               Collections.sort(collected);
       612  4
               final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence();
       613  4
               final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence();
       614  4
               boolean identifierAdded = false;
       615  4
               for (IdentifierMatch m : collected) {
       616  10
                   if (bestIdentifierQuality.equals(m.getConfidence())
       617  8
                           && bestEvidenceQuality.equals(m.getEvidenceConfidence())) {
       618  4
                       final Identifier i = m.getIdentifier();
       619  4
                       if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) {
       620  2
                           i.setConfidence(Confidence.LOW);
       621  
                       } else {
       622  2
                           i.setConfidence(bestEvidenceQuality);
       623  
                       }
       624  4
                       dependency.addIdentifier(i);
       625  4
                       identifierAdded = true;
       626  
                   }
       627  10
               }
       628  4
               return identifierAdded;
       629  
           }
       630  
       
       631  
           /**
       632  
            * The confidence whether the identifier is an exact match, or a best guess.
       633  
            */
       634  4
           private enum IdentifierConfidence {
       635  
       
       636  
               /**
       637  
                * An exact match for the CPE.
       638  
                */
       639  1
               EXACT_MATCH,
       640  
               /**
       641  
                * A best guess for the CPE.
       642  
                */
       643  1
               BEST_GUESS,
       644  
               /**
       645  
                * The entire vendor/product group must be added (without a guess at
       646  
                * version) because there is a CVE with a VS that only specifies
       647  
                * vendor/product.
       648  
                */
       649  1
               BROAD_MATCH
       650  
           }
       651  
       
       652  
           /**
       653  
            * A simple object to hold an identifier and carry information about the
       654  
            * confidence in the identifier.
       655  
            */
       656  6
           private static class IdentifierMatch implements Comparable<IdentifierMatch> {
       657  
       
       658  
               /**
       659  
                * Constructs an IdentifierMatch.
       660  
                *
       661  
                * @param type the type of identifier (such as CPE)
       662  
                * @param value the value of the identifier
       663  
                * @param url the URL of the identifier
       664  
                * @param identifierConfidence the confidence in the identifier: best
       665  
                * guess or exact match
       666  
                * @param evidenceConfidence the confidence of the evidence used to find
       667  
                * the identifier
       668  
                */
       669  10
               IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) {
       670  10
                   this.identifier = new Identifier(type, value, url);
       671  10
                   this.confidence = identifierConfidence;
       672  10
                   this.evidenceConfidence = evidenceConfidence;
       673  10
               }
       674  
               //<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier">
       675  
               /**
       676  
                * The confidence in the evidence used to identify this match.
       677  
                */
       678  
               private Confidence evidenceConfidence;
       679  
       
       680  
               /**
       681  
                * Get the value of evidenceConfidence
       682  
                *
       683  
                * @return the value of evidenceConfidence
       684  
                */
       685  
               public Confidence getEvidenceConfidence() {
       686  12
                   return evidenceConfidence;
       687  
               }
       688  
       
       689  
               /**
       690  
                * Set the value of evidenceConfidence
       691  
                *
       692  
                * @param evidenceConfidence new value of evidenceConfidence
       693  
                */
       694  
               public void setEvidenceConfidence(Confidence evidenceConfidence) {
       695  0
                   this.evidenceConfidence = evidenceConfidence;
       696  0
               }
       697  
               /**
       698  
                * The confidence whether this is an exact match, or a best guess.
       699  
                */
       700  
               private IdentifierConfidence confidence;
       701  
       
       702  
               /**
       703  
                * Get the value of confidence.
       704  
                *
       705  
                * @return the value of confidence
       706  
                */
       707  
               public IdentifierConfidence getConfidence() {
       708  14
                   return confidence;
       709  
               }
       710  
       
       711  
               /**
       712  
                * Set the value of confidence.
       713  
                *
       714  
                * @param confidence new value of confidence
       715  
                */
       716  
               public void setConfidence(IdentifierConfidence confidence) {
       717  0
                   this.confidence = confidence;
       718  0
               }
       719  
               /**
       720  
                * The CPE identifier.
       721  
                */
       722  
               private Identifier identifier;
       723  
       
       724  
               /**
       725  
                * Get the value of identifier.
       726  
                *
       727  
                * @return the value of identifier
       728  
                */
       729  
               public Identifier getIdentifier() {
       730  4
                   return identifier;
       731  
               }
       732  
       
       733  
               /**
       734  
                * Set the value of identifier.
       735  
                *
       736  
                * @param identifier new value of identifier
       737  
                */
       738  
               public void setIdentifier(Identifier identifier) {
       739  0
                   this.identifier = identifier;
       740  0
               }
       741  
               //</editor-fold>
       742  
               //<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals">
       743  
       
       744  
               /**
       745  
                * Standard toString() implementation.
       746  
                *
       747  
                * @return the string representation of the object
       748  
                */
       749  
               @Override
       750  
               public String toString() {
       751  0
                   return "IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence
       752  
                           + ", confidence=" + confidence + ", identifier=" + identifier + '}';
       753  
               }
       754  
       
       755  
               /**
       756  
                * Standard hashCode() implementation.
       757  
                *
       758  
                * @return the hashCode
       759  
                */
       760  
               @Override
       761  
               public int hashCode() {
       762  0
                   int hash = 5;
       763  0
                   hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0);
       764  0
                   hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0);
       765  0
                   hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0);
       766  0
                   return hash;
       767  
               }
       768  
       
       769  
               /**
       770  
                * Standard equals implementation.
       771  
                *
       772  
                * @param obj the object to compare
       773  
                * @return true if the objects are equal, otherwise false
       774  
                */
       775  
               @Override
       776  
               public boolean equals(Object obj) {
       777  0
                   if (obj == null) {
       778  0
                       return false;
       779  
                   }
       780  0
                   if (getClass() != obj.getClass()) {
       781  0
                       return false;
       782  
                   }
       783  0
                   final IdentifierMatch other = (IdentifierMatch) obj;
       784  0
                   if (this.evidenceConfidence != other.evidenceConfidence) {
       785  0
                       return false;
       786  
                   }
       787  0
                   if (this.confidence != other.confidence) {
       788  0
                       return false;
       789  
                   }
       790  0
                   if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) {
       791  0
                       return false;
       792  
                   }
       793  0
                   return true;
       794  
               }
       795  
               //</editor-fold>
       796  
       
       797  
               /**
       798  
                * Standard implementation of compareTo that compares identifier
       799  
                * confidence, evidence confidence, and then the identifier.
       800  
                *
       801  
                * @param o the IdentifierMatch to compare to
       802  
                * @return the natural ordering of IdentifierMatch
       803  
                */
       804  
               @Override
       805  
               public int compareTo(IdentifierMatch o) {
       806  12
                   return new CompareToBuilder()
       807  6
                           .append(confidence, o.confidence)
       808  6
                           .append(evidenceConfidence, o.evidenceConfidence)
       809  6
                           .append(identifier, o.identifier)
       810  6
                           .toComparison();
       811  
                   /*
       812  
                   int conf = this.confidence.compareTo(o.confidence);
       813  
                   if (conf == 0) {
       814  
                       conf = this.evidenceConfidence.compareTo(o.evidenceConfidence);
       815  
                       if (conf == 0) {
       816  
                           conf = identifier.compareTo(o.identifier);
       817  
                       }
       818  
                   }
       819  
                   return conf;
       820  
                    */
       821  
               }
       822  
           }
       823  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CentralAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CentralAnalyzer.html index 802ad4e38..25da0013a 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CentralAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CentralAnalyzer.html @@ -119,7 +119,7 @@
        * @author colezlaw
       51  
        */
      -  52  6
       public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
      +  52  8
       public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
       53  
       
       54   @@ -168,7 +168,7 @@
            * determine if such an error has occurred.
       77  
            */
      -  78  6
           private boolean errorFlag = false;
      +  78  8
           private volatile boolean errorFlag = false;
       79  
       
       80   @@ -185,7 +185,7 @@
            * Field indicating if the analyzer is enabled.
       86  
            */
      -  87  6
           private final boolean enabled = checkEnabled();
      +  87  8
           private final boolean enabled = checkEnabled();
       88  
       
       89   @@ -221,16 +221,16 @@
            */
       105  
           private boolean checkEnabled() {
      -  106  6
               boolean retval = false;
      +  106  8
               boolean retval = false;
       107  
       
       108  
               try {
      -  109  6
                   if (Settings.getBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED)) {
      -  110  4
                       if (!Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)
      +  109  8
                   if (Settings.getBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED)) {
      +  110  6
                       if (!Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)
       111  0
                               || NexusAnalyzer.DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL))) {
      -  112  4
                           LOGGER.debug("Enabling the Central analyzer");
      -  113  4
                           retval = true;
      +  112  6
                           LOGGER.debug("Enabling the Central analyzer");
      +  113  6
                           retval = true;
       114  
                       } else {
       115  0
                           LOGGER.info("Nexus analyzer is enabled, disabling the Central Analyzer");
      @@ -243,8 +243,8 @@
                   }
       120  0
               } catch (InvalidSettingException ise) {
       121  0
                   LOGGER.warn("Invalid setting. Disabling the Central analyzer");
      -  122  6
               }
      -  123  6
               return retval;
      +  122  8
               }
      +  123  8
               return retval;
       124  
           }
       125   @@ -294,7 +294,7 @@
           @Override
       153  
           public String getName() {
      -  154  16
               return ANALYZER_NAME;
      +  154  22
               return ANALYZER_NAME;
       155  
           }
       156   @@ -315,7 +315,7 @@
           @Override
       164  
           protected String getAnalyzerEnabledSettingKey() {
      -  165  6
               return Settings.KEYS.ANALYZER_CENTRAL_ENABLED;
      +  165  8
               return Settings.KEYS.ANALYZER_CENTRAL_ENABLED;
       166  
           }
       167   @@ -334,7 +334,7 @@
           @Override
       174  
           public AnalysisPhase getAnalysisPhase() {
      -  175  4
               return ANALYSIS_PHASE;
      +  175  6
               return ANALYSIS_PHASE;
       176  
           }
       177   @@ -352,7 +352,7 @@
           @Override
       184  
           protected FileFilter getFileFilter() {
      -  185  859
               return FILTER;
      +  185  862
               return FILTER;
       186  
           }
       187   @@ -443,6 +443,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer.html index 887ff7670..d08378f5d 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CocoaPodsAnalyzer.html @@ -103,7 +103,7 @@
        */
       43  
       @Experimental
      -  44  12
       public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
      +  44  14
       public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
       45  
       
       46   @@ -175,7 +175,7 @@
           @Override
       81  
           protected FileFilter getFileFilter() {
      -  82  860
               return PODSPEC_FILTER;
      +  82  863
               return PODSPEC_FILTER;
       83  
           }
       84   @@ -203,7 +203,7 @@
           @Override
       96  
           public String getName() {
      -  97  15
               return ANALYZER_NAME;
      +  97  21
               return ANALYZER_NAME;
       98  
           }
       99   @@ -222,7 +222,7 @@
           @Override
       106  
           public AnalysisPhase getAnalysisPhase() {
      -  107  4
               return ANALYSIS_PHASE;
      +  107  6
               return ANALYSIS_PHASE;
       108  
           }
       109   @@ -243,7 +243,7 @@
           @Override
       117  
           protected String getAnalyzerEnabledSettingKey() {
      -  118  12
               return Settings.KEYS.ANALYZER_COCOAPODS_ENABLED;
      +  118  14
               return Settings.KEYS.ANALYZER_COCOAPODS_ENABLED;
       119  
           }
       120   @@ -380,6 +380,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer.html index 509d17f64..cafbcee75 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      ComposerLockAnalyzer
      78%
      32/41
      75%
      3/4
      2.167
      ComposerLockAnalyzer
      86%
      39/45
      75%
      3/4
      2.429
       
      @@ -70,31 +70,31 @@  26  
       import org.owasp.dependencycheck.dependency.Dependency;
       27   -
       import org.owasp.dependencycheck.utils.Checksum;
      -  28   -
       import org.owasp.dependencycheck.utils.FileFilterBuilder;
      -  29   -
       import org.owasp.dependencycheck.utils.Settings;
      -  30   -
       import org.slf4j.Logger;
      -  31   -
       import org.slf4j.LoggerFactory;
      -  32   -
       
      -  33   -
       import java.io.FileFilter;
      -  34   -
       import java.io.FileInputStream;
      -  35   -
       import java.io.FileNotFoundException;
      -  36   -
       import java.nio.charset.Charset;
      -  37   -
       import java.security.MessageDigest;
      -  38   -
       import java.security.NoSuchAlgorithmException;
      -  39  
       import org.owasp.dependencycheck.exception.InitializationException;
      +  28   +
       import org.owasp.dependencycheck.utils.Checksum;
      +  29   +
       import org.owasp.dependencycheck.utils.FileFilterBuilder;
      +  30   +
       import org.owasp.dependencycheck.utils.Settings;
      +  31   +
       import org.slf4j.Logger;
      +  32   +
       import org.slf4j.LoggerFactory;
      +  33   +
       
      +  34   +
       import java.io.FileFilter;
      +  35   +
       import java.io.FileInputStream;
      +  36   +
       import java.io.FileNotFoundException;
      +  37   +
       import java.nio.charset.Charset;
      +  38   +
       import java.security.MessageDigest;
      +  39   +
       import java.security.NoSuchAlgorithmException;
       40  
       
       41   @@ -109,7 +109,7 @@
        */
       46  
       @Experimental
      -  47  9
       public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer {
      +  47  13
       public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer {
       48  
       
       49   @@ -164,7 +164,7 @@
           @Override
       75  
           protected FileFilter getFileFilter() {
      -  76  860
               return FILE_FILTER;
      +  76  863
               return FILE_FILTER;
       77  
           }
       78   @@ -187,141 +187,155 @@
           protected void initializeFileTypeAnalyzer() throws InitializationException {
       87  
               try {
      -  88  3
                   sha1 = MessageDigest.getInstance("SHA1");
      -  89  0
               } catch (NoSuchAlgorithmException ex) {
      -  90  0
                   setEnabled(false);
      -  91  0
                   throw new InitializationException("Unable to create SHA1 MmessageDigest", ex);
      -  92  3
               }
      -  93  3
           }
      +  88  5
                   getSha1MessageDigest();
      +  89  1
               } catch (IllegalStateException ex) {
      +  90  1
                   setEnabled(false);
      +  91  1
                   throw new InitializationException("Unable to create SHA1 MessageDigest", ex);
      +  92  4
               }
      +  93  4
           }
       94  
       
       95  
           /**
       96   -
            * The MessageDigest for calculating a new digest for the new dependencies
      -  97   -
            * added.
      -  98   -
            */
      -  99  9
           private MessageDigest sha1 = null;
      -  100   -
       
      -  101   -
           /**
      -  102  
            * Entry point for the analyzer.
      -  103   +  97  
            *
      -  104   +  98  
            * @param dependency the dependency to analyze
      -  105   +  99  
            * @param engine the engine scanning
      -  106   +  100  
            * @throws AnalysisException if there's a failure during analysis
      -  107   +  101  
            */
      -  108   +  102  
           @Override
      -  109   +  103  
           protected void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
      -  110  1
               FileInputStream fis = null;
      -  111   +  104  1
               FileInputStream fis = null;
      +  105  
               try {
      -  112  1
                   fis = new FileInputStream(dependency.getActualFile());
      -  113  1
                   final ComposerLockParser clp = new ComposerLockParser(fis);
      -  114  1
                   LOGGER.info("Checking composer.lock file {}", dependency.getActualFilePath());
      -  115  1
                   clp.process();
      -  116  1
                   for (ComposerDependency dep : clp.getDependencies()) {
      -  117  30
                       final Dependency d = new Dependency(dependency.getActualFile());
      -  118  30
                       d.setDisplayFileName(String.format("%s:%s/%s", dependency.getDisplayFileName(), dep.getGroup(), dep.getProject()));
      -  119  30
                       final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject());
      -  120  30
                       d.setFilePath(filePath);
      -  121  30
                       d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset()))));
      -  122  30
                       d.getVendorEvidence().addEvidence(COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST);
      -  123  30
                       d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST);
      -  124  30
                       d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST);
      -  125  30
                       LOGGER.info("Adding dependency {}", d);
      -  126  30
                       engine.getDependencies().add(d);
      -  127  30
                   }
      -  128  0
               } catch (FileNotFoundException fnfe) {
      -  129  0
                   LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath());
      -  130  0
               } catch (ComposerException ce) {
      -  131  0
                   LOGGER.warn("Error parsing composer.json {}", dependency.getActualFilePath(), ce);
      -  132   +  106  1
                   fis = new FileInputStream(dependency.getActualFile());
      +  107  1
                   final ComposerLockParser clp = new ComposerLockParser(fis);
      +  108  1
                   LOGGER.info("Checking composer.lock file {}", dependency.getActualFilePath());
      +  109  1
                   clp.process();
      +  110  1
                   for (ComposerDependency dep : clp.getDependencies()) {
      +  111  30
                       final Dependency d = new Dependency(dependency.getActualFile());
      +  112  30
                       d.setDisplayFileName(String.format("%s:%s/%s", dependency.getDisplayFileName(), dep.getGroup(), dep.getProject()));
      +  113  30
                       final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject());
      +  114  30
                       final MessageDigest sha1 = getSha1MessageDigest();
      +  115  30
                       d.setFilePath(filePath);
      +  116  30
                       d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset()))));
      +  117  30
                       d.getVendorEvidence().addEvidence(COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST);
      +  118  30
                       d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST);
      +  119  30
                       d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST);
      +  120  30
                       LOGGER.info("Adding dependency {}", d);
      +  121  30
                       engine.getDependencies().add(d);
      +  122  30
                   }
      +  123  0
               } catch (FileNotFoundException fnfe) {
      +  124  0
                   LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath());
      +  125  0
               } catch (ComposerException ce) {
      +  126  0
                   LOGGER.warn("Error parsing composer.json {}", dependency.getActualFilePath(), ce);
      +  127  
               } finally {
      -  133  1
                   if (fis != null) {
      -  134   +  128  1
                   if (fis != null) {
      +  129  
                       try {
      -  135  1
                           fis.close();
      -  136  0
                       } catch (Exception e) {
      -  137  0
                           LOGGER.debug("Unable to close file", e);
      -  138  1
                       }
      -  139   +  130  1
                           fis.close();
      +  131  0
                       } catch (Exception e) {
      +  132  0
                           LOGGER.debug("Unable to close file", e);
      +  133  1
                       }
      +  134  
                   }
      -  140   +  135  
               }
      -  141  1
           }
      -  142   +  136  1
           }
      +  137  
       
      -  143   +  138  
           /**
      -  144   +  139  
            * Gets the key to determine whether the analyzer is enabled.
      -  145   +  140  
            *
      -  146   +  141  
            * @return the key specifying whether the analyzer is enabled
      -  147   +  142  
            */
      -  148   +  143  
           @Override
      -  149   +  144  
           protected String getAnalyzerEnabledSettingKey() {
      -  150  9
               return Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED;
      -  151   +  145  13
               return Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED;
      +  146  
           }
      -  152   +  147  
       
      -  153   +  148  
           /**
      -  154   +  149  
            * Returns the analyzer's name.
      -  155   +  150  
            *
      -  156   +  151  
            * @return the analyzer's name
      -  157   +  152  
            */
      -  158   +  153  
           @Override
      -  159   +  154  
           public String getName() {
      -  160  15
               return ANALYZER_NAME;
      -  161   +  155  21
               return ANALYZER_NAME;
      +  156  
           }
      -  162   +  157  
       
      -  163   +  158  
           /**
      -  164   +  159  
            * Returns the phase this analyzer should run under.
      -  165   +  160  
            *
      -  166   +  161  
            * @return the analysis phase
      -  167   +  162  
            */
      -  168   +  163  
           @Override
      -  169   +  164  
           public AnalysisPhase getAnalysisPhase() {
      -  170  4
               return AnalysisPhase.INFORMATION_COLLECTION;
      -  171   +  165  6
               return AnalysisPhase.INFORMATION_COLLECTION;
      +  166  
           }
      +  167   +
       
      +  168   +
           /**
      +  169   +
            * Returns the sha1 message digest.
      +  170   +
            *
      +  171   +
            * @return the sha1 message digest
       172   +
            */
      +  173   +
           private MessageDigest getSha1MessageDigest() {
      +  174   +
               try {
      +  175  35
                   return MessageDigest.getInstance("SHA1");
      +  176  1
               } catch (NoSuchAlgorithmException e) {
      +  177  1
                   LOGGER.error(e.getMessage());
      +  178  1
                   throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e);
      +  179   +
               }
      +  180   +
           }
      +  181  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer.html index 1125a5821..bae628e0a 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer.html @@ -77,7 +77,7 @@
        * @author Jeremy Long
       30  
        */
      -  31  6
       public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer {
      +  31  8
       public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer {
       32  
       
       33   @@ -113,7 +113,7 @@
           @Override
       49  
           public String getName() {
      -  50  16
               return ANALYZER_NAME;
      +  50  26
               return ANALYZER_NAME;
       51  
           }
       52   @@ -132,7 +132,7 @@
           @Override
       59  
           public AnalysisPhase getAnalysisPhase() {
      -  60  4
               return ANALYSIS_PHASE;
      +  60  6
               return ANALYSIS_PHASE;
       61  
           }
       62   @@ -152,13 +152,13 @@  70  
       
       71  4
               for (final SuppressionRule rule : getRules()) {
      -  72  228
                   rule.process(dependency);
      -  73  228
               }
      +  72  240
                   rule.process(dependency);
      +  73  240
               }
       74  4
           }
       75  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer.html index 460a7d7ea..d9c5f2918 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      DependencyBundlingAnalyzer
      40%
      82/201
      30%
      64/212
      8
      DependencyBundlingAnalyzer
      42%
      85/201
      30%
      65/210
      7.2
       
      @@ -113,7 +113,7 @@
        * @author Jeremy Long
       48  
        */
      -  49  10
       public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Analyzer {
      +  49  13
       public class DependencyBundlingAnalyzer extends AbstractAnalyzer {
       50  
       
       51   @@ -135,144 +135,161 @@
            */
       60  1
           private static final Pattern STARTING_TEXT_PATTERN = Pattern.compile("^[a-zA-Z0-9]*");
       61   -
           /**
      +
       
       62   -
            * a flag indicating if this analyzer has run. This analyzer only runs once.
      +
           /**
       63   +
            * a flag indicating if this analyzer has run. This analyzer only runs once.
      +  64  
            */
      -  64  10
           private boolean analyzed = false;
      -  65   -
           //</editor-fold>
      +  65  13
           private boolean analyzed = false;
       66   -
           //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
      +
       
       67  
           /**
       68   -
            * The name of the analyzer.
      +
            * Returns a flag indicating if this analyzer has run. This analyzer only
       69   -
            */
      +
            * runs once. Note this is currently only used in the unit tests.
       70   -
           private static final String ANALYZER_NAME = "Dependency Bundling Analyzer";
      +
            *
       71   -
           /**
      +
            * @return a flag indicating if this analyzer has run. This analyzer only
       72   -
            * The phase that this analyzer is intended to run in.
      +
            * runs once
       73  
            */
      -  74  1
           private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS;
      -  75   -
       
      +  74   +
           protected boolean getAnalyzed() {
      +  75  3
               return analyzed;
       76   -
           /**
      +
           }
       77   -
            * Returns the name of the analyzer.
      +
       
       78   -
            *
      -  79   -
            * @return the name of the analyzer.
      -  80   -
            */
      -  81   -
           @Override
      -  82   -
           public String getName() {
      -  83  17
               return ANALYZER_NAME;
      -  84   -
           }
      -  85   -
       
      -  86   -
           /**
      -  87   -
            * Returns the phase that the analyzer is intended to run in.
      -  88   -
            *
      -  89   -
            * @return the phase that the analyzer is intended to run in.
      -  90   -
            */
      -  91   -
           @Override
      -  92   -
           public AnalysisPhase getAnalysisPhase() {
      -  93  5
               return ANALYSIS_PHASE;
      -  94   -
           }
      -  95  
           //</editor-fold>
      -  96   -
       
      -  97   +  79   +
           //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
      +  80  
           /**
      +  81   +
            * The name of the analyzer.
      +  82   +
            */
      +  83   +
           private static final String ANALYZER_NAME = "Dependency Bundling Analyzer";
      +  84   +
           /**
      +  85   +
            * The phase that this analyzer is intended to run in.
      +  86   +
            */
      +  87  1
           private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS;
      +  88   +
       
      +  89   +
           /**
      +  90   +
            * Returns the name of the analyzer.
      +  91   +
            *
      +  92   +
            * @return the name of the analyzer.
      +  93   +
            */
      +  94   +
           @Override
      +  95   +
           public String getName() {
      +  96  27
               return ANALYZER_NAME;
      +  97   +
           }
       98   -
            * Analyzes a set of dependencies. If they have been found to have the same
      +
       
       99   -
            * base path and the same set of identifiers they are likely related. The
      +
           /**
       100   -
            * related dependencies are bundled into a single reportable item.
      +
            * Returns the phase that the analyzer is intended to run in.
       101  
            *
       102   -
            * @param ignore this analyzer ignores the dependency being analyzed
      +
            * @return the phase that the analyzer is intended to run in.
       103   -
            * @param engine the engine that is scanning the dependencies
      -  104   -
            * @throws AnalysisException is thrown if there is an error reading the JAR
      -  105   -
            * file.
      -  106  
            */
      -  107   +  104  
           @Override
      +  105   +
           public AnalysisPhase getAnalysisPhase() {
      +  106  7
               return ANALYSIS_PHASE;
      +  107   +
           }
       108   -
           public void analyze(Dependency ignore, Engine engine) throws AnalysisException {
      -  109  4
               if (!analyzed) {
      -  110  2
                   analyzed = true;
      -  111  2
                   final Set<Dependency> dependenciesToRemove = new HashSet<Dependency>();
      -  112  2
                   final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator();
      +
           //</editor-fold>
      +  109   +
       
      +  110   +
           /**
      +  111   +
            * Does not support parallel processing as it only runs once and then
      +  112   +
            * operates on <em>all</em> dependencies.
       113   -
                   //for (Dependency nextDependency : engine.getDependencies()) {
      -  114  6
                   while (mainIterator.hasNext()) {
      -  115  4
                       final Dependency dependency = mainIterator.next();
      -  116  4
                       if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) {
      -  117  2
                           final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
      -  118  4
                           while (subIterator.hasNext()) {
      -  119  2
                               final Dependency nextDependency = subIterator.next();
      -  120  2
                               Dependency main = null;
      -  121  2
                               if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath())
      -  122  0
                                       && !containedInWar(nextDependency.getFilePath())) {
      -  123  0
                                   if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
      -  124  0
                                       mergeDependencies(dependency, nextDependency, dependenciesToRemove);
      +
            *
      +  114   +
            * @return whether or not parallel processing is enabled
      +  115   +
            * @see #analyze(Dependency, Engine)
      +  116   +
            */
      +  117   +
           @Override
      +  118   +
           public boolean supportsParallelProcessing() {
      +  119  2
               return false;
      +  120   +
           }
      +  121   +
       
      +  122   +
           /**
      +  123   +
            * Analyzes a set of dependencies. If they have been found to have the same
      +  124   +
            * base path and the same set of identifiers they are likely related. The
       125   -
                                   } else {
      -  126  0
                                       mergeDependencies(nextDependency, dependency, dependenciesToRemove);
      -  127  0
                                       break; //since we merged into the next dependency - skip forward to the next in mainIterator
      +
            * related dependencies are bundled into a single reportable item.
      +  126   +
            *
      +  127   +
            * @param ignore this analyzer ignores the dependency being analyzed
       128   -
                                   }
      -  129  2
                               } else if (isShadedJar(dependency, nextDependency)) {
      -  130  0
                                   if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
      -  131  0
                                       mergeDependencies(nextDependency, dependency, dependenciesToRemove);
      -  132  0
                                       nextDependency.getRelatedDependencies().remove(dependency);
      -  133  0
                                       break;
      -  134   -
                                   } else {
      -  135  0
                                       mergeDependencies(dependency, nextDependency, dependenciesToRemove);
      -  136  0
                                       dependency.getRelatedDependencies().remove(nextDependency);
      -  137   -
                                   }
      -  138  2
                               } else if (cpeIdentifiersMatch(dependency, nextDependency)
      -  139  0
                                       && hasSameBasePath(dependency, nextDependency)
      -  140  0
                                       && fileNameMatch(dependency, nextDependency)) {
      -  141  0
                                   if (isCore(dependency, nextDependency)) {
      -  142  0
                                       mergeDependencies(dependency, nextDependency, dependenciesToRemove);
      -  143   -
                                   } else {
      -  144  0
                                       mergeDependencies(nextDependency, dependency, dependenciesToRemove);
      -  145  0
                                       break; //since we merged into the next dependency - skip forward to the next in mainIterator
      -  146   -
                                   }
      -  147  2
                               } else if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) {
      -  148  0
                                   if (main == dependency) {
      +
            * @param engine the engine that is scanning the dependencies
      +  129   +
            * @throws AnalysisException is thrown if there is an error reading the JAR
      +  130   +
            * file.
      +  131   +
            */
      +  132   +
           @Override
      +  133   +
           public void analyze(Dependency ignore, Engine engine) throws AnalysisException {
      +  134  8
               if (!analyzed) {
      +  135  3
                   analyzed = true;
      +  136  3
                   final Set<Dependency> dependenciesToRemove = new HashSet<Dependency>();
      +  137  3
                   final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator();
      +  138   +
                   //for (Dependency nextDependency : engine.getDependencies()) {
      +  139  7
                   while (mainIterator.hasNext()) {
      +  140  4
                       final Dependency dependency = mainIterator.next();
      +  141  4
                       if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) {
      +  142  2
                           final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
      +  143  4
                           while (subIterator.hasNext()) {
      +  144  2
                               final Dependency nextDependency = subIterator.next();
      +  145  2
                               Dependency main = null;
      +  146  2
                               if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath())
      +  147  0
                                       && !containedInWar(nextDependency.getFilePath())) {
      +  148  0
                                   if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
       149  0
                                       mergeDependencies(dependency, nextDependency, dependenciesToRemove);
       150  
                                   } else {
      @@ -280,315 +297,305 @@  152  0
                                       break; //since we merged into the next dependency - skip forward to the next in mainIterator
       153  
                                   }
      -  154  2
                               } else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) {
      -  155  0
                                   if (main == dependency) {
      -  156  0
                                       mergeDependencies(dependency, nextDependency, dependenciesToRemove);
      -  157   +  154  2
                               } else if (isShadedJar(dependency, nextDependency)) {
      +  155  0
                                   if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
      +  156  0
                                       mergeDependencies(nextDependency, dependency, dependenciesToRemove);
      +  157  0
                                       nextDependency.getRelatedDependencies().remove(dependency);
      +  158  0
                                       break;
      +  159  
                                   } else {
      -  158  0
                                       mergeDependencies(nextDependency, dependency, dependenciesToRemove);
      -  159  0
                                       break; //since we merged into the next dependency - skip forward to the next in mainIterator
      -  160   +  160  0
                                       mergeDependencies(dependency, nextDependency, dependenciesToRemove);
      +  161  0
                                       dependency.getRelatedDependencies().remove(nextDependency);
      +  162  
                                   }
      -  161   -
                               }
      -  162  2
                           }
      -  163   -
                       }
      -  164  4
                   }
      -  165   -
                   //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
      -  166   -
                   // was difficult because of the inner iterator.
      -  167  2
                   engine.getDependencies().removeAll(dependenciesToRemove);
      +  163  2
                               } else if (cpeIdentifiersMatch(dependency, nextDependency)
      +  164  0
                                       && hasSameBasePath(dependency, nextDependency)
      +  165  0
                                       && fileNameMatch(dependency, nextDependency)) {
      +  166  0
                                   if (isCore(dependency, nextDependency)) {
      +  167  0
                                       mergeDependencies(dependency, nextDependency, dependenciesToRemove);
       168   -
               }
      -  169  4
           }
      -  170   -
       
      +
                                   } else {
      +  169  0
                                       mergeDependencies(nextDependency, dependency, dependenciesToRemove);
      +  170  0
                                       break; //since we merged into the next dependency - skip forward to the next in mainIterator
       171   -
           /**
      -  172   -
            * Adds the relatedDependency to the dependency's related dependencies.
      -  173   -
            *
      -  174   -
            * @param dependency the main dependency
      +
                                   }
      +  172  2
                               } else if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) {
      +  173  0
                                   if (main == dependency) {
      +  174  0
                                       mergeDependencies(dependency, nextDependency, dependenciesToRemove);
       175   -
            * @param relatedDependency a collection of dependencies to be removed from
      -  176   -
            * the main analysis loop, this is the source of dependencies to remove
      -  177   -
            * @param dependenciesToRemove a collection of dependencies that will be
      +
                                   } else {
      +  176  0
                                       mergeDependencies(nextDependency, dependency, dependenciesToRemove);
      +  177  0
                                       break; //since we merged into the next dependency - skip forward to the next in mainIterator
       178   -
            * removed from the main analysis loop, this function adds to this
      -  179   -
            * collection
      -  180   -
            */
      -  181   -
           private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) {
      -  182  0
               dependency.addRelatedDependency(relatedDependency);
      -  183  0
               final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator();
      -  184  0
               while (i.hasNext()) {
      -  185  0
                   dependency.addRelatedDependency(i.next());
      -  186  0
                   i.remove();
      -  187   -
               }
      -  188  0
               if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) {
      -  189  0
                   dependency.addAllProjectReferences(relatedDependency.getProjectReferences());
      +
                                   }
      +  179  2
                               } else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) {
      +  180  0
                                   if (main == dependency) {
      +  181  0
                                       mergeDependencies(dependency, nextDependency, dependenciesToRemove);
      +  182   +
                                   } else {
      +  183  0
                                       mergeDependencies(nextDependency, dependency, dependenciesToRemove);
      +  184  0
                                       break; //since we merged into the next dependency - skip forward to the next in mainIterator
      +  185   +
                                   }
      +  186   +
                               }
      +  187  2
                           }
      +  188   +
                       }
      +  189  4
                   }
       190   -
               }
      -  191  0
               dependenciesToRemove.add(relatedDependency);
      -  192  0
           }
      +
                   //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
      +  191   +
                   // was difficult because of the inner iterator.
      +  192  3
                   engine.getDependencies().removeAll(dependenciesToRemove);
       193   -
       
      -  194   -
           /**
      +
               }
      +  194  8
           }
       195   -
            * Attempts to trim a maven repo to a common base path. This is typically
      +
       
       196   -
            * [drive]\[repo_location]\repository\[path1]\[path2].
      +
           /**
       197   -
            *
      +
            * Adds the relatedDependency to the dependency's related dependencies.
       198   -
            * @param path the path to trim
      +
            *
       199   -
            * @return a string representing the base path.
      +
            * @param dependency the main dependency
       200   -
            */
      +
            * @param relatedDependency a collection of dependencies to be removed from
       201   -
           private String getBaseRepoPath(final String path) {
      -  202  0
               int pos = path.indexOf("repository" + File.separator) + 11;
      -  203  0
               if (pos < 0) {
      -  204  0
                   return path;
      +
            * the main analysis loop, this is the source of dependencies to remove
      +  202   +
            * @param dependenciesToRemove a collection of dependencies that will be
      +  203   +
            * removed from the main analysis loop, this function adds to this
      +  204   +
            * collection
       205   -
               }
      -  206  0
               int tmp = path.indexOf(File.separator, pos);
      -  207  0
               if (tmp <= 0) {
      -  208  0
                   return path;
      -  209   -
               }
      -  210  0
               if (tmp > 0) {
      -  211  0
                   pos = tmp + 1;
      +
            */
      +  206   +
           private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) {
      +  207  0
               dependency.addRelatedDependency(relatedDependency);
      +  208  0
               final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator();
      +  209  0
               while (i.hasNext()) {
      +  210  0
                   dependency.addRelatedDependency(i.next());
      +  211  0
                   i.remove();
       212  
               }
      -  213  0
               tmp = path.indexOf(File.separator, pos);
      -  214  0
               if (tmp > 0) {
      -  215  0
                   pos = tmp + 1;
      -  216   +  213  0
               if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) {
      +  214  0
                   dependency.addAllProjectReferences(relatedDependency.getProjectReferences());
      +  215  
               }
      -  217  0
               return path.substring(0, pos);
      +  216  0
               dependenciesToRemove.add(relatedDependency);
      +  217  0
           }
       218   -
           }
      +
       
       219   -
       
      +
           /**
       220   -
           /**
      +
            * Attempts to trim a maven repo to a common base path. This is typically
       221   -
            * Returns true if the file names (and version if it exists) of the two
      +
            * [drive]\[repo_location]\repository\[path1]\[path2].
       222   -
            * dependencies are sufficiently similar.
      +
            *
       223   -
            *
      +
            * @param path the path to trim
       224   -
            * @param dependency1 a dependency2 to compare
      +
            * @return a string representing the base path.
       225   -
            * @param dependency2 a dependency2 to compare
      +
            */
       226   -
            * @return true if the identifiers in the two supplied dependencies are
      -  227   -
            * equal
      -  228   -
            */
      -  229   -
           private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) {
      -  230  0
               if (dependency1 == null || dependency1.getFileName() == null
      -  231  0
                       || dependency2 == null || dependency2.getFileName() == null) {
      -  232  0
                   return false;
      -  233   +
           private String getBaseRepoPath(final String path) {
      +  227  0
               int pos = path.indexOf("repository" + File.separator) + 11;
      +  228  0
               if (pos < 0) {
      +  229  0
                   return path;
      +  230  
               }
      -  234  0
               final String fileName1 = dependency1.getActualFile().getName();
      -  235  0
               final String fileName2 = dependency2.getActualFile().getName();
      -  236   -
       
      +  231  0
               int tmp = path.indexOf(File.separator, pos);
      +  232  0
               if (tmp <= 0) {
      +  233  0
                   return path;
      +  234   +
               }
      +  235  0
               if (tmp > 0) {
      +  236  0
                   pos = tmp + 1;
       237   -
               //version check
      -  238  0
               final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1);
      -  239  0
               final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2);
      -  240  0
               if (version1 != null && version2 != null && !version1.equals(version2)) {
      -  241  0
                   return false;
      -  242  
               }
      +  238  0
               tmp = path.indexOf(File.separator, pos);
      +  239  0
               if (tmp > 0) {
      +  240  0
                   pos = tmp + 1;
      +  241   +
               }
      +  242  0
               return path.substring(0, pos);
       243   -
       
      -  244   -
               //filename check
      -  245  0
               final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1);
      -  246  0
               final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2);
      -  247  0
               if (match1.find() && match2.find()) {
      -  248  0
                   return match1.group().equals(match2.group());
      -  249   -
               }
      -  250   -
       
      -  251  0
               return false;
      -  252  
           }
      -  253   +  244  
       
      -  254   +  245  
           /**
      -  255   -
            * Returns true if the CPE identifiers in the two supplied dependencies are
      -  256   -
            * equal.
      -  257   +  246   +
            * Returns true if the file names (and version if it exists) of the two
      +  247   +
            * dependencies are sufficiently similar.
      +  248  
            *
      -  258   +  249  
            * @param dependency1 a dependency2 to compare
      -  259   +  250  
            * @param dependency2 a dependency2 to compare
      -  260   +  251  
            * @return true if the identifiers in the two supplied dependencies are
      -  261   +  252  
            * equal
      -  262   +  253  
            */
      -  263   -
           private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) {
      -  264  2
               if (dependency1 == null || dependency1.getIdentifiers() == null
      -  265  2
                       || dependency2 == null || dependency2.getIdentifiers() == null) {
      +  254   +
           private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) {
      +  255  0
               if (dependency1 == null || dependency1.getFileName() == null
      +  256  0
                       || dependency2 == null || dependency2.getFileName() == null) {
      +  257  0
                   return false;
      +  258   +
               }
      +  259  0
               final String fileName1 = dependency1.getActualFile().getName();
      +  260  0
               final String fileName2 = dependency2.getActualFile().getName();
      +  261   +
       
      +  262   +
               //version check
      +  263  0
               final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1);
      +  264  0
               final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2);
      +  265  0
               if (version1 != null && version2 != null && !version1.equals(version2)) {
       266  0
                   return false;
       267  
               }
      -  268  2
               boolean matches = false;
      -  269  2
               int cpeCount1 = 0;
      -  270  2
               int cpeCount2 = 0;
      -  271  2
               for (Identifier i : dependency1.getIdentifiers()) {
      -  272  0
                   if ("cpe".equals(i.getType())) {
      -  273  0
                       cpeCount1 += 1;
      +  268   +
       
      +  269   +
               //filename check
      +  270  0
               final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1);
      +  271  0
               final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2);
      +  272  0
               if (match1.find() && match2.find()) {
      +  273  0
                   return match1.group().equals(match2.group());
       274   -
                   }
      -  275  0
               }
      -  276  2
               for (Identifier i : dependency2.getIdentifiers()) {
      -  277  3
                   if ("cpe".equals(i.getType())) {
      -  278  3
                       cpeCount2 += 1;
      +
               }
      +  275   +
       
      +  276  0
               return false;
      +  277   +
           }
      +  278   +
       
       279   -
                   }
      -  280  3
               }
      -  281  2
               if (cpeCount1 > 0 && cpeCount1 == cpeCount2) {
      -  282  0
                   for (Identifier i : dependency1.getIdentifiers()) {
      -  283  0
                       if ("cpe".equals(i.getType())) {
      -  284  0
                           matches |= dependency2.getIdentifiers().contains(i);
      -  285  0
                           if (!matches) {
      -  286  0
                               break;
      +
           /**
      +  280   +
            * Returns true if the CPE identifiers in the two supplied dependencies are
      +  281   +
            * equal.
      +  282   +
            *
      +  283   +
            * @param dependency1 a dependency2 to compare
      +  284   +
            * @param dependency2 a dependency2 to compare
      +  285   +
            * @return true if the identifiers in the two supplied dependencies are
      +  286   +
            * equal
       287   -
                           }
      +
            */
       288   -
                       }
      -  289  0
                   }
      -  290   +
           private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) {
      +  289  2
               if (dependency1 == null || dependency1.getIdentifiers() == null
      +  290  2
                       || dependency2 == null || dependency2.getIdentifiers() == null) {
      +  291  0
                   return false;
      +  292  
               }
      -  291  2
               LOGGER.debug("IdentifiersMatch={} ({}, {})", matches, dependency1.getFileName(), dependency2.getFileName());
      -  292  2
               return matches;
      -  293   -
           }
      -  294   -
       
      -  295   -
           /**
      -  296   -
            * Determines if the two dependencies have the same base path.
      -  297   -
            *
      -  298   -
            * @param dependency1 a Dependency object
      +  293  2
               boolean matches = false;
      +  294  2
               int cpeCount1 = 0;
      +  295  2
               int cpeCount2 = 0;
      +  296  2
               for (Identifier i : dependency1.getIdentifiers()) {
      +  297  0
                   if ("cpe".equals(i.getType())) {
      +  298  0
                       cpeCount1 += 1;
       299   -
            * @param dependency2 a Dependency object
      -  300   -
            * @return true if the base paths of the dependencies are identical
      -  301   -
            */
      -  302   -
           private boolean hasSameBasePath(Dependency dependency1, Dependency dependency2) {
      -  303  0
               if (dependency1 == null || dependency2 == null) {
      -  304  0
                   return false;
      -  305   -
               }
      -  306  0
               final File lFile = new File(dependency1.getFilePath());
      -  307  0
               String left = lFile.getParent();
      -  308  0
               final File rFile = new File(dependency2.getFilePath());
      -  309  0
               String right = rFile.getParent();
      -  310  0
               if (left == null) {
      -  311  0
                   return right == null;
      -  312  0
               } else if (right == null) {
      -  313  0
                   return false;
      -  314   -
               }
      -  315  0
               if (left.equalsIgnoreCase(right)) {
      -  316  0
                   return true;
      -  317   -
               }
      -  318   -
       
      -  319  0
               if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) {
      -  320  0
                   left = getBaseRepoPath(left);
      -  321  0
                   right = getBaseRepoPath(right);
      -  322   -
               }
      -  323  0
               if (left.equalsIgnoreCase(right)) {
      -  324  0
                   return true;
      -  325   -
               }
      -  326   -
               //new code
      -  327  0
               for (Dependency child : dependency2.getRelatedDependencies()) {
      -  328  0
                   if (hasSameBasePath(dependency1, child)) {
      -  329  0
                       return true;
      -  330  
                   }
      -  331  0
               }
      -  332  0
               return false;
      -  333   +  300  0
               }
      +  301  2
               for (Identifier i : dependency2.getIdentifiers()) {
      +  302  4
                   if ("cpe".equals(i.getType())) {
      +  303  4
                       cpeCount2 += 1;
      +  304   +
                   }
      +  305  4
               }
      +  306  2
               if (cpeCount1 > 0 && cpeCount1 == cpeCount2) {
      +  307  0
                   for (Identifier i : dependency1.getIdentifiers()) {
      +  308  0
                       if ("cpe".equals(i.getType())) {
      +  309  0
                           matches |= dependency2.getIdentifiers().contains(i);
      +  310  0
                           if (!matches) {
      +  311  0
                               break;
      +  312   +
                           }
      +  313   +
                       }
      +  314  0
                   }
      +  315   +
               }
      +  316  2
               LOGGER.debug("IdentifiersMatch={} ({}, {})", matches, dependency1.getFileName(), dependency2.getFileName());
      +  317  2
               return matches;
      +  318  
           }
      -  334   +  319  
       
      -  335   +  320  
           /**
      -  336   -
            * Bundling Ruby gems that are identified from different .gemspec files but
      -  337   -
            * denote the same package path. This happens when Ruby bundler installs an
      -  338   -
            * application's dependencies by running "bundle install".
      -  339   +  321   +
            * Determines if the two dependencies have the same base path.
      +  322  
            *
      -  340   -
            * @param dependency1 dependency to compare
      -  341   -
            * @param dependency2 dependency to compare
      -  342   -
            * @return true if the the dependencies being analyzed appear to be the
      -  343   -
            * same; otherwise false
      -  344   +  323   +
            * @param dependency1 a Dependency object
      +  324   +
            * @param dependency2 a Dependency object
      +  325   +
            * @return true if the base paths of the dependencies are identical
      +  326  
            */
      -  345   -
           private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) {
      -  346  2
               if (dependency1 == null || dependency2 == null
      -  347  2
                       || !dependency1.getFileName().endsWith(".gemspec")
      -  348  0
                       || !dependency2.getFileName().endsWith(".gemspec")
      -  349  0
                       || dependency1.getPackagePath() == null
      -  350  0
                       || dependency2.getPackagePath() == null) {
      -  351  2
                   return false;
      -  352   +  327   +
           private boolean hasSameBasePath(Dependency dependency1, Dependency dependency2) {
      +  328  0
               if (dependency1 == null || dependency2 == null) {
      +  329  0
                   return false;
      +  330  
               }
      -  353  0
               if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) {
      -  354  0
                   return true;
      -  355   +  331  0
               final File lFile = new File(dependency1.getFilePath());
      +  332  0
               String left = lFile.getParent();
      +  333  0
               final File rFile = new File(dependency2.getFilePath());
      +  334  0
               String right = rFile.getParent();
      +  335  0
               if (left == null) {
      +  336  0
                   return right == null;
      +  337  0
               } else if (right == null) {
      +  338  0
                   return false;
      +  339  
               }
      -  356   +  340  0
               if (left.equalsIgnoreCase(right)) {
      +  341  0
                   return true;
      +  342   +
               }
      +  343  
       
      +  344  0
               if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) {
      +  345  0
                   left = getBaseRepoPath(left);
      +  346  0
                   right = getBaseRepoPath(right);
      +  347   +
               }
      +  348  0
               if (left.equalsIgnoreCase(right)) {
      +  349  0
                   return true;
      +  350   +
               }
      +  351   +
               //new code
      +  352  0
               for (Dependency child : dependency2.getRelatedDependencies()) {
      +  353  0
                   if (hasSameBasePath(dependency1, child)) {
      +  354  0
                       return true;
      +  355   +
                   }
      +  356  0
               }
       357  0
               return false;
       358  
           }
      @@ -597,120 +604,120 @@  360  
           /**
       361   -
            * Ruby gems installed by "bundle install" can have zero or more *.gemspec
      +
            * Bundling Ruby gems that are identified from different .gemspec files but
       362   -
            * files, all of which have the same packagePath and should be grouped. If
      +
            * denote the same package path. This happens when Ruby bundler installs an
       363   -
            * one of these gemspec is from <parent>/specifications/*.gemspec, because
      +
            * application's dependencies by running "bundle install".
       364   -
            * it is a stub with fully resolved gem meta-data created by Ruby bundler,
      +
            *
       365   -
            * this dependency should be the main one. Otherwise, use dependency2 as
      -  366   -
            * main.
      -  367   -
            *
      -  368   -
            * This method returns null if any dependency is not from *.gemspec, or the
      -  369   -
            * two do not have the same packagePath. In this case, they should not be
      -  370   -
            * grouped.
      -  371   -
            *
      -  372  
            * @param dependency1 dependency to compare
      -  373   +  366  
            * @param dependency2 dependency to compare
      -  374   -
            * @return the main dependency; or null if a gemspec is not included in the
      -  375   -
            * analysis
      -  376   +  367   +
            * @return true if the the dependencies being analyzed appear to be the
      +  368   +
            * same; otherwise false
      +  369  
            */
      +  370   +
           private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) {
      +  371  2
               if (dependency1 == null || dependency2 == null
      +  372  2
                       || !dependency1.getFileName().endsWith(".gemspec")
      +  373  0
                       || !dependency2.getFileName().endsWith(".gemspec")
      +  374  0
                       || dependency1.getPackagePath() == null
      +  375  0
                       || dependency2.getPackagePath() == null) {
      +  376  2
                   return false;
       377   -
           private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) {
      -  378  2
               if (isSameRubyGem(dependency1, dependency2)) {
      -  379  0
                   final File lFile = dependency1.getActualFile();
      -  380  0
                   final File left = lFile.getParentFile();
      -  381  0
                   if (left != null && left.getName().equalsIgnoreCase("specifications")) {
      -  382  0
                       return dependency1;
      -  383   -
                   }
      -  384  0
                   return dependency2;
      -  385  
               }
      -  386  2
               return null;
      -  387   +  378  0
               return dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath());
      +  379  
           }
      -  388   +  380  
       
      -  389   +  381  
           /**
      +  382   +
            * Ruby gems installed by "bundle install" can have zero or more *.gemspec
      +  383   +
            * files, all of which have the same packagePath and should be grouped. If
      +  384   +
            * one of these gemspec is from <parent>/specifications/*.gemspec, because
      +  385   +
            * it is a stub with fully resolved gem meta-data created by Ruby bundler,
      +  386   +
            * this dependency should be the main one. Otherwise, use dependency2 as
      +  387   +
            * main.
      +  388   +
            *
      +  389   +
            * This method returns null if any dependency is not from *.gemspec, or the
       390   -
            * Bundling same swift dependencies with the same packagePath but identified
      +
            * two do not have the same packagePath. In this case, they should not be
       391   -
            * by different analyzers.
      +
            * grouped.
       392  
            *
       393   -
            * @param dependency1 dependency to test
      +
            * @param dependency1 dependency to compare
       394   -
            * @param dependency2 dependency to test
      +
            * @param dependency2 dependency to compare
       395   -
            * @return <code>true</code> if the dependencies appear to be the same;
      +
            * @return the main dependency; or null if a gemspec is not included in the
       396   -
            * otherwise <code>false</code>
      +
            * analysis
       397  
            */
       398   -
           private boolean isSameSwiftPackage(Dependency dependency1, Dependency dependency2) {
      -  399  2
               if (dependency1 == null || dependency2 == null
      -  400  2
                       || (!dependency1.getFileName().endsWith(".podspec")
      -  401  2
                       && !dependency1.getFileName().equals("Package.swift"))
      -  402  0
                       || (!dependency2.getFileName().endsWith(".podspec")
      -  403  0
                       && !dependency2.getFileName().equals("Package.swift"))
      -  404  0
                       || dependency1.getPackagePath() == null
      -  405  0
                       || dependency2.getPackagePath() == null) {
      -  406  2
                   return false;
      -  407   -
               }
      -  408  0
               if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) {
      -  409  0
                   return true;
      -  410   -
               }
      -  411  0
               return false;
      -  412   -
           }
      -  413   -
       
      -  414   -
           /**
      -  415   -
            * Determines which of the swift dependencies should be considered the
      -  416   -
            * primary.
      -  417   -
            *
      -  418   -
            * @param dependency1 the first swift dependency to compare
      -  419   -
            * @param dependency2 the second swift dependency to compare
      -  420   -
            * @return the primary swift dependency
      -  421   -
            */
      -  422   -
           private Dependency getMainSwiftDependency(Dependency dependency1, Dependency dependency2) {
      -  423  2
               if (isSameSwiftPackage(dependency1, dependency2)) {
      -  424  0
                   if (dependency1.getFileName().endsWith(".podspec")) {
      -  425  0
                       return dependency1;
      -  426   +
           private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) {
      +  399  2
               if (isSameRubyGem(dependency1, dependency2)) {
      +  400  0
                   final File lFile = dependency1.getActualFile();
      +  401  0
                   final File left = lFile.getParentFile();
      +  402  0
                   if (left != null && left.getName().equalsIgnoreCase("specifications")) {
      +  403  0
                       return dependency1;
      +  404  
                   }
      -  427  0
                   return dependency2;
      +  405  0
                   return dependency2;
      +  406   +
               }
      +  407  2
               return null;
      +  408   +
           }
      +  409   +
       
      +  410   +
           /**
      +  411   +
            * Bundling same swift dependencies with the same packagePath but identified
      +  412   +
            * by different analyzers.
      +  413   +
            *
      +  414   +
            * @param dependency1 dependency to test
      +  415   +
            * @param dependency2 dependency to test
      +  416   +
            * @return <code>true</code> if the dependencies appear to be the same;
      +  417   +
            * otherwise <code>false</code>
      +  418   +
            */
      +  419   +
           private boolean isSameSwiftPackage(Dependency dependency1, Dependency dependency2) {
      +  420  2
               if (dependency1 == null || dependency2 == null
      +  421  2
                       || (!dependency1.getFileName().endsWith(".podspec")
      +  422  2
                       && !dependency1.getFileName().equals("Package.swift"))
      +  423  0
                       || (!dependency2.getFileName().endsWith(".podspec")
      +  424  0
                       && !dependency2.getFileName().equals("Package.swift"))
      +  425  0
                       || dependency1.getPackagePath() == null
      +  426  0
                       || dependency2.getPackagePath() == null) {
      +  427  2
                   return false;
       428  
               }
      -  429  2
               return null;
      +  429  0
               return dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath());
       430  
           }
       431   @@ -718,224 +725,259 @@  432  
           /**
       433   -
            * This is likely a very broken attempt at determining if the 'left'
      +
            * Determines which of the swift dependencies should be considered the
       434   -
            * dependency is the 'core' library in comparison to the 'right' library.
      +
            * primary.
       435  
            *
       436   -
            * @param left the dependency to test
      +
            * @param dependency1 the first swift dependency to compare
       437   -
            * @param right the dependency to test against
      +
            * @param dependency2 the second swift dependency to compare
       438   -
            * @return a boolean indicating whether or not the left dependency should be
      +
            * @return the primary swift dependency
       439   -
            * considered the "core" version.
      +
            */
       440   -
            */
      -  441   -
           boolean isCore(Dependency left, Dependency right) {
      -  442  2
               final String leftName = left.getFileName().toLowerCase();
      -  443  2
               final String rightName = right.getFileName().toLowerCase();
      +
           private Dependency getMainSwiftDependency(Dependency dependency1, Dependency dependency2) {
      +  441  2
               if (isSameSwiftPackage(dependency1, dependency2)) {
      +  442  0
                   if (dependency1.getFileName().endsWith(".podspec")) {
      +  443  0
                       return dependency1;
       444   -
       
      -  445   -
               final boolean returnVal;
      -  446  2
               if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
      -  447  2
                       || rightName.contains("core") && !leftName.contains("core")
      -  448  2
                       || rightName.contains("kernel") && !leftName.contains("kernel")) {
      -  449  0
                   returnVal = false;
      -  450  2
               } else if (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
      -  451  1
                       || !rightName.contains("core") && leftName.contains("core")
      -  452  1
                       || !rightName.contains("kernel") && leftName.contains("kernel")) {
      -  453  2
                   returnVal = true;
      -  454   -
       //        } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) {
      -  455   -
       //            returnVal = true;
      -  456   -
       //        } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) {
      -  457   -
       //            returnVal = false;
      -  458   -
               } else {
      -  459   -
                   /*
      -  460   -
                    * considered splitting the names up and comparing the components,
      -  461   -
                    * but decided that the file name length should be sufficient as the
      -  462   -
                    * "core" component, if this follows a normal naming protocol should
      -  463   -
                    * be shorter:
      -  464   -
                    * axis2-saaj-1.4.1.jar
      -  465   -
                    * axis2-1.4.1.jar       <-----
      -  466   -
                    * axis2-kernel-1.4.1.jar
      -  467   -
                    */
      -  468  0
                   returnVal = leftName.length() <= rightName.length();
      -  469   -
               }
      -  470  2
               LOGGER.debug("IsCore={} ({}, {})", returnVal, left.getFileName(), right.getFileName());
      -  471  2
               return returnVal;
      -  472   -
           }
      -  473   -
       
      -  474   -
           /**
      -  475   -
            * Compares the SHA1 hashes of two dependencies to determine if they are
      -  476   -
            * equal.
      -  477   -
            *
      -  478   -
            * @param dependency1 a dependency object to compare
      -  479   -
            * @param dependency2 a dependency object to compare
      -  480   -
            * @return true if the sha1 hashes of the two dependencies match; otherwise
      -  481   -
            * false
      -  482   -
            */
      -  483   -
           private boolean hashesMatch(Dependency dependency1, Dependency dependency2) {
      -  484  2
               if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) {
      -  485  0
                   return false;
      -  486   -
               }
      -  487  2
               return dependency1.getSha1sum().equals(dependency2.getSha1sum());
      -  488   -
           }
      -  489   -
       
      -  490   -
           /**
      -  491   -
            * Determines if the jar is shaded and the created pom.xml identified the
      -  492   -
            * same CPE as the jar - if so, the pom.xml dependency should be removed.
      -  493   -
            *
      -  494   -
            * @param dependency a dependency to check
      -  495   -
            * @param nextDependency another dependency to check
      -  496   -
            * @return true if on of the dependencies is a pom.xml and the identifiers
      -  497   -
            * between the two collections match; otherwise false
      -  498   -
            */
      -  499   -
           private boolean isShadedJar(Dependency dependency, Dependency nextDependency) {
      -  500  2
               final String mainName = dependency.getFileName().toLowerCase();
      -  501  2
               final String nextName = nextDependency.getFileName().toLowerCase();
      -  502  2
               if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) {
      -  503  0
                   return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers());
      -  504  2
               } else if (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) {
      -  505  0
                   return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers());
      -  506   -
               }
      -  507  2
               return false;
      -  508   -
           }
      -  509   -
       
      -  510   -
           /**
      -  511   -
            * Determines which path is shortest; if path lengths are equal then we use
      -  512   -
            * compareTo of the string method to determine if the first path is smaller.
      -  513   -
            *
      -  514   -
            * @param left the first path to compare
      -  515   -
            * @param right the second path to compare
      -  516   -
            * @return <code>true</code> if the leftPath is the shortest; otherwise
      -  517   -
            * <code>false</code>
      -  518   -
            */
      -  519   -
           protected boolean firstPathIsShortest(String left, String right) {
      -  520  5
               final String leftPath = left.replace('\\', '/');
      -  521  5
               final String rightPath = right.replace('\\', '/');
      -  522   -
       
      -  523  5
               final int leftCount = countChar(leftPath, '/');
      -  524  5
               final int rightCount = countChar(rightPath, '/');
      -  525  5
               if (leftCount == rightCount) {
      -  526  3
                   return leftPath.compareTo(rightPath) <= 0;
      -  527   -
               } else {
      -  528  2
                   return leftCount < rightCount;
      -  529   -
               }
      -  530   -
           }
      -  531   -
       
      -  532   -
           /**
      -  533   -
            * Counts the number of times the character is present in the string.
      -  534   -
            *
      -  535   -
            * @param string the string to count the characters in
      -  536   -
            * @param c the character to count
      -  537   -
            * @return the number of times the character is present in the string
      -  538   -
            */
      -  539   -
           private int countChar(String string, char c) {
      -  540  10
               int count = 0;
      -  541  10
               final int max = string.length();
      -  542  116
               for (int i = 0; i < max; i++) {
      -  543  106
                   if (c == string.charAt(i)) {
      -  544  28
                       count++;
      -  545  
                   }
      -  546   +  445  0
                   return dependency2;
      +  446  
               }
      -  547  10
               return count;
      -  548   +  447  2
               return null;
      +  448  
           }
      -  549   +  449  
       
      -  550   +  450  
           /**
      -  551   -
            * Checks if the given file path is contained within a war or ear file.
      -  552   +  451   +
            * This is likely a very broken attempt at determining if the 'left'
      +  452   +
            * dependency is the 'core' library in comparison to the 'right' library.
      +  453  
            *
      -  553   -
            * @param filePath the file path to check
      -  554   -
            * @return true if the path contains '.war\' or '.ear\'.
      -  555   +  454   +
            * @param left the dependency to test
      +  455   +
            * @param right the dependency to test against
      +  456   +
            * @return a boolean indicating whether or not the left dependency should be
      +  457   +
            * considered the "core" version.
      +  458  
            */
      -  556   -
           private boolean containedInWar(String filePath) {
      -  557  0
               return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*");
      -  558   +  459   +
           boolean isCore(Dependency left, Dependency right) {
      +  460  2
               final String leftName = left.getFileName().toLowerCase();
      +  461  2
               final String rightName = right.getFileName().toLowerCase();
      +  462   +
       
      +  463   +
               final boolean returnVal;
      +  464  2
               if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
      +  465  2
                       || rightName.contains("core") && !leftName.contains("core")
      +  466  2
                       || rightName.contains("kernel") && !leftName.contains("kernel")) {
      +  467  0
                   returnVal = false;
      +  468  2
               } else if (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+")
      +  469  1
                       || !rightName.contains("core") && leftName.contains("core")
      +  470  1
                       || !rightName.contains("kernel") && leftName.contains("kernel")) {
      +  471  2
                   returnVal = true;
      +  472   +
       //        } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) {
      +  473   +
       //            returnVal = true;
      +  474   +
       //        } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) {
      +  475   +
       //            returnVal = false;
      +  476   +
               } else {
      +  477   +
                   /*
      +  478   +
                    * considered splitting the names up and comparing the components,
      +  479   +
                    * but decided that the file name length should be sufficient as the
      +  480   +
                    * "core" component, if this follows a normal naming protocol should
      +  481   +
                    * be shorter:
      +  482   +
                    * axis2-saaj-1.4.1.jar
      +  483   +
                    * axis2-1.4.1.jar       <-----
      +  484   +
                    * axis2-kernel-1.4.1.jar
      +  485   +
                    */
      +  486  0
                   returnVal = leftName.length() <= rightName.length();
      +  487   +
               }
      +  488  2
               LOGGER.debug("IsCore={} ({}, {})", returnVal, left.getFileName(), right.getFileName());
      +  489  2
               return returnVal;
      +  490  
           }
      +  491   +
       
      +  492   +
           /**
      +  493   +
            * Compares the SHA1 hashes of two dependencies to determine if they are
      +  494   +
            * equal.
      +  495   +
            *
      +  496   +
            * @param dependency1 a dependency object to compare
      +  497   +
            * @param dependency2 a dependency object to compare
      +  498   +
            * @return true if the sha1 hashes of the two dependencies match; otherwise
      +  499   +
            * false
      +  500   +
            */
      +  501   +
           private boolean hashesMatch(Dependency dependency1, Dependency dependency2) {
      +  502  2
               if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) {
      +  503  0
                   return false;
      +  504   +
               }
      +  505  2
               return dependency1.getSha1sum().equals(dependency2.getSha1sum());
      +  506   +
           }
      +  507   +
       
      +  508   +
           /**
      +  509   +
            * Determines if the jar is shaded and the created pom.xml identified the
      +  510   +
            * same CPE as the jar - if so, the pom.xml dependency should be removed.
      +  511   +
            *
      +  512   +
            * @param dependency a dependency to check
      +  513   +
            * @param nextDependency another dependency to check
      +  514   +
            * @return true if on of the dependencies is a pom.xml and the identifiers
      +  515   +
            * between the two collections match; otherwise false
      +  516   +
            */
      +  517   +
           private boolean isShadedJar(Dependency dependency, Dependency nextDependency) {
      +  518  2
               final String mainName = dependency.getFileName().toLowerCase();
      +  519  2
               final String nextName = nextDependency.getFileName().toLowerCase();
      +  520  2
               if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) {
      +  521  0
                   return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers());
      +  522  2
               } else if (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) {
      +  523  0
                   return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers());
      +  524   +
               }
      +  525  2
               return false;
      +  526   +
           }
      +  527   +
       
      +  528   +
           /**
      +  529   +
            * Determines which path is shortest; if path lengths are equal then we use
      +  530   +
            * compareTo of the string method to determine if the first path is smaller.
      +  531   +
            *
      +  532   +
            * @param left the first path to compare
      +  533   +
            * @param right the second path to compare
      +  534   +
            * @return <code>true</code> if the leftPath is the shortest; otherwise
      +  535   +
            * <code>false</code>
      +  536   +
            */
      +  537   +
           protected boolean firstPathIsShortest(String left, String right) {
      +  538  5
               if (left.contains("dctemp")) {
      +  539  0
                   return false;
      +  540   +
               }
      +  541  5
               final String leftPath = left.replace('\\', '/');
      +  542  5
               final String rightPath = right.replace('\\', '/');
      +  543   +
       
      +  544  5
               final int leftCount = countChar(leftPath, '/');
      +  545  5
               final int rightCount = countChar(rightPath, '/');
      +  546  5
               if (leftCount == rightCount) {
      +  547  3
                   return leftPath.compareTo(rightPath) <= 0;
      +  548   +
               } else {
      +  549  2
                   return leftCount < rightCount;
      +  550   +
               }
      +  551   +
           }
      +  552   +
       
      +  553   +
           /**
      +  554   +
            * Counts the number of times the character is present in the string.
      +  555   +
            *
      +  556   +
            * @param string the string to count the characters in
      +  557   +
            * @param c the character to count
      +  558   +
            * @return the number of times the character is present in the string
       559   +
            */
      +  560   +
           private int countChar(String string, char c) {
      +  561  10
               int count = 0;
      +  562  10
               final int max = string.length();
      +  563  116
               for (int i = 0; i < max; i++) {
      +  564  106
                   if (c == string.charAt(i)) {
      +  565  28
                       count++;
      +  566   +
                   }
      +  567   +
               }
      +  568  10
               return count;
      +  569   +
           }
      +  570   +
       
      +  571   +
           /**
      +  572   +
            * Checks if the given file path is contained within a war or ear file.
      +  573   +
            *
      +  574   +
            * @param filePath the file path to check
      +  575   +
            * @return true if the path contains '.war\' or '.ear\'.
      +  576   +
            */
      +  577   +
           private boolean containedInWar(String filePath) {
      +  578  0
               return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*");
      +  579   +
           }
      +  580  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Experimental.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Experimental.html index 836a03935..1bd2812f2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Experimental.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.Experimental.html @@ -87,6 +87,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer.html index 4e64ba2a1..1d5cea998 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      FalsePositiveAnalyzer
      47%
      106/224
      25%
      58/230
      10.385
      FalsePositiveAnalyzer
      46%
      106/227
      25%
      58/230
      10.385
       
      @@ -105,7 +105,7 @@
        * @author Jeremy Long
       44  
        */
      -  45  9
       public class FalsePositiveAnalyzer extends AbstractAnalyzer {
      +  45  11
       public class FalsePositiveAnalyzer extends AbstractAnalyzer {
       46  
       
       47   @@ -159,7 +159,7 @@
           @Override
       73  
           public String getName() {
      -  74  17
               return ANALYZER_NAME;
      +  74  27
               return ANALYZER_NAME;
       75  
           }
       76   @@ -178,7 +178,7 @@
           @Override
       83  
           public AnalysisPhase getAnalysisPhase() {
      -  84  5
               return ANALYSIS_PHASE;
      +  84  7
               return ANALYSIS_PHASE;
       85  
           }
       86   @@ -227,7 +227,7 @@
           private void removeBadSpringMatches(Dependency dependency) {
       112  5
               String mustContain = null;
       113  5
               for (Identifier i : dependency.getIdentifiers()) {
      -  114  3
                   if ("maven".contains(i.getType())) {
      +  114  4
                   if ("maven".contains(i.getType())) {
       115  0
                       if (i.getValue() != null && i.getValue().startsWith("org.springframework.")) {
       116  0
                           final int endPoint = i.getValue().indexOf(':', 19);
       117  0
                           if (endPoint >= 0) {
      @@ -239,7 +239,7 @@
                       }
       122  
                   }
      -  123  3
               }
      +  123  4
               }
       124  5
               if (mustContain != null) {
       125  0
                   final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
       126  0
                   while (itr.hasNext()) {
      @@ -302,24 +302,24 @@  159  5
               final List<Identifier> ids = new ArrayList<Identifier>(dependency.getIdentifiers());
       160  5
               Collections.sort(ids);
       161  5
               final ListIterator<Identifier> mainItr = ids.listIterator();
      -  162  8
               while (mainItr.hasNext()) {
      -  163  3
                   final Identifier currentId = mainItr.next();
      -  164  3
                   final VulnerableSoftware currentCpe = parseCpe(currentId.getType(), currentId.getValue());
      -  165  3
                   if (currentCpe == null) {
      +  162  9
               while (mainItr.hasNext()) {
      +  163  4
                   final Identifier currentId = mainItr.next();
      +  164  4
                   final VulnerableSoftware currentCpe = parseCpe(currentId.getType(), currentId.getValue());
      +  165  4
                   if (currentCpe == null) {
       166  0
                       continue;
       167  
                   }
      -  168  3
                   final ListIterator<Identifier> subItr = ids.listIterator(mainItr.nextIndex());
      -  169  6
                   while (subItr.hasNext()) {
      -  170  3
                       final Identifier nextId = subItr.next();
      -  171  3
                       final VulnerableSoftware nextCpe = parseCpe(nextId.getType(), nextId.getValue());
      -  172  3
                       if (nextCpe == null) {
      +  168  4
                   final ListIterator<Identifier> subItr = ids.listIterator(mainItr.nextIndex());
      +  169  10
                   while (subItr.hasNext()) {
      +  170  6
                       final Identifier nextId = subItr.next();
      +  171  6
                       final VulnerableSoftware nextCpe = parseCpe(nextId.getType(), nextId.getValue());
      +  172  6
                       if (nextCpe == null) {
       173  0
                           continue;
       174  
                       }
       175  
                       //TODO fix the version problem below
      -  176  3
                       if (currentCpe.getVendor().equals(nextCpe.getVendor())) {
      +  176  6
                       if (currentCpe.getVendor().equals(nextCpe.getVendor())) {
       177  0
                           if (currentCpe.getProduct().equals(nextCpe.getProduct())) {
       178  
                               // see if one is contained in the other.. remove the contained one from dependency.getIdentifier
      @@ -350,8 +350,8 @@
                           }
       198  
                       }
      -  199  3
                   }
      -  200  3
               }
      +  199  6
                   }
      +  200  4
               }
       201  5
           }
       202  
           /**
      @@ -403,21 +403,21 @@
           private void removeJreEntries(Dependency dependency) {
       228  5
               final Set<Identifier> identifiers = dependency.getIdentifiers();
       229  5
               final Iterator<Identifier> itr = identifiers.iterator();
      -  230  9
               while (itr.hasNext()) {
      -  231  4
                   final Identifier i = itr.next();
      -  232  4
                   final Matcher coreCPE = CORE_JAVA.matcher(i.getValue());
      -  233  4
                   final Matcher coreFiles = CORE_FILES.matcher(dependency.getFileName());
      -  234  4
                   if (coreCPE.matches() && !coreFiles.matches()) {
      +  230  10
               while (itr.hasNext()) {
      +  231  5
                   final Identifier i = itr.next();
      +  232  5
                   final Matcher coreCPE = CORE_JAVA.matcher(i.getValue());
      +  233  5
                   final Matcher coreFiles = CORE_FILES.matcher(dependency.getFileName());
      +  234  5
                   if (coreCPE.matches() && !coreFiles.matches()) {
       235  0
                       itr.remove();
       236  
                   }
      -  237  4
                   final Matcher coreJsfCPE = CORE_JAVA_JSF.matcher(i.getValue());
      -  238  4
                   final Matcher coreJsfFiles = CORE_JSF_FILES.matcher(dependency.getFileName());
      -  239  4
                   if (coreJsfCPE.matches() && !coreJsfFiles.matches()) {
      +  237  5
                   final Matcher coreJsfCPE = CORE_JAVA_JSF.matcher(i.getValue());
      +  238  5
                   final Matcher coreJsfFiles = CORE_JSF_FILES.matcher(dependency.getFileName());
      +  239  5
                   if (coreJsfCPE.matches() && !coreJsfFiles.matches()) {
       240  0
                       itr.remove();
       241  
                   }
      -  242  4
               }
      +  242  5
               }
       243  5
           }
       244  
       
      @@ -437,19 +437,19 @@
            */
       252  
           private VulnerableSoftware parseCpe(String type, String value) {
      -  253  6
               if (!"cpe".equals(type)) {
      +  253  10
               if (!"cpe".equals(type)) {
       254  0
                   return null;
       255  
               }
      -  256  6
               final VulnerableSoftware cpe = new VulnerableSoftware();
      +  256  10
               final VulnerableSoftware cpe = new VulnerableSoftware();
       257  
               try {
      -  258  6
                   cpe.parseName(value);
      +  258  10
                   cpe.parseName(value);
       259  0
               } catch (UnsupportedEncodingException ex) {
       260  0
                   LOGGER.trace("", ex);
       261  0
                   return null;
      -  262  6
               }
      -  263  6
               return cpe;
      +  262  10
               }
      +  263  10
               return cpe;
       264  
           }
       265   @@ -486,19 +486,19 @@
               //Set<Evidence> groupId = dependency.getVendorEvidence().getEvidence("pom", "groupid");
       282  
               //Set<Evidence> artifactId = dependency.getVendorEvidence().getEvidence("pom", "artifactid");
      -  283  9
               while (itr.hasNext()) {
      -  284  4
                   final Identifier i = itr.next();
      +  283  10
               while (itr.hasNext()) {
      +  284  5
                   final Identifier i = itr.next();
       285  
                   //TODO move this startsWith expression to the base suppression file
      -  286  4
                   if ("cpe".equals(i.getType())) {
      -  287  4
                       if ((i.getValue().matches(".*c\\+\\+.*")
      -  288  4
                               || i.getValue().startsWith("cpe:/a:file:file")
      -  289  3
                               || i.getValue().startsWith("cpe:/a:mozilla:mozilla")
      -  290  3
                               || i.getValue().startsWith("cpe:/a:cvs:cvs")
      -  291  3
                               || i.getValue().startsWith("cpe:/a:ftp:ftp")
      -  292  3
                               || i.getValue().startsWith("cpe:/a:tcp:tcp")
      -  293  3
                               || i.getValue().startsWith("cpe:/a:ssh:ssh")
      -  294  3
                               || i.getValue().startsWith("cpe:/a:lookup:lookup"))
      +  286  5
                   if ("cpe".equals(i.getType())) {
      +  287  5
                       if ((i.getValue().matches(".*c\\+\\+.*")
      +  288  5
                               || i.getValue().startsWith("cpe:/a:file:file")
      +  289  4
                               || i.getValue().startsWith("cpe:/a:mozilla:mozilla")
      +  290  4
                               || i.getValue().startsWith("cpe:/a:cvs:cvs")
      +  291  4
                               || i.getValue().startsWith("cpe:/a:ftp:ftp")
      +  292  4
                               || i.getValue().startsWith("cpe:/a:tcp:tcp")
      +  293  4
                               || i.getValue().startsWith("cpe:/a:ssh:ssh")
      +  294  4
                               || i.getValue().startsWith("cpe:/a:lookup:lookup"))
       295  1
                               && (dependency.getFileName().toLowerCase().endsWith(".jar")
       296  1
                               || dependency.getFileName().toLowerCase().endsWith("pom.xml")
       297  0
                               || dependency.getFileName().toLowerCase().endsWith(".dll")
      @@ -513,39 +513,39 @@  306  0
                               || dependency.getFileName().toLowerCase().endsWith(".ear")
       307  0
                               || dependency.getFileName().toLowerCase().endsWith(".war"))) {
       308  1
                           itr.remove();
      -  309  3
                       } else if ((i.getValue().startsWith("cpe:/a:jquery:jquery")
      -  310  3
                               || i.getValue().startsWith("cpe:/a:prototypejs:prototype")
      -  311  3
                               || i.getValue().startsWith("cpe:/a:yahoo:yui"))
      +  309  4
                       } else if ((i.getValue().startsWith("cpe:/a:jquery:jquery")
      +  310  4
                               || i.getValue().startsWith("cpe:/a:prototypejs:prototype")
      +  311  4
                               || i.getValue().startsWith("cpe:/a:yahoo:yui"))
       312  0
                               && (dependency.getFileName().toLowerCase().endsWith(".jar")
       313  0
                               || dependency.getFileName().toLowerCase().endsWith("pom.xml")
       314  0
                               || dependency.getFileName().toLowerCase().endsWith(".dll")
       315  0
                               || dependency.getFileName().toLowerCase().endsWith(".exe"))) {
       316  0
                           itr.remove();
      -  317  3
                       } else if ((i.getValue().startsWith("cpe:/a:microsoft:excel")
      -  318  3
                               || i.getValue().startsWith("cpe:/a:microsoft:word")
      -  319  3
                               || i.getValue().startsWith("cpe:/a:microsoft:visio")
      -  320  3
                               || i.getValue().startsWith("cpe:/a:microsoft:powerpoint")
      -  321  3
                               || i.getValue().startsWith("cpe:/a:microsoft:office")
      -  322  3
                               || i.getValue().startsWith("cpe:/a:core_ftp:core_ftp"))
      +  317  4
                       } else if ((i.getValue().startsWith("cpe:/a:microsoft:excel")
      +  318  4
                               || i.getValue().startsWith("cpe:/a:microsoft:word")
      +  319  4
                               || i.getValue().startsWith("cpe:/a:microsoft:visio")
      +  320  4
                               || i.getValue().startsWith("cpe:/a:microsoft:powerpoint")
      +  321  4
                               || i.getValue().startsWith("cpe:/a:microsoft:office")
      +  322  4
                               || i.getValue().startsWith("cpe:/a:core_ftp:core_ftp"))
       323  0
                               && (dependency.getFileName().toLowerCase().endsWith(".jar")
       324  0
                               || dependency.getFileName().toLowerCase().endsWith(".ear")
       325  0
                               || dependency.getFileName().toLowerCase().endsWith(".war")
       326  0
                               || dependency.getFileName().toLowerCase().endsWith("pom.xml"))) {
       327  0
                           itr.remove();
      -  328  3
                       } else if (i.getValue().startsWith("cpe:/a:apache:maven")
      +  328  4
                       } else if (i.getValue().startsWith("cpe:/a:apache:maven")
       329  0
                               && !dependency.getFileName().toLowerCase().matches("maven-core-[\\d\\.]+\\.jar")) {
       330  0
                           itr.remove();
      -  331  3
                       } else if (i.getValue().startsWith("cpe:/a:m-core:m-core")
      +  331  4
                       } else if (i.getValue().startsWith("cpe:/a:m-core:m-core")
       332  0
                               && !dependency.getEvidenceUsed().containsUsedString("m-core")) {
       333  0
                           itr.remove();
      -  334  3
                       } else if (i.getValue().startsWith("cpe:/a:jboss:jboss")
      +  334  4
                       } else if (i.getValue().startsWith("cpe:/a:jboss:jboss")
       335  0
                               && !dependency.getFileName().toLowerCase().matches("jboss-?[\\d\\.-]+(GA)?\\.jar")) {
       336  0
                           itr.remove();
       337  
                       }
       338  
                   }
      -  339  4
               }
      +  339  5
               }
       340  5
           }
       341  
       
      @@ -612,11 +612,11 @@  382  
               //TODO move this to the hint analyzer
       383  5
               for (final Identifier identifier : dependency.getIdentifiers()) {
      -  384  3
                   if ("cpe".equals(identifier.getType()) && identifier.getValue() != null
      -  385  3
                           && (identifier.getValue().startsWith("cpe:/a:oracle:opensso:")
      -  386  3
                           || identifier.getValue().startsWith("cpe:/a:oracle:opensso_enterprise:")
      -  387  3
                           || identifier.getValue().startsWith("cpe:/a:sun:opensso_enterprise:")
      -  388  3
                           || identifier.getValue().startsWith("cpe:/a:sun:opensso:"))) {
      +  384  4
                   if ("cpe".equals(identifier.getType()) && identifier.getValue() != null
      +  385  4
                           && (identifier.getValue().startsWith("cpe:/a:oracle:opensso:")
      +  386  4
                           || identifier.getValue().startsWith("cpe:/a:oracle:opensso_enterprise:")
      +  387  4
                           || identifier.getValue().startsWith("cpe:/a:sun:opensso_enterprise:")
      +  388  4
                           || identifier.getValue().startsWith("cpe:/a:sun:opensso:"))) {
       389  0
                       final String newCpe = String.format("cpe:/a:sun:opensso_enterprise:%s", identifier.getValue().substring(22));
       390  0
                       final String newCpe2 = String.format("cpe:/a:oracle:opensso_enterprise:%s", identifier.getValue().substring(22));
       391  0
                       final String newCpe3 = String.format("cpe:/a:sun:opensso:%s", identifier.getValue().substring(22));
      @@ -644,7 +644,7 @@  408  0
                       }
       409  
                   }
      -  410  3
               }
      +  410  4
               }
       411  5
           }
       412  
       
      @@ -669,98 +669,99 @@  423  1
                   String parentPath = dependency.getFilePath().toLowerCase();
       424  1
                   if (parentPath.contains(".jar")) {
       425  0
                       parentPath = parentPath.substring(0, parentPath.indexOf(".jar") + 4);
      -  426  0
                       final Dependency parent = findDependency(parentPath, engine.getDependencies());
      -  427  0
                       if (parent != null) {
      -  428  0
                           boolean remove = false;
      -  429  0
                           for (Identifier i : dependency.getIdentifiers()) {
      -  430  0
                               if ("cpe".equals(i.getType())) {
      -  431  0
                                   final String trimmedCPE = trimCpeToVendor(i.getValue());
      -  432  0
                                   for (Identifier parentId : parent.getIdentifiers()) {
      -  433  0
                                       if ("cpe".equals(parentId.getType()) && parentId.getValue().startsWith(trimmedCPE)) {
      -  434  0
                                           remove |= true;
      -  435   -
                                       }
      -  436  0
                                   }
      +  426  0
                       final List<Dependency> dependencies = engine.getDependencies();
      +  427  0
                       synchronized (dependencies) {
      +  428  0
                           final Dependency parent = findDependency(parentPath, dependencies);
      +  429  0
                           if (parent != null) {
      +  430  0
                               boolean remove = false;
      +  431  0
                               for (Identifier i : dependency.getIdentifiers()) {
      +  432  0
                                   if ("cpe".equals(i.getType())) {
      +  433  0
                                       final String trimmedCPE = trimCpeToVendor(i.getValue());
      +  434  0
                                       for (Identifier parentId : parent.getIdentifiers()) {
      +  435  0
                                           if ("cpe".equals(parentId.getType()) && parentId.getValue().startsWith(trimmedCPE)) {
      +  436  0
                                               remove |= true;
       437   -
                               }
      -  438  0
                               if (!remove) { //we can escape early
      -  439  0
                                   return;
      -  440   -
                               }
      -  441  0
                           }
      -  442  0
                           if (remove) {
      -  443  0
                               engine.getDependencies().remove(dependency);
      -  444   -
                           }
      -  445   -
                       }
      +
                                           }
      +  438  0
                                       }
      +  439   +
                                   }
      +  440  0
                                   if (!remove) { //we can escape early
      +  441  0
                                       return;
      +  442   +
                                   }
      +  443  0
                               }
      +  444  0
                               if (remove) {
      +  445  0
                                   dependencies.remove(dependency);
       446   -
                   }
      +
                               }
       447   -
       
      -  448   -
               }
      -  449  5
           }
      -  450   -
       
      -  451   -
           /**
      -  452   -
            * Retrieves a given dependency, based on a given path, from a list of dependencies.
      -  453   -
            *
      -  454   -
            * @param dependencyPath the path of the dependency to return
      -  455   -
            * @param dependencies the collection of dependencies to search
      -  456   -
            * @return the dependency object for the given path, otherwise null
      -  457   -
            */
      -  458   -
           private Dependency findDependency(String dependencyPath, List<Dependency> dependencies) {
      -  459  0
               for (Dependency d : dependencies) {
      -  460  0
                   if (d.getFilePath().equalsIgnoreCase(dependencyPath)) {
      -  461  0
                       return d;
      -  462   +
                           }
      +  448  0
                       }
      +  449  
                   }
      -  463  0
               }
      -  464  0
               return null;
      -  465   -
           }
      -  466   -
       
      -  467   -
           /**
      -  468   -
            * Takes a full CPE and returns the CPE trimmed to include only vendor and product.
      -  469   -
            *
      -  470   -
            * @param value the CPE value to trim
      -  471   -
            * @return a CPE value that only includes the vendor and product
      -  472   -
            */
      -  473   -
           private String trimCpeToVendor(String value) {
      -  474   -
               //cpe:/a:jruby:jruby:1.0.8
      -  475  0
               final int pos1 = value.indexOf(':', 7); //right of vendor
      -  476  0
               final int pos2 = value.indexOf(':', pos1 + 1); //right of product
      -  477  0
               if (pos2 < 0) {
      -  478  0
                   return value;
      -  479   -
               } else {
      -  480  0
                   return value.substring(0, pos2);
      -  481   +  450  
               }
      -  482   +  451  5
           }
      +  452   +
       
      +  453   +
           /**
      +  454   +
            * Retrieves a given dependency, based on a given path, from a list of dependencies.
      +  455   +
            *
      +  456   +
            * @param dependencyPath the path of the dependency to return
      +  457   +
            * @param dependencies the collection of dependencies to search
      +  458   +
            * @return the dependency object for the given path, otherwise null
      +  459   +
            */
      +  460   +
           private Dependency findDependency(String dependencyPath, List<Dependency> dependencies) {
      +  461  0
               for (Dependency d : dependencies) {
      +  462  0
                   if (d.getFilePath().equalsIgnoreCase(dependencyPath)) {
      +  463  0
                       return d;
      +  464   +
                   }
      +  465  0
               }
      +  466  0
               return null;
      +  467  
           }
      +  468   +
       
      +  469   +
           /**
      +  470   +
            * Takes a full CPE and returns the CPE trimmed to include only vendor and product.
      +  471   +
            *
      +  472   +
            * @param value the CPE value to trim
      +  473   +
            * @return a CPE value that only includes the vendor and product
      +  474   +
            */
      +  475   +
           private String trimCpeToVendor(String value) {
      +  476   +
               //cpe:/a:jruby:jruby:1.0.8
      +  477  0
               final int pos1 = value.indexOf(':', 7); //right of vendor
      +  478  0
               final int pos2 = value.indexOf(':', pos1 + 1); //right of product
      +  479  0
               if (pos2 < 0) {
      +  480  0
                   return value;
      +  481   +
               } else {
      +  482  0
                   return value.substring(0, pos2);
       483   +
               }
      +  484   +
           }
      +  485  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileNameAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileNameAnalyzer.html index e563dbd08..a49ea7cd9 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileNameAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileNameAnalyzer.html @@ -89,7 +89,7 @@
        * @author Jeremy Long
       36  
        */
      -  37  11
       public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
      +  37  13
       public class FileNameAnalyzer extends AbstractAnalyzer {
       38  
       
       39   @@ -125,7 +125,7 @@
           @Override
       55  
           public String getName() {
      -  56  17
               return ANALYZER_NAME;
      +  56  27
               return ANALYZER_NAME;
       57  
           }
       58   @@ -144,7 +144,7 @@
           @Override
       65  
           public AnalysisPhase getAnalysisPhase() {
      -  66  5
               return ANALYSIS_PHASE;
      +  66  7
               return ANALYSIS_PHASE;
       67  
           }
       68   @@ -239,6 +239,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileTypeAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileTypeAnalyzer.html index 12bec1241..8ddc8954c 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileTypeAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.FileTypeAnalyzer.html @@ -85,6 +85,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.HintAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.HintAnalyzer.html index 55bc2c1e8..ede9a4ab4 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.HintAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.HintAnalyzer.html @@ -123,7 +123,7 @@
        * @author Jeremy Long
       53  
        */
      -  54  9
       public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
      +  54  12
       public class HintAnalyzer extends AbstractAnalyzer {
       55  
       
       56   @@ -159,7 +159,7 @@
           @Override
       72  
           public String getName() {
      -  73  17
               return ANALYZER_NAME;
      +  73  27
               return ANALYZER_NAME;
       74  
           }
       75   @@ -178,7 +178,7 @@
           @Override
       82  
           public AnalysisPhase getAnalysisPhase() {
      -  83  5
               return ANALYSIS_PHASE;
      +  83  7
               return ANALYSIS_PHASE;
       84  
           }
       85   @@ -259,7 +259,7 @@
           public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
       127  4
               for (HintRule hint : hints.getHintRules()) {
       128  48
                   boolean shouldAdd = false;
      -  129  48
                   for (Evidence given : hint.getGivenVendor()) {
      +  129  47
                   for (Evidence given : hint.getGivenVendor()) {
       130  8
                       if (dependency.getVendorEvidence().getEvidence().contains(given)) {
       131  0
                           shouldAdd = true;
       132  0
                           break;
      @@ -267,8 +267,8 @@
                       }
       134  8
                   }
       135  48
                   if (!shouldAdd) {
      -  136  48
                       for (Evidence given : hint.getGivenProduct()) {
      -  137  31
                           if (dependency.getProductEvidence().getEvidence().contains(given)) {
      +  136  46
                       for (Evidence given : hint.getGivenProduct()) {
      +  137  29
                           if (dependency.getProductEvidence().getEvidence().contains(given)) {
       138  1
                               shouldAdd = true;
       139  1
                               break;
       140   @@ -301,11 +301,11 @@  162  
       
       163  4
               final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
      -  164  4
               final List<Evidence> newEntries = new ArrayList<Evidence>();
      +  164  3
               final List<Evidence> newEntries = new ArrayList<Evidence>();
       165  29
               while (itr.hasNext()) {
       166  25
                   final Evidence e = itr.next();
      -  167  25
                   for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) {
      -  168  50
                       if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) {
      +  167  24
                   for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) {
      +  168  49
                       if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) {
       169  0
                           newEntries.add(new Evidence(e.getSource() + " (hint)",
       170  0
                                   e.getName(), dhr.getDuplicate(), e.getConfidence()));
       171   @@ -579,7 +579,7 @@
                                   try {
       324  0
                                       org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
       325  0
                                   } catch (IOException ex) {
      -  326  0
                                       throw new HintParseException("Unable to locate suppressions file in classpath", ex);
      +  326  0
                                       throw new HintParseException("Unable to locate hints file in classpath", ex);
       327  0
                                   }
       328  
                               }
      @@ -632,6 +632,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.JarAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.JarAnalyzer.html index b40544064..1039eabb7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.JarAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.JarAnalyzer.html @@ -12,8 +12,8 @@
       
      - - + +
      Classes in this File Line Coverage Branch Coverage Complexity
      JarAnalyzer
      66%
      351/531
      55%
      198/354
      7.581
      JarAnalyzer$ClassNameInformation
      80%
      17/21
      80%
      8/10
      7.581
      JarAnalyzer
      65%
      351/532
      55%
      198/360
      7.677
      JarAnalyzer$ClassNameInformation
      80%
      17/21
      80%
      8/10
      7.677
       
      @@ -75,23 +75,23 @@  28  
       import java.util.ArrayList;
       29   -
       import java.util.Collections;
      -  30  
       import java.util.Enumeration;
      -  31   +  30  
       import java.util.HashMap;
      -  32   +  31  
       import java.util.List;
      -  33   +  32  
       import java.util.Map;
      -  34   +  33  
       import java.util.Map.Entry;
      -  35   +  34  
       import java.util.Properties;
      -  36   +  35  
       import java.util.Set;
      -  37   +  36  
       import java.util.StringTokenizer;
      +  37   +
       import java.util.concurrent.atomic.AtomicInteger;
       38  
       import java.util.jar.Attributes;
       39   @@ -173,7 +173,7 @@
            * creating temporary directories.
       78  
            */
      -  79  1
           private static int dirCount = 0;
      +  79  1
           private static final AtomicInteger DIR_COUNT = new AtomicInteger(0);
       80  
           /**
       81   @@ -320,8 +320,8 @@
            * Constructs a new JarAnalyzer.
       155  
            */
      -  156  10
           public JarAnalyzer() {
      -  157  10
           }
      +  156  13
           public JarAnalyzer() {
      +  157  13
           }
       158  
       
       159   @@ -373,7 +373,7 @@
           @Override
       184  
           protected FileFilter getFileFilter() {
      -  185  861
               return FILTER;
      +  185  867
               return FILTER;
       186  
           }
       187   @@ -392,7 +392,7 @@
           @Override
       194  
           public String getName() {
      -  195  17
               return ANALYZER_NAME;
      +  195  25
               return ANALYZER_NAME;
       196  
           }
       197   @@ -411,7 +411,7 @@
           @Override
       204  
           public AnalysisPhase getAnalysisPhase() {
      -  205  4
               return ANALYSIS_PHASE;
      +  205  6
               return ANALYSIS_PHASE;
       206  
           }
       207   @@ -434,7 +434,7 @@
           @Override
       216  
           protected String getAnalyzerEnabledSettingKey() {
      -  217  10
               return Settings.KEYS.ANALYZER_JAR_ENABLED;
      +  217  13
               return Settings.KEYS.ANALYZER_JAR_ENABLED;
       218  
           }
       219   @@ -584,1356 +584,1359 @@  318  0
                           pom.processProperties(pomProperties);
       319  0
                           setPomEvidence(newDependency, pom, null);
       320  0
                           engine.getDependencies().add(newDependency);
      -  321  0
                           Collections.sort(engine.getDependencies());
      -  322  0
                       } else {
      -  323  2
                           if (externalPom == null) {
      -  324  2
                               pom = PomUtils.readPom(path, jar);
      -  325   +  321  0
                       } else {
      +  322  2
                           if (externalPom == null) {
      +  323  2
                               pom = PomUtils.readPom(path, jar);
      +  324  
                           } else {
      -  326  0
                               pom = PomUtils.readPom(externalPom);
      -  327   +  325  0
                               pom = PomUtils.readPom(externalPom);
      +  326   +
                           }
      +  327  2
                           if (pom != null) {
      +  328  2
                               pom.processProperties(pomProperties);
      +  329  2
                               foundSomething |= setPomEvidence(dependency, pom, classes);
      +  330  
                           }
      -  328  2
                           if (pom != null) {
      -  329  2
                               pom.processProperties(pomProperties);
      -  330  2
                               foundSomething |= setPomEvidence(dependency, pom, classes);
       331   -
                           }
      -  332  
                       }
      -  333  0
                   } catch (AnalysisException ex) {
      -  334  0
                       LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath());
      -  335  0
                       LOGGER.trace("", ex);
      -  336  2
                   }
      -  337  2
               }
      -  338  2
               return foundSomething;
      +  332  0
                   } catch (AnalysisException ex) {
      +  333  0
                       LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath());
      +  334  0
                       LOGGER.trace("", ex);
      +  335  2
                   }
      +  336  2
               }
      +  337  2
               return foundSomething;
      +  338   +
           }
       339   -
           }
      +
       
       340   -
       
      +
           /**
       341   -
           /**
      -  342  
            * Given a path to a pom.xml within a JarFile, this method attempts to load
      -  343   +  342  
            * a sibling pom.properties if one exists.
      +  343   +
            *
       344   -
            *
      -  345  
            * @param path the path to the pom.xml within the JarFile
      -  346   +  345  
            * @param jar the JarFile to load the pom.properties from
      -  347   +  346  
            * @return a Properties object or null if no pom.properties was found
      -  348   +  347  
            * @throws IOException thrown if there is an exception reading the
      -  349   +  348  
            * pom.properties
      +  349   +
            */
       350   -
            */
      -  351  
           private Properties retrievePomProperties(String path, final JarFile jar) throws IOException {
      -  352  2
               Properties pomProperties = null;
      -  353  2
               final String propPath = path.substring(0, path.length() - 7) + "pom.properies";
      -  354  2
               final ZipEntry propEntry = jar.getEntry(propPath);
      -  355  2
               if (propEntry != null) {
      -  356  0
                   Reader reader = null;
      -  357   +  351  2
               Properties pomProperties = null;
      +  352  2
               final String propPath = path.substring(0, path.length() - 7) + "pom.properies";
      +  353  2
               final ZipEntry propEntry = jar.getEntry(propPath);
      +  354  2
               if (propEntry != null) {
      +  355  0
                   Reader reader = null;
      +  356  
                   try {
      -  358  0
                       reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
      -  359  0
                       pomProperties = new Properties();
      -  360  0
                       pomProperties.load(reader);
      -  361  0
                       LOGGER.debug("Read pom.properties: {}", propPath);
      -  362   +  357  0
                       reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
      +  358  0
                       pomProperties = new Properties();
      +  359  0
                       pomProperties.load(reader);
      +  360  0
                       LOGGER.debug("Read pom.properties: {}", propPath);
      +  361  
                   } finally {
      -  363  0
                       if (reader != null) {
      -  364   +  362  0
                       if (reader != null) {
      +  363  
                           try {
      -  365  0
                               reader.close();
      -  366  0
                           } catch (IOException ex) {
      -  367  0
                               LOGGER.trace("close error", ex);
      -  368  0
                           }
      +  364  0
                               reader.close();
      +  365  0
                           } catch (IOException ex) {
      +  366  0
                               LOGGER.trace("close error", ex);
      +  367  0
                           }
      +  368   +
                       }
       369   -
                       }
      +
                   }
       370   -
                   }
      -  371  
               }
      -  372  2
               return pomProperties;
      +  371  2
               return pomProperties;
      +  372   +
           }
       373   -
           }
      +
       
       374   -
       
      +
           /**
       375   -
           /**
      -  376  
            * Searches a JarFile for pom.xml entries and returns a listing of these
      -  377   +  376  
            * entries.
      +  377   +
            *
       378   -
            *
      -  379  
            * @param jar the JarFile to search
      -  380   +  379  
            * @return a list of pom.xml entries
      -  381   +  380  
            * @throws IOException thrown if there is an exception reading a JarEntry
      +  381   +
            */
       382   -
            */
      -  383  
           private List<String> retrievePomListing(final JarFile jar) throws IOException {
      -  384  6
               final List<String> pomEntries = new ArrayList<String>();
      -  385  6
               final Enumeration<JarEntry> entries = jar.entries();
      -  386  1852
               while (entries.hasMoreElements()) {
      -  387  1846
                   final JarEntry entry = entries.nextElement();
      -  388  1846
                   final String entryName = (new File(entry.getName())).getName().toLowerCase();
      -  389  1846
                   if (!entry.isDirectory() && "pom.xml".equals(entryName)) {
      -  390  2
                       LOGGER.trace("POM Entry found: {}", entry.getName());
      -  391  2
                       pomEntries.add(entry.getName());
      -  392   +  383  6
               final List<String> pomEntries = new ArrayList<String>();
      +  384  6
               final Enumeration<JarEntry> entries = jar.entries();
      +  385  1852
               while (entries.hasMoreElements()) {
      +  386  1846
                   final JarEntry entry = entries.nextElement();
      +  387  1846
                   final String entryName = (new File(entry.getName())).getName().toLowerCase();
      +  388  1846
                   if (!entry.isDirectory() && "pom.xml".equals(entryName)) {
      +  389  2
                       LOGGER.trace("POM Entry found: {}", entry.getName());
      +  390  2
                       pomEntries.add(entry.getName());
      +  391  
                   }
      -  393  1846
               }
      -  394  6
               return pomEntries;
      +  392  1846
               }
      +  393  6
               return pomEntries;
      +  394   +
           }
       395   -
           }
      +
       
       396   -
       
      +
           /**
       397   -
           /**
      -  398  
            * Retrieves the specified POM from a jar file and converts it to a Model.
      +  398   +
            *
       399   -
            *
      -  400  
            * @param path the path to the pom.xml file within the jar file
      -  401   +  400  
            * @param jar the jar file to extract the pom from
      +  401   +
            * @param dependency the dependency being analyzed
       402   -
            * @param dependency the dependency being analyzed
      -  403  
            * @return returns the POM object
      -  404   +  403  
            * @throws AnalysisException is thrown if there is an exception extracting
      -  405   +  404  
            * or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object
      +  405   +
            */
       406   -
            */
      -  407  
           private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException {
      -  408  0
               InputStream input = null;
      -  409  0
               FileOutputStream fos = null;
      -  410  0
               final File tmpDir = getNextTempDirectory();
      -  411  0
               final File file = new File(tmpDir, "pom.xml");
      -  412   +  407  0
               InputStream input = null;
      +  408  0
               FileOutputStream fos = null;
      +  409  0
               final File tmpDir = getNextTempDirectory();
      +  410  0
               final File file = new File(tmpDir, "pom.xml");
      +  411  
               try {
      -  413  0
                   final ZipEntry entry = jar.getEntry(path);
      -  414  0
                   if (entry == null) {
      -  415  0
                       throw new AnalysisException(String.format("Pom (%s)does not exist in %s", path, jar.getName()));
      -  416   +  412  0
                   final ZipEntry entry = jar.getEntry(path);
      +  413  0
                   if (entry == null) {
      +  414  0
                       throw new AnalysisException(String.format("Pom (%s)does not exist in %s", path, jar.getName()));
      +  415  
                   }
      -  417  0
                   input = jar.getInputStream(entry);
      -  418  0
                   fos = new FileOutputStream(file);
      -  419  0
                   IOUtils.copy(input, fos);
      -  420  0
                   dependency.setActualFilePath(file.getAbsolutePath());
      -  421  0
               } catch (IOException ex) {
      -  422  0
                   LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath());
      -  423  0
                   LOGGER.error("", ex);
      -  424   +  416  0
                   input = jar.getInputStream(entry);
      +  417  0
                   fos = new FileOutputStream(file);
      +  418  0
                   IOUtils.copy(input, fos);
      +  419  0
                   dependency.setActualFilePath(file.getAbsolutePath());
      +  420  0
               } catch (IOException ex) {
      +  421  0
                   LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath());
      +  422  0
                   LOGGER.error("", ex);
      +  423  
               } finally {
      -  425  0
                   closeStream(fos);
      -  426  0
                   closeStream(input);
      -  427  0
               }
      -  428  0
               return PomUtils.readPom(file);
      +  424  0
                   closeStream(fos);
      +  425  0
                   closeStream(input);
      +  426  0
               }
      +  427  0
               return PomUtils.readPom(file);
      +  428   +
           }
       429   -
           }
      +
       
       430   -
       
      +
           /**
       431   -
           /**
      -  432  
            * Silently closes an input stream ignoring errors.
      +  432   +
            *
       433   -
            *
      -  434  
            * @param stream an input stream to close
      +  434   +
            */
       435   -
            */
      -  436  
           private void closeStream(InputStream stream) {
      -  437  0
               if (stream != null) {
      -  438   +  436  0
               if (stream != null) {
      +  437  
                   try {
      -  439  0
                       stream.close();
      -  440  0
                   } catch (IOException ex) {
      -  441  0
                       LOGGER.trace("", ex);
      -  442  0
                   }
      -  443   +  438  0
                       stream.close();
      +  439  0
                   } catch (IOException ex) {
      +  440  0
                       LOGGER.trace("", ex);
      +  441  0
                   }
      +  442  
               }
      -  444  0
           }
      +  443  0
           }
      +  444   +
       
       445   -
       
      +
           /**
       446   -
           /**
      -  447  
            * Silently closes an output stream ignoring errors.
      +  447   +
            *
       448   -
            *
      -  449  
            * @param stream an output stream to close
      +  449   +
            */
       450   -
            */
      -  451  
           private void closeStream(OutputStream stream) {
      -  452  0
               if (stream != null) {
      -  453   +  451  0
               if (stream != null) {
      +  452  
                   try {
      -  454  0
                       stream.close();
      -  455  0
                   } catch (IOException ex) {
      -  456  0
                       LOGGER.trace("", ex);
      -  457  0
                   }
      -  458   +  453  0
                       stream.close();
      +  454  0
                   } catch (IOException ex) {
      +  455  0
                       LOGGER.trace("", ex);
      +  456  0
                   }
      +  457  
               }
      -  459  0
           }
      +  458  0
           }
      +  459   +
       
       460   -
       
      +
           /**
       461   -
           /**
      -  462  
            * Sets evidence from the pom on the supplied dependency.
      +  462   +
            *
       463   -
            *
      -  464  
            * @param dependency the dependency to set data on
      -  465   +  464  
            * @param pom the information from the pom
      -  466   +  465  
            * @param classes a collection of ClassNameInformation - containing data
      -  467   +  466  
            * about the fully qualified class names within the JAR file being analyzed
      -  468   +  467  
            * @return true if there was evidence within the pom that we could use;
      -  469   +  468  
            * otherwise false
      +  469   +
            */
       470   -
            */
      -  471  
           public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) {
      -  472  2
               boolean foundSomething = false;
      -  473  2
               boolean addAsIdentifier = true;
      -  474  2
               if (pom == null) {
      -  475  0
                   return foundSomething;
      -  476   +  471  2
               boolean foundSomething = false;
      +  472  2
               boolean addAsIdentifier = true;
      +  473  2
               if (pom == null) {
      +  474  0
                   return foundSomething;
      +  475  
               }
      -  477  2
               String groupid = pom.getGroupId();
      -  478  2
               String parentGroupId = pom.getParentGroupId();
      -  479  2
               String artifactid = pom.getArtifactId();
      -  480  2
               String parentArtifactId = pom.getParentArtifactId();
      -  481  2
               String version = pom.getVersion();
      -  482  2
               String parentVersion = pom.getParentVersion();
      -  483   +  476  2
               String groupid = pom.getGroupId();
      +  477  2
               String parentGroupId = pom.getParentGroupId();
      +  478  2
               String artifactid = pom.getArtifactId();
      +  479  2
               String parentArtifactId = pom.getParentArtifactId();
      +  480  2
               String version = pom.getVersion();
      +  481  2
               String parentVersion = pom.getParentVersion();
      +  482  
       
      -  484  2
               if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) {
      -  485  0
                   parentGroupId = null;
      -  486  0
                   parentArtifactId = null;
      -  487  0
                   parentVersion = null;
      +  483  2
               if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) {
      +  484  0
                   parentGroupId = null;
      +  485  0
                   parentArtifactId = null;
      +  486  0
                   parentVersion = null;
      +  487   +
               }
       488   -
               }
      -  489  
       
      -  490  2
               if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) {
      -  491  0
                   groupid = parentGroupId;
      +  489  2
               if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) {
      +  490  0
                   groupid = parentGroupId;
      +  491   +
               }
       492   -
               }
      -  493  
       
      -  494  2
               final String originalGroupID = groupid;
      -  495  2
               if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) {
      -  496  1
                   groupid = groupid.substring(4);
      +  493  2
               final String originalGroupID = groupid;
      +  494  2
               if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) {
      +  495  1
                   groupid = groupid.substring(4);
      +  496   +
               }
       497   -
               }
      -  498  
       
      -  499  2
               if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) {
      -  500  0
                   artifactid = parentArtifactId;
      +  498  2
               if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) {
      +  499  0
                   artifactid = parentArtifactId;
      +  500   +
               }
       501   -
               }
      -  502  
       
      -  503  2
               final String originalArtifactID = artifactid;
      -  504  2
               if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) {
      -  505  0
                   artifactid = artifactid.substring(4);
      +  502  2
               final String originalArtifactID = artifactid;
      +  503  2
               if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) {
      +  504  0
                   artifactid = artifactid.substring(4);
      +  505   +
               }
       506   -
               }
      -  507  
       
      -  508  2
               if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) {
      -  509  1
                   version = parentVersion;
      +  507  2
               if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) {
      +  508  1
                   version = parentVersion;
      +  509   +
               }
       510   -
               }
      -  511  
       
      -  512  2
               if (groupid != null && !groupid.isEmpty()) {
      -  513  2
                   foundSomething = true;
      -  514  2
                   dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST);
      -  515  2
                   dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
      -  516  2
                   addMatchingValues(classes, groupid, dependency.getVendorEvidence());
      -  517  2
                   addMatchingValues(classes, groupid, dependency.getProductEvidence());
      -  518  2
                   if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) {
      -  519  1
                       dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM);
      -  520  1
                       dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW);
      -  521  1
                       addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence());
      -  522  1
                       addMatchingValues(classes, parentGroupId, dependency.getProductEvidence());
      +  511  2
               if (groupid != null && !groupid.isEmpty()) {
      +  512  2
                   foundSomething = true;
      +  513  2
                   dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST);
      +  514  2
                   dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW);
      +  515  2
                   addMatchingValues(classes, groupid, dependency.getVendorEvidence());
      +  516  2
                   addMatchingValues(classes, groupid, dependency.getProductEvidence());
      +  517  2
                   if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) {
      +  518  1
                       dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM);
      +  519  1
                       dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW);
      +  520  1
                       addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence());
      +  521  1
                       addMatchingValues(classes, parentGroupId, dependency.getProductEvidence());
      +  522   +
                   }
       523   -
                   }
      -  524  
               } else {
      -  525  0
                   addAsIdentifier = false;
      +  524  0
                   addAsIdentifier = false;
      +  525   +
               }
       526   -
               }
      -  527  
       
      -  528  2
               if (artifactid != null && !artifactid.isEmpty()) {
      -  529  2
                   foundSomething = true;
      -  530  2
                   dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST);
      -  531  2
                   dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
      -  532  2
                   addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
      -  533  2
                   addMatchingValues(classes, artifactid, dependency.getProductEvidence());
      -  534  2
                   if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) {
      -  535  1
                       dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM);
      -  536  1
                       dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW);
      -  537  1
                       addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence());
      -  538  1
                       addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence());
      +  527  2
               if (artifactid != null && !artifactid.isEmpty()) {
      +  528  2
                   foundSomething = true;
      +  529  2
                   dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST);
      +  530  2
                   dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW);
      +  531  2
                   addMatchingValues(classes, artifactid, dependency.getVendorEvidence());
      +  532  2
                   addMatchingValues(classes, artifactid, dependency.getProductEvidence());
      +  533  2
                   if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) {
      +  534  1
                       dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM);
      +  535  1
                       dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW);
      +  536  1
                       addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence());
      +  537  1
                       addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence());
      +  538   +
                   }
       539   -
                   }
      -  540  
               } else {
      -  541  0
                   addAsIdentifier = false;
      +  540  0
                   addAsIdentifier = false;
      +  541   +
               }
       542   -
               }
      -  543  
       
      -  544  2
               if (version != null && !version.isEmpty()) {
      -  545  2
                   foundSomething = true;
      -  546  2
                   dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST);
      -  547  2
                   if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) {
      -  548  0
                       dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW);
      +  543  2
               if (version != null && !version.isEmpty()) {
      +  544  2
                   foundSomething = true;
      +  545  2
                   dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST);
      +  546  2
                   if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) {
      +  547  0
                       dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW);
      +  548   +
                   }
       549   -
                   }
      -  550  
               } else {
      -  551  0
                   addAsIdentifier = false;
      +  550  0
                   addAsIdentifier = false;
      +  551   +
               }
       552   -
               }
      -  553  
       
      -  554  2
               if (addAsIdentifier) {
      -  555  2
                   dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH);
      +  553  2
               if (addAsIdentifier) {
      +  554  2
                   dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH);
      +  555   +
               }
       556   -
               }
      +
       
       557   -
       
      -  558  
               // org name
      -  559  2
               final String org = pom.getOrganization();
      -  560  2
               if (org != null && !org.isEmpty()) {
      -  561  0
                   dependency.getVendorEvidence().addEvidence("pom", "organization name", org, Confidence.HIGH);
      -  562  0
                   dependency.getProductEvidence().addEvidence("pom", "organization name", org, Confidence.LOW);
      -  563  0
                   addMatchingValues(classes, org, dependency.getVendorEvidence());
      -  564  0
                   addMatchingValues(classes, org, dependency.getProductEvidence());
      +  558  2
               final String org = pom.getOrganization();
      +  559  2
               if (org != null && !org.isEmpty()) {
      +  560  0
                   dependency.getVendorEvidence().addEvidence("pom", "organization name", org, Confidence.HIGH);
      +  561  0
                   dependency.getProductEvidence().addEvidence("pom", "organization name", org, Confidence.LOW);
      +  562  0
                   addMatchingValues(classes, org, dependency.getVendorEvidence());
      +  563  0
                   addMatchingValues(classes, org, dependency.getProductEvidence());
      +  564   +
               }
       565   -
               }
      -  566  
               //pom name
      -  567  2
               final String pomName = pom.getName();
      -  568  2
               if (pomName
      -  569  2
                       != null && !pomName.isEmpty()) {
      -  570  2
                   foundSomething = true;
      -  571  2
                   dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
      -  572  2
                   dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
      -  573  2
                   addMatchingValues(classes, pomName, dependency.getVendorEvidence());
      -  574  2
                   addMatchingValues(classes, pomName, dependency.getProductEvidence());
      +  566  2
               final String pomName = pom.getName();
      +  567  2
               if (pomName
      +  568  2
                       != null && !pomName.isEmpty()) {
      +  569  2
                   foundSomething = true;
      +  570  2
                   dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
      +  571  2
                   dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH);
      +  572  2
                   addMatchingValues(classes, pomName, dependency.getVendorEvidence());
      +  573  2
                   addMatchingValues(classes, pomName, dependency.getProductEvidence());
      +  574   +
               }
       575   -
               }
      +
       
       576   -
       
      -  577  
               //Description
      -  578  2
               final String description = pom.getDescription();
      -  579  2
               if (description != null && !description.isEmpty() && !description.startsWith("POM was created by")) {
      -  580  1
                   foundSomething = true;
      -  581  1
                   final String trimmedDescription = addDescription(dependency, description, "pom", "description");
      -  582  1
                   addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence());
      -  583  1
                   addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence());
      +  577  2
               final String description = pom.getDescription();
      +  578  2
               if (description != null && !description.isEmpty() && !description.startsWith("POM was created by")) {
      +  579  1
                   foundSomething = true;
      +  580  1
                   final String trimmedDescription = addDescription(dependency, description, "pom", "description");
      +  581  1
                   addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence());
      +  582  1
                   addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence());
      +  583   +
               }
       584   -
               }
      -  585  
       
      -  586  2
               final String projectURL = pom.getProjectURL();
      -  587  2
               if (projectURL != null && !projectURL.trim().isEmpty()) {
      -  588  1
                   dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST);
      +  585  2
               final String projectURL = pom.getProjectURL();
      +  586  2
               if (projectURL != null && !projectURL.trim().isEmpty()) {
      +  587  1
                   dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST);
      +  588   +
               }
       589   -
               }
      -  590  
       
      -  591  2
               extractLicense(pom, dependency);
      -  592  2
               return foundSomething;
      +  590  2
               extractLicense(pom, dependency);
      +  591  2
               return foundSomething;
      +  592   +
           }
       593   -
           }
      +
       
       594   -
       
      +
           /**
       595   -
           /**
      -  596  
            * Analyzes the path information of the classes contained within the
      -  597   +  596  
            * JarAnalyzer to try and determine possible vendor or product names. If any
      -  598   +  597  
            * are found they are stored in the packageVendor and packageProduct
      -  599   +  598  
            * hashSets.
      +  599   +
            *
       600   -
            *
      +
            * @param classNames a list of class names
       601   -
            * @param classNames a list of class names
      -  602  
            * @param dependency a dependency to analyze
      -  603   +  602  
            * @param addPackagesAsEvidence a flag indicating whether or not package
      -  604   +  603  
            * names should be added as evidence.
      +  604   +
            */
       605   -
            */
      -  606  
           protected void analyzePackageNames(List<ClassNameInformation> classNames,
      -  607   +  606  
                   Dependency dependency, boolean addPackagesAsEvidence) {
      -  608  6
               final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>();
      -  609  6
               final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>();
      -  610  6
               analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers);
      -  611   +  607  6
               final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>();
      +  608  6
               final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>();
      +  609  6
               analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers);
      +  610  
       
      -  612  6
               final int classCount = classNames.size();
      -  613  6
               final EvidenceCollection vendor = dependency.getVendorEvidence();
      -  614  6
               final EvidenceCollection product = dependency.getProductEvidence();
      -  615   +  611  6
               final int classCount = classNames.size();
      +  612  6
               final EvidenceCollection vendor = dependency.getVendorEvidence();
      +  613  6
               final EvidenceCollection product = dependency.getProductEvidence();
      +  614  
       
      -  616  6
               for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) {
      -  617  48
                   final float ratio = entry.getValue() / (float) classCount;
      -  618  48
                   if (ratio > 0.5) {
      -  619   +  615  6
               for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) {
      +  616  48
                   final float ratio = entry.getValue() / (float) classCount;
      +  617  48
                   if (ratio > 0.5) {
      +  618  
                       //TODO remove weighting
      -  620  10
                       vendor.addWeighting(entry.getKey());
      -  621  10
                       if (addPackagesAsEvidence && entry.getKey().length() > 1) {
      -  622  8
                           vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW);
      +  619  10
                       vendor.addWeighting(entry.getKey());
      +  620  10
                       if (addPackagesAsEvidence && entry.getKey().length() > 1) {
      +  621  8
                           vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW);
      +  622   +
                       }
       623   -
                       }
      -  624  
                   }
      -  625  48
               }
      -  626  6
               for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) {
      -  627  985
                   final float ratio = entry.getValue() / (float) classCount;
      -  628  985
                   if (ratio > 0.5) {
      -  629  5
                       product.addWeighting(entry.getKey());
      -  630  5
                       if (addPackagesAsEvidence && entry.getKey().length() > 1) {
      -  631  4
                           product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW);
      +  624  48
               }
      +  625  6
               for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) {
      +  626  985
                   final float ratio = entry.getValue() / (float) classCount;
      +  627  985
                   if (ratio > 0.5) {
      +  628  5
                       product.addWeighting(entry.getKey());
      +  629  5
                       if (addPackagesAsEvidence && entry.getKey().length() > 1) {
      +  630  4
                           product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW);
      +  631   +
                       }
       632   -
                       }
      -  633  
                   }
      -  634  985
               }
      -  635  6
           }
      +  633  985
               }
      +  634  6
           }
      +  635   +
       
       636   -
       
      +
           /**
       637   -
           /**
      -  638  
            * <p>
      -  639   +  638  
            * Reads the manifest from the JAR file and collects the entries. Some
      -  640   +  639  
            * vendorKey entries are:</p>
      -  641   +  640  
            * <ul><li>Implementation Title</li>
      -  642   +  641  
            * <li>Implementation Version</li> <li>Implementation Vendor</li>
      -  643   +  642  
            * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle
      -  644   +  643  
            * Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main
      -  645   +  644  
            * Class</li> </ul>
      -  646   +  645  
            * However, all but a handful of specific entries are read in.
      +  646   +
            *
       647   -
            *
      -  648  
            * @param dependency A reference to the dependency
      -  649   +  648  
            * @param classInformation a collection of class information
      -  650   +  649  
            * @return whether evidence was identified parsing the manifest
      -  651   +  650  
            * @throws IOException if there is an issue reading the JAR file
      +  651   +
            */
       652   -
            */
      -  653  
           protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException {
      -  654  7
               boolean foundSomething = false;
      -  655  7
               JarFile jar = null;
      -  656   +  653  7
               boolean foundSomething = false;
      +  654  7
               JarFile jar = null;
      +  655  
               try {
      -  657  7
                   jar = new JarFile(dependency.getActualFilePath());
      -  658  7
                   final Manifest manifest = jar.getManifest();
      -  659  7
                   if (manifest == null) {
      -  660  0
                       if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar")
      -  661  0
                               && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
      -  662  0
                               && !dependency.getFileName().toLowerCase().endsWith("-src.jar")
      -  663  0
                               && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) {
      -  664  0
                           LOGGER.debug("Jar file '{}' does not contain a manifest.",
      -  665  0
                                   dependency.getFileName());
      -  666   +  656  7
                   jar = new JarFile(dependency.getActualFilePath());
      +  657  7
                   final Manifest manifest = jar.getManifest();
      +  658  7
                   if (manifest == null) {
      +  659  0
                       if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar")
      +  660  0
                               && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
      +  661  0
                               && !dependency.getFileName().toLowerCase().endsWith("-src.jar")
      +  662  0
                               && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) {
      +  663  0
                           LOGGER.debug("Jar file '{}' does not contain a manifest.",
      +  664  0
                                   dependency.getFileName());
      +  665  
                       }
      -  667  0
                       return false;
      -  668   +  666  0
                       return false;
      +  667  
                   }
      -  669  7
                   final EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
      -  670  7
                   final EvidenceCollection productEvidence = dependency.getProductEvidence();
      -  671  7
                   final EvidenceCollection versionEvidence = dependency.getVersionEvidence();
      -  672  7
                   String source = "Manifest";
      -  673  7
                   String specificationVersion = null;
      -  674  7
                   boolean hasImplementationVersion = false;
      -  675  7
                   Attributes atts = manifest.getMainAttributes();
      -  676  7
                   for (Entry<Object, Object> entry : atts.entrySet()) {
      -  677  72
                       String key = entry.getKey().toString();
      -  678  72
                       String value = atts.getValue(key);
      -  679  72
                       if (HTML_DETECTION_PATTERN.matcher(value).find()) {
      -  680  0
                           value = Jsoup.parse(value).text();
      -  681   +  668  7
                   final EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
      +  669  7
                   final EvidenceCollection productEvidence = dependency.getProductEvidence();
      +  670  7
                   final EvidenceCollection versionEvidence = dependency.getVersionEvidence();
      +  671  7
                   String source = "Manifest";
      +  672  7
                   String specificationVersion = null;
      +  673  7
                   boolean hasImplementationVersion = false;
      +  674  7
                   Attributes atts = manifest.getMainAttributes();
      +  675  7
                   for (Entry<Object, Object> entry : atts.entrySet()) {
      +  676  72
                       String key = entry.getKey().toString();
      +  677  72
                       String value = atts.getValue(key);
      +  678  72
                       if (HTML_DETECTION_PATTERN.matcher(value).find()) {
      +  679  0
                           value = Jsoup.parse(value).text();
      +  680  
                       }
      -  682  72
                       if (IGNORE_VALUES.contains(value)) {
      -  683  0
                           continue;
      -  684  72
                       } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
      -  685  1
                           foundSomething = true;
      -  686  1
                           productEvidence.addEvidence(source, key, value, Confidence.HIGH);
      -  687  1
                           addMatchingValues(classInformation, value, productEvidence);
      -  688  71
                       } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
      -  689  2
                           hasImplementationVersion = true;
      -  690  2
                           foundSomething = true;
      -  691  2
                           versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
      -  692  69
                       } else if ("specification-version".equalsIgnoreCase(key)) {
      -  693  1
                           specificationVersion = value;
      -  694  68
                       } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
      -  695  1
                           foundSomething = true;
      -  696  1
                           vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
      -  697  1
                           addMatchingValues(classInformation, value, vendorEvidence);
      -  698  67
                       } else if (key.equalsIgnoreCase(IMPLEMENTATION_VENDOR_ID)) {
      -  699  0
                           foundSomething = true;
      -  700  0
                           vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  701  0
                           addMatchingValues(classInformation, value, vendorEvidence);
      -  702  67
                       } else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) {
      -  703  2
                           foundSomething = true;
      -  704  2
                           addDescription(dependency, value, "manifest", key);
      -  705  2
                           addMatchingValues(classInformation, value, productEvidence);
      -  706  65
                       } else if (key.equalsIgnoreCase(BUNDLE_NAME)) {
      -  707  3
                           foundSomething = true;
      -  708  3
                           productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  709  3
                           addMatchingValues(classInformation, value, productEvidence);
      -  710   +  681  72
                       if (IGNORE_VALUES.contains(value)) {
      +  682  0
                           continue;
      +  683  72
                       } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
      +  684  1
                           foundSomething = true;
      +  685  1
                           productEvidence.addEvidence(source, key, value, Confidence.HIGH);
      +  686  1
                           addMatchingValues(classInformation, value, productEvidence);
      +  687  71
                       } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
      +  688  2
                           hasImplementationVersion = true;
      +  689  2
                           foundSomething = true;
      +  690  2
                           versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
      +  691  69
                       } else if ("specification-version".equalsIgnoreCase(key)) {
      +  692  1
                           specificationVersion = value;
      +  693  68
                       } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
      +  694  1
                           foundSomething = true;
      +  695  1
                           vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
      +  696  1
                           addMatchingValues(classInformation, value, vendorEvidence);
      +  697  67
                       } else if (key.equalsIgnoreCase(IMPLEMENTATION_VENDOR_ID)) {
      +  698  0
                           foundSomething = true;
      +  699  0
                           vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  700  0
                           addMatchingValues(classInformation, value, vendorEvidence);
      +  701  67
                       } else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) {
      +  702  2
                           foundSomething = true;
      +  703  2
                           addDescription(dependency, value, "manifest", key);
      +  704  2
                           addMatchingValues(classInformation, value, productEvidence);
      +  705  65
                       } else if (key.equalsIgnoreCase(BUNDLE_NAME)) {
      +  706  3
                           foundSomething = true;
      +  707  3
                           productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  708  3
                           addMatchingValues(classInformation, value, productEvidence);
      +  709  
       //                //the following caused false positives.
      -  711   +  710  
       //                } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) {
      -  712  62
                       } else if (key.equalsIgnoreCase(BUNDLE_VERSION)) {
      -  713  3
                           foundSomething = true;
      -  714  3
                           versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
      -  715  59
                       } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
      -  716  3
                           continue;
      -  717   +  711  62
                       } else if (key.equalsIgnoreCase(BUNDLE_VERSION)) {
      +  712  3
                           foundSomething = true;
      +  713  3
                           versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
      +  714  59
                       } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
      +  715  3
                           continue;
      +  716  
                           //skipping main class as if this has important information to add it will be added during class name analysis...
      -  718   +  717  
                       } else {
      -  719  56
                           key = key.toLowerCase();
      -  720  56
                           if (!IGNORE_KEYS.contains(key)
      -  721  15
                                   && !key.endsWith("jdk")
      -  722  15
                                   && !key.contains("lastmodified")
      -  723  14
                                   && !key.endsWith("package")
      -  724  14
                                   && !key.endsWith("classpath")
      -  725  14
                                   && !key.endsWith("class-path")
      -  726  14
                                   && !key.endsWith("-scm") //todo change this to a regex?
      -  727  14
                                   && !key.startsWith("scm-")
      -  728  14
                                   && !value.trim().startsWith("scm:")
      -  729  14
                                   && !isImportPackage(key, value)
      -  730  14
                                   && !isPackage(key, value)) {
      -  731  13
                               foundSomething = true;
      -  732  13
                               if (key.contains("version")) {
      -  733  0
                                   if (!key.contains("specification")) {
      -  734  0
                                       versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  735   +  718  56
                           key = key.toLowerCase();
      +  719  56
                           if (!IGNORE_KEYS.contains(key)
      +  720  15
                                   && !key.endsWith("jdk")
      +  721  15
                                   && !key.contains("lastmodified")
      +  722  14
                                   && !key.endsWith("package")
      +  723  14
                                   && !key.endsWith("classpath")
      +  724  14
                                   && !key.endsWith("class-path")
      +  725  14
                                   && !key.endsWith("-scm") //todo change this to a regex?
      +  726  14
                                   && !key.startsWith("scm-")
      +  727  14
                                   && !value.trim().startsWith("scm:")
      +  728  14
                                   && !isImportPackage(key, value)
      +  729  14
                                   && !isPackage(key, value)) {
      +  730  13
                               foundSomething = true;
      +  731  13
                               if (key.contains("version")) {
      +  732  0
                                   if (!key.contains("specification")) {
      +  733  0
                                       versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  734  
                                   }
      -  736  13
                               } else if ("build-id".equals(key)) {
      -  737  0
                                   int pos = value.indexOf('(');
      -  738  0
                                   if (pos >= 0) {
      -  739  0
                                       value = value.substring(0, pos - 1);
      -  740   +  735  13
                               } else if ("build-id".equals(key)) {
      +  736  0
                                   int pos = value.indexOf('(');
      +  737  0
                                   if (pos >= 0) {
      +  738  0
                                       value = value.substring(0, pos - 1);
      +  739  
                                   }
      -  741  0
                                   pos = value.indexOf('[');
      -  742  0
                                   if (pos >= 0) {
      -  743  0
                                       value = value.substring(0, pos - 1);
      -  744   +  740  0
                                   pos = value.indexOf('[');
      +  741  0
                                   if (pos >= 0) {
      +  742  0
                                       value = value.substring(0, pos - 1);
      +  743  
                                   }
      -  745  0
                                   versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  746  0
                               } else if (key.contains("title")) {
      -  747  1
                                   productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  748  1
                                   addMatchingValues(classInformation, value, productEvidence);
      -  749  12
                               } else if (key.contains("vendor")) {
      -  750  0
                                   if (key.contains("specification")) {
      -  751  0
                                       vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
      -  752   +  744  0
                                   versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  745  0
                               } else if (key.contains("title")) {
      +  746  1
                                   productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  747  1
                                   addMatchingValues(classInformation, value, productEvidence);
      +  748  12
                               } else if (key.contains("vendor")) {
      +  749  0
                                   if (key.contains("specification")) {
      +  750  0
                                       vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
      +  751  
                                   } else {
      -  753  0
                                       vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  754  0
                                       addMatchingValues(classInformation, value, vendorEvidence);
      -  755   +  752  0
                                       vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  753  0
                                       addMatchingValues(classInformation, value, vendorEvidence);
      +  754  
                                   }
      -  756  12
                               } else if (key.contains("name")) {
      -  757  3
                                   productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  758  3
                                   vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  759  3
                                   addMatchingValues(classInformation, value, vendorEvidence);
      -  760  3
                                   addMatchingValues(classInformation, value, productEvidence);
      -  761  9
                               } else if (key.contains("license")) {
      -  762  2
                                   addLicense(dependency, value);
      -  763  7
                               } else if (key.contains("description")) {
      -  764  0
                                   addDescription(dependency, value, "manifest", key);
      -  765   +  755  12
                               } else if (key.contains("name")) {
      +  756  3
                                   productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  757  3
                                   vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  758  3
                                   addMatchingValues(classInformation, value, vendorEvidence);
      +  759  3
                                   addMatchingValues(classInformation, value, productEvidence);
      +  760  9
                               } else if (key.contains("license")) {
      +  761  2
                                   addLicense(dependency, value);
      +  762  7
                               } else if (key.contains("description")) {
      +  763  0
                                   addDescription(dependency, value, "manifest", key);
      +  764  
                               } else {
      -  766  7
                                   productEvidence.addEvidence(source, key, value, Confidence.LOW);
      -  767  7
                                   vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
      -  768  7
                                   addMatchingValues(classInformation, value, vendorEvidence);
      -  769  7
                                   addMatchingValues(classInformation, value, productEvidence);
      -  770  7
                                   if (value.matches(".*\\d.*")) {
      -  771  3
                                       final StringTokenizer tokenizer = new StringTokenizer(value, " ");
      -  772  15
                                       while (tokenizer.hasMoreElements()) {
      -  773  12
                                           final String s = tokenizer.nextToken();
      -  774  12
                                           if (s.matches("^[0-9.]+$")) {
      -  775  1
                                               versionEvidence.addEvidence(source, key, s, Confidence.LOW);
      -  776   +  765  7
                                   productEvidence.addEvidence(source, key, value, Confidence.LOW);
      +  766  7
                                   vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
      +  767  7
                                   addMatchingValues(classInformation, value, vendorEvidence);
      +  768  7
                                   addMatchingValues(classInformation, value, productEvidence);
      +  769  7
                                   if (value.matches(".*\\d.*")) {
      +  770  3
                                       final StringTokenizer tokenizer = new StringTokenizer(value, " ");
      +  771  15
                                       while (tokenizer.hasMoreElements()) {
      +  772  12
                                           final String s = tokenizer.nextToken();
      +  773  12
                                           if (s.matches("^[0-9.]+$")) {
      +  774  1
                                               versionEvidence.addEvidence(source, key, s, Confidence.LOW);
      +  775  
                                           }
      -  777  12
                                       }
      -  778   +  776  12
                                       }
      +  777  
                                   }
      -  779   +  778  
                               }
      +  779   +
                           }
       780   -
                           }
      -  781  
                       }
      -  782  69
                   }
      -  783  7
                   for (Map.Entry<String, Attributes> item : manifest.getEntries().entrySet()) {
      -  784  8
                       final String name = item.getKey();
      -  785  8
                       source = "manifest: " + name;
      -  786  8
                       atts = item.getValue();
      -  787  8
                       for (Entry<Object, Object> entry : atts.entrySet()) {
      -  788  38
                           final String key = entry.getKey().toString();
      -  789  38
                           final String value = atts.getValue(key);
      -  790  38
                           if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
      -  791  8
                               foundSomething = true;
      -  792  8
                               productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  793  8
                               addMatchingValues(classInformation, value, productEvidence);
      -  794  30
                           } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
      -  795  5
                               foundSomething = true;
      -  796  5
                               versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  797  25
                           } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
      -  798  5
                               foundSomething = true;
      -  799  5
                               vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  800  5
                               addMatchingValues(classInformation, value, vendorEvidence);
      -  801  20
                           } else if (key.equalsIgnoreCase(Attributes.Name.SPECIFICATION_TITLE.toString())) {
      -  802  4
                               foundSomething = true;
      -  803  4
                               productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      -  804  4
                               addMatchingValues(classInformation, value, productEvidence);
      -  805   +  781  69
                   }
      +  782  7
                   for (Map.Entry<String, Attributes> item : manifest.getEntries().entrySet()) {
      +  783  8
                       final String name = item.getKey();
      +  784  8
                       source = "manifest: " + name;
      +  785  8
                       atts = item.getValue();
      +  786  8
                       for (Entry<Object, Object> entry : atts.entrySet()) {
      +  787  38
                           final String key = entry.getKey().toString();
      +  788  38
                           final String value = atts.getValue(key);
      +  789  38
                           if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
      +  790  8
                               foundSomething = true;
      +  791  8
                               productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  792  8
                               addMatchingValues(classInformation, value, productEvidence);
      +  793  30
                           } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
      +  794  5
                               foundSomething = true;
      +  795  5
                               versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  796  25
                           } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
      +  797  5
                               foundSomething = true;
      +  798  5
                               vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  799  5
                               addMatchingValues(classInformation, value, vendorEvidence);
      +  800  20
                           } else if (key.equalsIgnoreCase(Attributes.Name.SPECIFICATION_TITLE.toString())) {
      +  801  4
                               foundSomething = true;
      +  802  4
                               productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
      +  803  4
                               addMatchingValues(classInformation, value, productEvidence);
      +  804  
                           }
      -  806  38
                       }
      -  807  8
                   }
      -  808  7
                   if (specificationVersion != null && !hasImplementationVersion) {
      -  809  0
                       foundSomething = true;
      -  810  0
                       versionEvidence.addEvidence(source, "specification-version", specificationVersion, Confidence.HIGH);
      +  805  38
                       }
      +  806  8
                   }
      +  807  7
                   if (specificationVersion != null && !hasImplementationVersion) {
      +  808  0
                       foundSomething = true;
      +  809  0
                       versionEvidence.addEvidence(source, "specification-version", specificationVersion, Confidence.HIGH);
      +  810   +
                   }
       811   -
                   }
      -  812  
               } finally {
      -  813  7
                   if (jar != null) {
      -  814  7
                       jar.close();
      +  812  7
                   if (jar != null) {
      +  813  7
                       jar.close();
      +  814   +
                   }
       815   -
                   }
      -  816  
               }
      -  817  7
               return foundSomething;
      +  816  7
               return foundSomething;
      +  817   +
           }
       818   -
           }
      +
       
       819   -
       
      +
           /**
       820   -
           /**
      -  821  
            * Adds a description to the given dependency. If the description contains
      -  822   +  821  
            * one of the following strings beyond 100 characters, then the description
      -  823   +  822  
            * used will be trimmed to that position:
      -  824   +  823  
            * <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses
      -  825   +  824  
            * "</li></ul>
      +  825   +
            *
       826   -
            *
      -  827  
            * @param dependency a dependency
      -  828   +  827  
            * @param description the description
      -  829   +  828  
            * @param source the source of the evidence
      -  830   +  829  
            * @param key the "name" of the evidence
      -  831   +  830  
            * @return if the description is trimmed, the trimmed version is returned;
      -  832   +  831  
            * otherwise the original description is returned
      +  832   +
            */
       833   -
            */
      -  834  
           public static String addDescription(Dependency dependency, String description, String source, String key) {
      -  835  10
               if (dependency.getDescription() == null) {
      -  836  10
                   dependency.setDescription(description);
      +  834  10
               if (dependency.getDescription() == null) {
      +  835  10
                   dependency.setDescription(description);
      +  836   +
               }
       837   -
               }
      -  838  
               String desc;
      -  839  10
               if (HTML_DETECTION_PATTERN.matcher(description).find()) {
      -  840  0
                   desc = Jsoup.parse(description).text();
      -  841   +  838  10
               if (HTML_DETECTION_PATTERN.matcher(description).find()) {
      +  839  0
                   desc = Jsoup.parse(description).text();
      +  840  
               } else {
      -  842  10
                   desc = description;
      -  843   +  841  10
                   desc = description;
      +  842  
               }
      -  844  10
               dependency.setDescription(desc);
      -  845  10
               if (desc.length() > 100) {
      -  846  0
                   desc = desc.replaceAll("\\s\\s+", " ");
      -  847  0
                   final int posSuchAs = desc.toLowerCase().indexOf("such as ", 100);
      -  848  0
                   final int posLike = desc.toLowerCase().indexOf("like ", 100);
      -  849  0
                   final int posWillUse = desc.toLowerCase().indexOf("will use ", 100);
      -  850  0
                   final int posUses = desc.toLowerCase().indexOf(" uses ", 100);
      -  851  0
                   int pos = -1;
      -  852  0
                   pos = Math.max(pos, posSuchAs);
      -  853  0
                   if (pos >= 0 && posLike >= 0) {
      -  854  0
                       pos = Math.min(pos, posLike);
      -  855   +  843  10
               dependency.setDescription(desc);
      +  844  10
               if (desc.length() > 100) {
      +  845  0
                   desc = desc.replaceAll("\\s\\s+", " ");
      +  846  0
                   final int posSuchAs = desc.toLowerCase().indexOf("such as ", 100);
      +  847  0
                   final int posLike = desc.toLowerCase().indexOf("like ", 100);
      +  848  0
                   final int posWillUse = desc.toLowerCase().indexOf("will use ", 100);
      +  849  0
                   final int posUses = desc.toLowerCase().indexOf(" uses ", 100);
      +  850  0
                   int pos = -1;
      +  851  0
                   pos = Math.max(pos, posSuchAs);
      +  852  0
                   if (pos >= 0 && posLike >= 0) {
      +  853  0
                       pos = Math.min(pos, posLike);
      +  854  
                   } else {
      -  856  0
                       pos = Math.max(pos, posLike);
      -  857   +  855  0
                       pos = Math.max(pos, posLike);
      +  856  
                   }
      -  858  0
                   if (pos >= 0 && posWillUse >= 0) {
      -  859  0
                       pos = Math.min(pos, posWillUse);
      -  860   +  857  0
                   if (pos >= 0 && posWillUse >= 0) {
      +  858  0
                       pos = Math.min(pos, posWillUse);
      +  859  
                   } else {
      -  861  0
                       pos = Math.max(pos, posWillUse);
      -  862   +  860  0
                       pos = Math.max(pos, posWillUse);
      +  861  
                   }
      -  863  0
                   if (pos >= 0 && posUses >= 0) {
      -  864  0
                       pos = Math.min(pos, posUses);
      -  865   +  862  0
                   if (pos >= 0 && posUses >= 0) {
      +  863  0
                       pos = Math.min(pos, posUses);
      +  864  
                   } else {
      -  866  0
                       pos = Math.max(pos, posUses);
      +  865  0
                       pos = Math.max(pos, posUses);
      +  866   +
                   }
       867   -
                   }
      -  868  
       
      -  869  0
                   if (pos > 0) {
      -  870  0
                       desc = desc.substring(0, pos) + "...";
      -  871   +  868  0
                   if (pos > 0) {
      +  869  0
                       desc = desc.substring(0, pos) + "...";
      +  870  
                   }
      -  872  0
                   dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW);
      -  873  0
                   dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW);
      -  874  0
               } else {
      -  875  10
                   dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
      -  876  10
                   dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
      -  877   +  871  0
                   dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW);
      +  872  0
                   dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW);
      +  873  0
               } else {
      +  874  10
                   dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
      +  875  10
                   dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.MEDIUM);
      +  876  
               }
      -  878  10
               return desc;
      +  877  10
               return desc;
      +  878   +
           }
       879   -
           }
      +
       
       880   -
       
      +
           /**
       881   -
           /**
      -  882  
            * Adds a license to the given dependency.
      +  882   +
            *
       883   -
            *
      -  884  
            * @param d a dependency
      -  885   +  884  
            * @param license the license
      +  885   +
            */
       886   -
            */
      -  887  
           private void addLicense(Dependency d, String license) {
      -  888  2
               if (d.getLicense() == null) {
      -  889  2
                   d.setLicense(license);
      -  890  0
               } else if (!d.getLicense().contains(license)) {
      -  891  0
                   d.setLicense(d.getLicense() + NEWLINE + license);
      -  892   +  887  2
               if (d.getLicense() == null) {
      +  888  2
                   d.setLicense(license);
      +  889  0
               } else if (!d.getLicense().contains(license)) {
      +  890  0
                   d.setLicense(d.getLicense() + NEWLINE + license);
      +  891  
               }
      -  893  2
           }
      +  892  2
           }
      +  893   +
       
       894   -
       
      +
           /**
       895   -
           /**
      -  896  
            * The parent directory for the individual directories per archive.
      -  897   +  896  
            */
      -  898  10
           private File tempFileLocation = null;
      +  897  13
           private File tempFileLocation = null;
      +  898   +
       
       899   -
       
      +
           /**
       900   -
           /**
      -  901  
            * Initializes the JarAnalyzer.
      +  901   +
            *
       902   -
            *
      -  903  
            * @throws InitializationException is thrown if there is an exception
      -  904   +  903  
            * creating a temporary directory
      +  904   +
            */
       905   -
            */
      +
           @Override
       906   -
           @Override
      -  907  
           public void initializeFileTypeAnalyzer() throws InitializationException {
      -  908   +  907  
               try {
      -  909  1
                   final File baseDir = Settings.getTempDirectory();
      -  910  1
                   tempFileLocation = File.createTempFile("check", "tmp", baseDir);
      -  911  1
                   if (!tempFileLocation.delete()) {
      -  912  0
                       final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
      -  913  0
                       setEnabled(false);
      -  914  0
                       throw new InitializationException(msg);
      -  915   +  908  1
                   final File baseDir = Settings.getTempDirectory();
      +  909  1
                   tempFileLocation = File.createTempFile("check", "tmp", baseDir);
      +  910  1
                   if (!tempFileLocation.delete()) {
      +  911  0
                       final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
      +  912  0
                       setEnabled(false);
      +  913  0
                       throw new InitializationException(msg);
      +  914  
                   }
      -  916  1
                   if (!tempFileLocation.mkdirs()) {
      -  917  0
                       final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
      -  918  0
                       setEnabled(false);
      -  919  0
                       throw new InitializationException(msg);
      -  920   +  915  1
                   if (!tempFileLocation.mkdirs()) {
      +  916  0
                       final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
      +  917  0
                       setEnabled(false);
      +  918  0
                       throw new InitializationException(msg);
      +  919  
                   }
      -  921  0
               } catch (IOException ex) {
      -  922  0
                   setEnabled(false);
      -  923  0
                   throw new InitializationException("Unable to create a temporary file", ex);
      -  924  1
               }
      -  925  1
           }
      +  920  0
               } catch (IOException ex) {
      +  921  0
                   setEnabled(false);
      +  922  0
                   throw new InitializationException("Unable to create a temporary file", ex);
      +  923  1
               }
      +  924  1
           }
      +  925   +
       
       926   -
       
      +
           /**
       927   -
           /**
      -  928  
            * Deletes any files extracted from the JAR during analysis.
      +  928   +
            */
       929   -
            */
      -  930  
           @Override
      -  931   +  930  
           public void close() {
      -  932  2
               if (tempFileLocation != null && tempFileLocation.exists()) {
      -  933  1
                   LOGGER.debug("Attempting to delete temporary files");
      -  934  1
                   final boolean success = FileUtils.delete(tempFileLocation);
      -  935  1
                   if (!success) {
      -  936  0
                       LOGGER.warn("Failed to delete some temporary files, see the log for more details");
      -  937   -
                   }
      +  931  2
               if (tempFileLocation != null && tempFileLocation.exists()) {
      +  932  1
                   LOGGER.debug("Attempting to delete temporary files");
      +  933  1
                   final boolean success = FileUtils.delete(tempFileLocation);
      +  934  1
                   if (!success && tempFileLocation.exists()) {
      +  935  0
                       final String[] l = tempFileLocation.list();
      +  936  0
                       if (l != null && l.length > 0) {
      +  937  0
                           LOGGER.warn("Failed to delete some temporary files, see the log for more details");
       938   -
               }
      -  939  2
           }
      +
                       }
      +  939   +
                   }
       940   -
       
      -  941   -
           /**
      +
               }
      +  941  2
           }
       942   -
            * Determines if the key value pair from the manifest is for an "import"
      +
       
       943   -
            * type entry for package names.
      +
           /**
       944   -
            *
      +
            * Determines if the key value pair from the manifest is for an "import"
       945   -
            * @param key the key from the manifest
      +
            * type entry for package names.
       946   -
            * @param value the value from the manifest
      +
            *
       947   -
            * @return true or false depending on if it is believed the entry is an
      +
            * @param key the key from the manifest
       948   -
            * "import" entry
      +
            * @param value the value from the manifest
       949   -
            */
      +
            * @return true or false depending on if it is believed the entry is an
       950   +
            * "import" entry
      +  951   +
            */
      +  952  
           private boolean isImportPackage(String key, String value) {
      -  951  14
               final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$");
      -  952  14
               final boolean matches = packageRx.matcher(value).matches();
      -  953  14
               return matches && (key.contains("import") || key.contains("include") || value.length() > 10);
      -  954   -
           }
      -  955   -
       
      +  953  14
               final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$");
      +  954  14
               final boolean matches = packageRx.matcher(value).matches();
      +  955  14
               return matches && (key.contains("import") || key.contains("include") || value.length() > 10);
       956   -
           /**
      +
           }
       957   -
            * Cycles through an enumeration of JarEntries, contained within the
      +
       
       958   -
            * dependency, and returns a list of the class names. This does not include
      +
           /**
       959   -
            * core Java package names (i.e. java.* or javax.*).
      +
            * Cycles through an enumeration of JarEntries, contained within the
       960   -
            *
      +
            * dependency, and returns a list of the class names. This does not include
       961   -
            * @param dependency the dependency being analyzed
      +
            * core Java package names (i.e. java.* or javax.*).
       962   -
            * @return an list of fully qualified class names
      +
            *
       963   -
            */
      +
            * @param dependency the dependency being analyzed
       964   +
            * @return an list of fully qualified class names
      +  965   +
            */
      +  966  
           private List<ClassNameInformation> collectClassNames(Dependency dependency) {
      -  965  6
               final List<ClassNameInformation> classNames = new ArrayList<ClassNameInformation>();
      -  966  6
               JarFile jar = null;
      -  967   +  967  6
               final List<ClassNameInformation> classNames = new ArrayList<ClassNameInformation>();
      +  968  6
               JarFile jar = null;
      +  969  
               try {
      -  968  6
                   jar = new JarFile(dependency.getActualFilePath());
      -  969  6
                   final Enumeration<JarEntry> entries = jar.entries();
      -  970  1852
                   while (entries.hasMoreElements()) {
      -  971  1846
                       final JarEntry entry = entries.nextElement();
      -  972  1846
                       final String name = entry.getName().toLowerCase();
      -  973   +  970  6
                   jar = new JarFile(dependency.getActualFilePath());
      +  971  6
                   final Enumeration<JarEntry> entries = jar.entries();
      +  972  1848
                   while (entries.hasMoreElements()) {
      +  973  1842
                       final JarEntry entry = entries.nextElement();
      +  974  1842
                       final String name = entry.getName().toLowerCase();
      +  975  
                       //no longer stripping "|com\\.sun" - there are some com.sun jar files with CVEs.
      -  974  1846
                       if (name.endsWith(".class") && !name.matches("^javax?\\..*$")) {
      -  975  1535
                           final ClassNameInformation className = new ClassNameInformation(name.substring(0, name.length() - 6));
      -  976  1535
                           classNames.add(className);
      -  977   +  976  1846
                       if (name.endsWith(".class") && !name.matches("^javax?\\..*$")) {
      +  977  1535
                           final ClassNameInformation className = new ClassNameInformation(name.substring(0, name.length() - 6));
      +  978  1535
                           classNames.add(className);
      +  979  
                       }
      -  978  1846
                   }
      -  979  0
               } catch (IOException ex) {
      -  980  0
                   LOGGER.warn("Unable to open jar file '{}'.", dependency.getFileName());
      -  981  0
                   LOGGER.debug("", ex);
      -  982   -
               } finally {
      -  983  6
                   if (jar != null) {
      +  980  1841
                   }
      +  981  0
               } catch (IOException ex) {
      +  982  0
                   LOGGER.warn("Unable to open jar file '{}'.", dependency.getFileName());
      +  983  0
                   LOGGER.debug("", ex);
       984   +
               } finally {
      +  985  6
                   if (jar != null) {
      +  986  
                       try {
      -  985  6
                           jar.close();
      -  986  0
                       } catch (IOException ex) {
      -  987  0
                           LOGGER.trace("", ex);
      -  988  6
                       }
      -  989   +  987  6
                           jar.close();
      +  988  0
                       } catch (IOException ex) {
      +  989  0
                           LOGGER.trace("", ex);
      +  990  6
                       }
      +  991  
                   }
      -  990   -
               }
      -  991  6
               return classNames;
       992   -
           }
      -  993   -
       
      +
               }
      +  993  6
               return classNames;
       994   -
           /**
      -  995   -
            * Cycles through the list of class names and places the package levels 0-3
      -  996   -
            * into the provided maps for vendor and product. This is helpful when
      -  997   -
            * analyzing vendor/product as many times this is included in the package
      -  998   -
            * name.
      -  999   -
            *
      -  1000   -
            * @param classNames a list of class names
      -  1001   -
            * @param vendor HashMap of possible vendor names from package names (e.g.
      -  1002   -
            * owasp)
      -  1003   -
            * @param product HashMap of possible product names from package names (e.g.
      -  1004   -
            * dependencycheck)
      -  1005   -
            */
      -  1006   -
           private void analyzeFullyQualifiedClassNames(List<ClassNameInformation> classNames,
      -  1007   -
                   Map<String, Integer> vendor, Map<String, Integer> product) {
      -  1008  6
               for (ClassNameInformation entry : classNames) {
      -  1009  1535
                   final List<String> list = entry.getPackageStructure();
      -  1010  1535
                   addEntry(vendor, list.get(0));
      -  1011   -
       
      -  1012  1535
                   if (list.size() == 2) {
      -  1013  0
                       addEntry(product, list.get(1));
      -  1014   -
                   }
      -  1015  1535
                   if (list.size() == 3) {
      -  1016  345
                       addEntry(vendor, list.get(1));
      -  1017  345
                       addEntry(product, list.get(1));
      -  1018  345
                       addEntry(product, list.get(2));
      -  1019   -
                   }
      -  1020  1535
                   if (list.size() >= 4) {
      -  1021  1190
                       addEntry(vendor, list.get(1));
      -  1022  1190
                       addEntry(vendor, list.get(2));
      -  1023  1190
                       addEntry(product, list.get(1));
      -  1024  1190
                       addEntry(product, list.get(2));
      -  1025  1190
                       addEntry(product, list.get(3));
      -  1026   -
                   }
      -  1027  1535
               }
      -  1028  6
           }
      -  1029   -
       
      -  1030   -
           /**
      -  1031   -
            * Adds an entry to the specified collection and sets the Integer (e.g. the
      -  1032   -
            * count) to 1. If the entry already exists in the collection then the
      -  1033   -
            * Integer is incremented by 1.
      -  1034   -
            *
      -  1035   -
            * @param collection a collection of strings and their occurrence count
      -  1036   -
            * @param key the key to add to the collection
      -  1037   -
            */
      -  1038   -
           private void addEntry(Map<String, Integer> collection, String key) {
      -  1039  8520
               if (collection.containsKey(key)) {
      -  1040  7487
                   collection.put(key, collection.get(key) + 1);
      -  1041   -
               } else {
      -  1042  1033
                   collection.put(key, 1);
      -  1043   -
               }
      -  1044  8520
           }
      -  1045   -
       
      -  1046   -
           /**
      -  1047   -
            * Cycles through the collection of class name information to see if parts
      -  1048   -
            * of the package names are contained in the provided value. If found, it
      -  1049   -
            * will be added as the HIGHEST confidence evidence because we have more
      -  1050   -
            * then one source corroborating the value.
      -  1051   -
            *
      -  1052   -
            * @param classes a collection of class name information
      -  1053   -
            * @param value the value to check to see if it contains a package name
      -  1054   -
            * @param evidence the evidence collection to add new entries too
      -  1055   -
            */
      -  1056   -
           private static void addMatchingValues(List<ClassNameInformation> classes, String value, EvidenceCollection evidence) {
      -  1057  63
               if (value == null || value.isEmpty() || classes == null || classes.isEmpty()) {
      -  1058  21
                   return;
      -  1059   -
               }
      -  1060  42
               final String text = value.toLowerCase();
      -  1061  42
               for (ClassNameInformation cni : classes) {
      -  1062  16322
                   for (String key : cni.getPackageStructure()) {
      -  1063  62418
                       final Pattern p = Pattern.compile("\b" + key + "\b");
      -  1064  62418
                       if (p.matcher(text).find()) {
      -  1065   -
                           //if (text.contains(key)) { //note, package structure elements are already lowercase.
      -  1066  0
                           evidence.addEvidence("jar", "package name", key, Confidence.HIGHEST);
      -  1067   -
                       }
      -  1068  62418
                   }
      -  1069  16322
               }
      -  1070  42
           }
      -  1071   -
       
      -  1072   -
           /**
      -  1073   -
            * Simple check to see if the attribute from a manifest is just a package
      -  1074   -
            * name.
      -  1075   -
            *
      -  1076   -
            * @param key the key of the value to check
      -  1077   -
            * @param value the value to check
      -  1078   -
            * @return true if the value looks like a java package name, otherwise false
      -  1079   -
            */
      -  1080   -
           private boolean isPackage(String key, String value) {
      -  1081   -
       
      -  1082  28
               return !key.matches(".*(version|title|vendor|name|license|description).*")
      -  1083  8
                       && value.matches("^([a-zA-Z_][a-zA-Z0-9_\\$]*(\\.[a-zA-Z_][a-zA-Z0-9_\\$]*)*)?$");
      -  1084   -
       
      -  1085  
           }
      +  995   +
       
      +  996   +
           /**
      +  997   +
            * Cycles through the list of class names and places the package levels 0-3
      +  998   +
            * into the provided maps for vendor and product. This is helpful when
      +  999   +
            * analyzing vendor/product as many times this is included in the package
      +  1000   +
            * name.
      +  1001   +
            *
      +  1002   +
            * @param classNames a list of class names
      +  1003   +
            * @param vendor HashMap of possible vendor names from package names (e.g.
      +  1004   +
            * owasp)
      +  1005   +
            * @param product HashMap of possible product names from package names (e.g.
      +  1006   +
            * dependencycheck)
      +  1007   +
            */
      +  1008   +
           private void analyzeFullyQualifiedClassNames(List<ClassNameInformation> classNames,
      +  1009   +
                   Map<String, Integer> vendor, Map<String, Integer> product) {
      +  1010  6
               for (ClassNameInformation entry : classNames) {
      +  1011  1535
                   final List<String> list = entry.getPackageStructure();
      +  1012  1535
                   addEntry(vendor, list.get(0));
      +  1013   +
       
      +  1014  1535
                   if (list.size() == 2) {
      +  1015  0
                       addEntry(product, list.get(1));
      +  1016   +
                   }
      +  1017  1535
                   if (list.size() == 3) {
      +  1018  345
                       addEntry(vendor, list.get(1));
      +  1019  345
                       addEntry(product, list.get(1));
      +  1020  345
                       addEntry(product, list.get(2));
      +  1021   +
                   }
      +  1022  1535
                   if (list.size() >= 4) {
      +  1023  1190
                       addEntry(vendor, list.get(1));
      +  1024  1190
                       addEntry(vendor, list.get(2));
      +  1025  1190
                       addEntry(product, list.get(1));
      +  1026  1190
                       addEntry(product, list.get(2));
      +  1027  1190
                       addEntry(product, list.get(3));
      +  1028   +
                   }
      +  1029  1535
               }
      +  1030  6
           }
      +  1031   +
       
      +  1032   +
           /**
      +  1033   +
            * Adds an entry to the specified collection and sets the Integer (e.g. the
      +  1034   +
            * count) to 1. If the entry already exists in the collection then the
      +  1035   +
            * Integer is incremented by 1.
      +  1036   +
            *
      +  1037   +
            * @param collection a collection of strings and their occurrence count
      +  1038   +
            * @param key the key to add to the collection
      +  1039   +
            */
      +  1040   +
           private void addEntry(Map<String, Integer> collection, String key) {
      +  1041  8520
               if (collection.containsKey(key)) {
      +  1042  7487
                   collection.put(key, collection.get(key) + 1);
      +  1043   +
               } else {
      +  1044  1033
                   collection.put(key, 1);
      +  1045   +
               }
      +  1046  8520
           }
      +  1047   +
       
      +  1048   +
           /**
      +  1049   +
            * Cycles through the collection of class name information to see if parts
      +  1050   +
            * of the package names are contained in the provided value. If found, it
      +  1051   +
            * will be added as the HIGHEST confidence evidence because we have more
      +  1052   +
            * then one source corroborating the value.
      +  1053   +
            *
      +  1054   +
            * @param classes a collection of class name information
      +  1055   +
            * @param value the value to check to see if it contains a package name
      +  1056   +
            * @param evidence the evidence collection to add new entries too
      +  1057   +
            */
      +  1058   +
           private static void addMatchingValues(List<ClassNameInformation> classes, String value, EvidenceCollection evidence) {
      +  1059  63
               if (value == null || value.isEmpty() || classes == null || classes.isEmpty()) {
      +  1060  21
                   return;
      +  1061   +
               }
      +  1062  42
               final String text = value.toLowerCase();
      +  1063  42
               for (ClassNameInformation cni : classes) {
      +  1064  16320
                   for (String key : cni.getPackageStructure()) {
      +  1065  62390
                       final Pattern p = Pattern.compile("\b" + key + "\b");
      +  1066  62417
                       if (p.matcher(text).find()) {
      +  1067   +
                           //if (text.contains(key)) { //note, package structure elements are already lowercase.
      +  1068  0
                           evidence.addEvidence("jar", "package name", key, Confidence.HIGHEST);
      +  1069   +
                       }
      +  1070  62390
                   }
      +  1071  16318
               }
      +  1072  42
           }
      +  1073   +
       
      +  1074   +
           /**
      +  1075   +
            * Simple check to see if the attribute from a manifest is just a package
      +  1076   +
            * name.
      +  1077   +
            *
      +  1078   +
            * @param key the key of the value to check
      +  1079   +
            * @param value the value to check
      +  1080   +
            * @return true if the value looks like a java package name, otherwise false
      +  1081   +
            */
      +  1082   +
           private boolean isPackage(String key, String value) {
      +  1083   +
       
      +  1084  28
               return !key.matches(".*(version|title|vendor|name|license|description).*")
      +  1085  8
                       && value.matches("^([a-zA-Z_][a-zA-Z0-9_\\$]*(\\.[a-zA-Z_][a-zA-Z0-9_\\$]*)*)?$");
       1086  
       
       1087   -
           /**
      +
           }
       1088   -
            * Extracts the license information from the pom and adds it to the
      +
       
       1089   -
            * dependency.
      +
           /**
       1090   -
            *
      +
            * Extracts the license information from the pom and adds it to the
       1091   -
            * @param pom the pom object
      +
            * dependency.
       1092   -
            * @param dependency the dependency to add license information too
      -  1093   -
            */
      -  1094   -
           public static void extractLicense(Model pom, Dependency dependency) {
      -  1095   -
               //license
      -  1096  2
               if (pom.getLicenses() != null) {
      -  1097  2
                   String license = null;
      -  1098  2
                   for (License lic : pom.getLicenses()) {
      -  1099  0
                       String tmp = null;
      -  1100  0
                       if (lic.getName() != null) {
      -  1101  0
                           tmp = lic.getName();
      -  1102   -
                       }
      -  1103  0
                       if (lic.getUrl() != null) {
      -  1104  0
                           if (tmp == null) {
      -  1105  0
                               tmp = lic.getUrl();
      -  1106   -
                           } else {
      -  1107  0
                               tmp += ": " + lic.getUrl();
      -  1108   -
                           }
      -  1109   -
                       }
      -  1110  0
                       if (tmp == null) {
      -  1111  0
                           continue;
      -  1112   -
                       }
      -  1113  0
                       if (HTML_DETECTION_PATTERN.matcher(tmp).find()) {
      -  1114  0
                           tmp = Jsoup.parse(tmp).text();
      -  1115   -
                       }
      -  1116  0
                       if (license == null) {
      -  1117  0
                           license = tmp;
      -  1118   -
                       } else {
      -  1119  0
                           license += "\n" + tmp;
      -  1120   -
                       }
      -  1121  0
                   }
      -  1122  2
                   if (license != null) {
      -  1123  0
                       dependency.setLicense(license);
      -  1124   -
       
      -  1125   -
                   }
      -  1126   -
               }
      -  1127  2
           }
      -  1128   -
       
      -  1129   -
           /**
      -  1130   -
            * Stores information about a class name.
      -  1131   -
            */
      -  1132   -
           protected static class ClassNameInformation {
      -  1133   -
       
      -  1134   -
               /**
      -  1135   -
                * <p>
      -  1136   -
                * Stores information about a given class name. This class will keep the
      -  1137   -
                * fully qualified class name and a list of the important parts of the
      -  1138   -
                * package structure. Up to the first four levels of the package
      -  1139   -
                * structure are stored, excluding a leading "org" or "com".
      -  1140   -
                * Example:</p>
      -  1141   -
                * <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer");
      -  1142   -
                * System.out.println(obj.getName());
      -  1143   -
                * for (String p : obj.getPackageStructure())
      -  1144   -
                *     System.out.println(p);
      -  1145   -
                * </code>
      -  1146   -
                * <p>
      -  1147   -
                * Would result in:</p>
      -  1148   -
                * <code>org.owasp.dependencycheck.analyzer.JarAnalyzer
      -  1149   -
                * owasp
      -  1150   -
                * dependencycheck
      -  1151   -
                * analyzer
      -  1152   -
                * jaranalyzer</code>
      -  1153   -
                *
      -  1154   -
                * @param className a fully qualified class name
      -  1155   -
                */
      -  1156  1535
               ClassNameInformation(String className) {
      -  1157  1535
                   name = className;
      -  1158  1535
                   if (name.contains("/")) {
      -  1159  1535
                       final String[] tmp = className.toLowerCase().split("/");
      -  1160  1535
                       int start = 0;
      -  1161  1535
                       int end = 3;
      -  1162  1535
                       if ("com".equals(tmp[0]) || "org".equals(tmp[0])) {
      -  1163  1535
                           start = 1;
      -  1164  1535
                           end = 4;
      -  1165   -
                       }
      -  1166  1535
                       if (tmp.length <= end) {
      -  1167  345
                           end = tmp.length - 1;
      -  1168   -
                       }
      -  1169  7330
                       for (int i = start; i <= end; i++) {
      -  1170  5795
                           packageStructure.add(tmp[i]);
      -  1171   -
                       }
      -  1172  1535
                   } else {
      -  1173  0
                       packageStructure.add(name);
      -  1174   -
                   }
      -  1175  1535
               }
      -  1176   -
               /**
      -  1177   -
                * The fully qualified class name.
      -  1178   -
                */
      -  1179   -
               private String name;
      -  1180   -
       
      -  1181   -
               /**
      -  1182   -
                * Get the value of name
      -  1183   -
                *
      -  1184   -
                * @return the value of name
      -  1185   -
                */
      -  1186   -
               public String getName() {
      -  1187  0
                   return name;
      -  1188   -
               }
      -  1189   -
       
      -  1190   -
               /**
      -  1191   -
                * Set the value of name
      -  1192   -
                *
      -  1193   -
                * @param name new value of name
      -  1194   -
                */
      -  1195   -
               public void setName(String name) {
      -  1196  0
                   this.name = name;
      -  1197  0
               }
      -  1198   -
               /**
      -  1199   -
                * Up to the first four levels of the package structure, excluding a
      -  1200   -
                * leading "org" or "com".
      -  1201   -
                */
      -  1202  1535
               private final ArrayList<String> packageStructure = new ArrayList<String>();
      -  1203   -
       
      -  1204   -
               /**
      -  1205   -
                * Get the value of packageStructure
      -  1206   -
                *
      -  1207   -
                * @return the value of packageStructure
      -  1208   -
                */
      -  1209   -
               public ArrayList<String> getPackageStructure() {
      -  1210  17857
                   return packageStructure;
      -  1211   -
               }
      -  1212   -
           }
      -  1213   -
       
      -  1214   -
           /**
      -  1215   -
            * Retrieves the next temporary directory to extract an archive too.
      -  1216  
            *
      -  1217   -
            * @return a directory
      -  1218   -
            * @throws AnalysisException thrown if unable to create temporary directory
      -  1219   +  1093   +
            * @param pom the pom object
      +  1094   +
            * @param dependency the dependency to add license information too
      +  1095  
            */
      -  1220   -
           private File getNextTempDirectory() throws AnalysisException {
      -  1221  0
               dirCount += 1;
      -  1222  0
               final File directory = new File(tempFileLocation, String.valueOf(dirCount));
      -  1223   -
               //getting an exception for some directories not being able to be created; might be because the directory already exists?
      -  1224  0
               if (directory.exists()) {
      -  1225  0
                   return getNextTempDirectory();
      -  1226   +  1096   +
           public static void extractLicense(Model pom, Dependency dependency) {
      +  1097   +
               //license
      +  1098  2
               if (pom.getLicenses() != null) {
      +  1099  2
                   String license = null;
      +  1100  2
                   for (License lic : pom.getLicenses()) {
      +  1101  0
                       String tmp = null;
      +  1102  0
                       if (lic.getName() != null) {
      +  1103  0
                           tmp = lic.getName();
      +  1104   +
                       }
      +  1105  0
                       if (lic.getUrl() != null) {
      +  1106  0
                           if (tmp == null) {
      +  1107  0
                               tmp = lic.getUrl();
      +  1108   +
                           } else {
      +  1109  0
                               tmp += ": " + lic.getUrl();
      +  1110   +
                           }
      +  1111   +
                       }
      +  1112  0
                       if (tmp == null) {
      +  1113  0
                           continue;
      +  1114   +
                       }
      +  1115  0
                       if (HTML_DETECTION_PATTERN.matcher(tmp).find()) {
      +  1116  0
                           tmp = Jsoup.parse(tmp).text();
      +  1117   +
                       }
      +  1118  0
                       if (license == null) {
      +  1119  0
                           license = tmp;
      +  1120   +
                       } else {
      +  1121  0
                           license += "\n" + tmp;
      +  1122   +
                       }
      +  1123  0
                   }
      +  1124  2
                   if (license != null) {
      +  1125  0
                       dependency.setLicense(license);
      +  1126   +
       
      +  1127   +
                   }
      +  1128  
               }
      -  1227  0
               if (!directory.mkdirs()) {
      -  1228  0
                   final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath());
      -  1229  0
                   throw new AnalysisException(msg);
      -  1230   +  1129  2
           }
      +  1130   +
       
      +  1131   +
           /**
      +  1132   +
            * Stores information about a class name.
      +  1133   +
            */
      +  1134   +
           protected static class ClassNameInformation {
      +  1135   +
       
      +  1136   +
               /**
      +  1137   +
                * <p>
      +  1138   +
                * Stores information about a given class name. This class will keep the
      +  1139   +
                * fully qualified class name and a list of the important parts of the
      +  1140   +
                * package structure. Up to the first four levels of the package
      +  1141   +
                * structure are stored, excluding a leading "org" or "com".
      +  1142   +
                * Example:</p>
      +  1143   +
                * <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer");
      +  1144   +
                * System.out.println(obj.getName());
      +  1145   +
                * for (String p : obj.getPackageStructure())
      +  1146   +
                *     System.out.println(p);
      +  1147   +
                * </code>
      +  1148   +
                * <p>
      +  1149   +
                * Would result in:</p>
      +  1150   +
                * <code>org.owasp.dependencycheck.analyzer.JarAnalyzer
      +  1151   +
                * owasp
      +  1152   +
                * dependencycheck
      +  1153   +
                * analyzer
      +  1154   +
                * jaranalyzer</code>
      +  1155   +
                *
      +  1156   +
                * @param className a fully qualified class name
      +  1157   +
                */
      +  1158  1535
               ClassNameInformation(String className) {
      +  1159  1535
                   name = className;
      +  1160  1535
                   if (name.contains("/")) {
      +  1161  1535
                       final String[] tmp = className.toLowerCase().split("/");
      +  1162  1535
                       int start = 0;
      +  1163  1535
                       int end = 3;
      +  1164  1535
                       if ("com".equals(tmp[0]) || "org".equals(tmp[0])) {
      +  1165  1535
                           start = 1;
      +  1166  1535
                           end = 4;
      +  1167   +
                       }
      +  1168  1535
                       if (tmp.length <= end) {
      +  1169  345
                           end = tmp.length - 1;
      +  1170   +
                       }
      +  1171  7330
                       for (int i = start; i <= end; i++) {
      +  1172  5795
                           packageStructure.add(tmp[i]);
      +  1173   +
                       }
      +  1174  1535
                   } else {
      +  1175  0
                       packageStructure.add(name);
      +  1176   +
                   }
      +  1177  1535
               }
      +  1178   +
               /**
      +  1179   +
                * The fully qualified class name.
      +  1180   +
                */
      +  1181   +
               private String name;
      +  1182   +
       
      +  1183   +
               /**
      +  1184   +
                * Get the value of name
      +  1185   +
                *
      +  1186   +
                * @return the value of name
      +  1187   +
                */
      +  1188   +
               public String getName() {
      +  1189  0
                   return name;
      +  1190  
               }
      -  1231  0
               return directory;
      -  1232   +  1191   +
       
      +  1192   +
               /**
      +  1193   +
                * Set the value of name
      +  1194   +
                *
      +  1195   +
                * @param name new value of name
      +  1196   +
                */
      +  1197   +
               public void setName(String name) {
      +  1198  0
                   this.name = name;
      +  1199  0
               }
      +  1200   +
               /**
      +  1201   +
                * Up to the first four levels of the package structure, excluding a
      +  1202   +
                * leading "org" or "com".
      +  1203   +
                */
      +  1204  1535
               private final ArrayList<String> packageStructure = new ArrayList<String>();
      +  1205   +
       
      +  1206   +
               /**
      +  1207   +
                * Get the value of packageStructure
      +  1208   +
                *
      +  1209   +
                * @return the value of packageStructure
      +  1210   +
                */
      +  1211   +
               public ArrayList<String> getPackageStructure() {
      +  1212  17855
                   return packageStructure;
      +  1213   +
               }
      +  1214  
           }
      -  1233   +  1215   +
       
      +  1216   +
           /**
      +  1217   +
            * Retrieves the next temporary directory to extract an archive too.
      +  1218   +
            *
      +  1219   +
            * @return a directory
      +  1220   +
            * @throws AnalysisException thrown if unable to create temporary directory
      +  1221   +
            */
      +  1222   +
           private File getNextTempDirectory() throws AnalysisException {
      +  1223  0
               final int dirCount = DIR_COUNT.incrementAndGet();
      +  1224  0
               final File directory = new File(tempFileLocation, String.valueOf(dirCount));
      +  1225   +
               //getting an exception for some directories not being able to be created; might be because the directory already exists?
      +  1226  0
               if (directory.exists()) {
      +  1227  0
                   return getNextTempDirectory();
      +  1228   +
               }
      +  1229  0
               if (!directory.mkdirs()) {
      +  1230  0
                   final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath());
      +  1231  0
                   throw new AnalysisException(msg);
      +  1232   +
               }
      +  1233  0
               return directory;
      +  1234   +
           }
      +  1235  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NexusAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NexusAnalyzer.html index 049b29ba1..380af31c7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NexusAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NexusAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      NexusAnalyzer
      19%
      14/71
      3%
      1/26
      3.75
      NexusAnalyzer
      18%
      14/77
      3%
      1/30
      3.778
       
      @@ -139,7 +139,7 @@
        * @author colezlaw
       61  
        */
      -  62  6
       public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
      +  62  8
       public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
       63  
       
       64   @@ -193,293 +193,321 @@  89  
       
       90   -
           /**
      +
           private boolean useProxy;
       91   -
            * The Nexus Search to be set up for this analyzer.
      +
           /**
       92   -
            */
      +
            * The Nexus Search to be set up for this analyzer.
       93   -
           private NexusSearch searcher;
      +
            */
       94   -
       
      +
           private NexusSearch searcher;
       95   -
           /**
      +
       
       96   -
            * Field indicating if the analyzer is enabled.
      +
           /**
       97   +
            * Field indicating if the analyzer is enabled.
      +  98  
            */
      -  98  6
           private final boolean enabled = checkEnabled();
      -  99   -
       
      +  99  8
           private final boolean enabled = checkEnabled();
       100   -
           /**
      +
       
       101   -
            * Determines if this analyzer is enabled
      +
           /**
       102   -
            *
      +
            * Determines if this analyzer is enabled
       103   -
            * @return <code>true</code> if the analyzer is enabled; otherwise
      +
            *
       104   -
            * <code>false</code>
      +
            * @return <code>true</code> if the analyzer is enabled; otherwise
       105   -
            */
      +
            * <code>false</code>
       106   -
           private boolean checkEnabled() {
      +
            */
       107   -
               /* Enable this analyzer ONLY if the Nexus URL has been set to something
      +
           private boolean checkEnabled() {
       108   -
                other than the default one (if it's the default one, we'll use the
      +
               /* Enable this analyzer ONLY if the Nexus URL has been set to something
       109   -
                central one) and it's enabled by the user.
      +
                other than the default one (if it's the default one, we'll use the
       110   +
                central one) and it's enabled by the user.
      +  111  
                */
      -  111  6
               boolean retval = false;
      -  112   +  112  8
               boolean retval = false;
      +  113  
               try {
      -  113  6
                   if (!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL))
      -  114  0
                           && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) {
      -  115  0
                       LOGGER.info("Enabling Nexus analyzer");
      -  116  0
                       retval = true;
      -  117   +  114  8
                   if (!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL))
      +  115  0
                           && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) {
      +  116  0
                       LOGGER.info("Enabling Nexus analyzer");
      +  117  0
                       retval = true;
      +  118  
                   } else {
      -  118  6
                       LOGGER.debug("Nexus analyzer disabled, using Central instead");
      -  119   +  119  8
                       LOGGER.debug("Nexus analyzer disabled, using Central instead");
      +  120  
                   }
      -  120  0
               } catch (InvalidSettingException ise) {
      -  121  0
                   LOGGER.warn("Invalid setting. Disabling Nexus analyzer");
      -  122  6
               }
      -  123   +  121  0
               } catch (InvalidSettingException ise) {
      +  122  0
                   LOGGER.warn("Invalid setting. Disabling Nexus analyzer");
      +  123  8
               }
      +  124  
       
      -  124  6
               return retval;
      -  125   -
           }
      +  125  8
               return retval;
       126   -
       
      +
           }
       127   -
           /**
      +
       
       128   -
            * Determine whether to enable this analyzer or not.
      +
           /**
       129   -
            *
      +
            * Determine whether to enable this analyzer or not.
       130   -
            * @return whether the analyzer should be enabled
      +
            *
       131   -
            */
      +
            * @return whether the analyzer should be enabled
       132   -
           @Override
      +
            */
       133   +
           @Override
      +  134  
           public boolean isEnabled() {
      -  134  0
               return enabled;
      -  135   -
           }
      +  135  0
               return enabled;
       136   -
       
      +
           }
       137   -
           /**
      +
       
       138   -
            * Initializes the analyzer once before any analysis is performed.
      +
           /**
       139   -
            *
      +
            * Initializes the analyzer once before any analysis is performed.
       140   -
            * @throws InitializationException if there's an error during initialization
      +
            *
       141   -
            */
      +
            * @throws InitializationException if there's an error during initialization
       142   -
           @Override
      +
            */
       143   +
           @Override
      +  144  
           public void initializeFileTypeAnalyzer() throws InitializationException {
      -  144  0
               LOGGER.debug("Initializing Nexus Analyzer");
      -  145  0
               LOGGER.debug("Nexus Analyzer enabled: {}", isEnabled());
      -  146  0
               if (isEnabled()) {
      -  147  0
                   final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
      -  148  0
                   LOGGER.debug("Nexus Analyzer URL: {}", searchUrl);
      -  149   +  145  0
               LOGGER.debug("Initializing Nexus Analyzer");
      +  146  0
               LOGGER.debug("Nexus Analyzer enabled: {}", isEnabled());
      +  147  0
               if (isEnabled()) {
      +  148  0
                   useProxy = useProxy();
      +  149  0
                   final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
      +  150  0
                   LOGGER.debug("Nexus Analyzer URL: {}", searchUrl);
      +  151  
                   try {
      -  150  0
                       searcher = new NexusSearch(new URL(searchUrl));
      -  151  0
                       if (!searcher.preflightRequest()) {
      -  152  0
                           setEnabled(false);
      -  153  0
                           throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer.");
      -  154   +  152  0
                       searcher = new NexusSearch(new URL(searchUrl), useProxy);
      +  153  0
                       if (!searcher.preflightRequest()) {
      +  154  0
                           setEnabled(false);
      +  155  0
                           throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer.");
      +  156  
                       }
      -  155  0
                   } catch (MalformedURLException mue) {
      -  156  0
                       setEnabled(false);
      -  157  0
                       throw new InitializationException("Malformed URL to Nexus: " + searchUrl, mue);
      -  158  0
                   }
      -  159   -
               }
      -  160  0
           }
      +  157  0
                   } catch (MalformedURLException mue) {
      +  158  0
                       setEnabled(false);
      +  159  0
                       throw new InitializationException("Malformed URL to Nexus: " + searchUrl, mue);
      +  160  0
                   }
       161   -
       
      -  162   -
           /**
      -  163   -
            * Returns the analyzer's name.
      -  164   -
            *
      -  165   -
            * @return the name of the analyzer
      -  166   -
            */
      -  167   -
           @Override
      -  168   -
           public String getName() {
      -  169  16
               return ANALYZER_NAME;
      -  170   -
           }
      -  171   -
       
      -  172   -
           /**
      -  173   -
            * Returns the key used in the properties file to reference the analyzer's
      -  174   -
            * enabled property.
      -  175   -
            *
      -  176   -
            * @return the analyzer's enabled property setting key
      -  177   -
            */
      -  178   -
           @Override
      -  179   -
           protected String getAnalyzerEnabledSettingKey() {
      -  180  6
               return Settings.KEYS.ANALYZER_NEXUS_ENABLED;
      -  181   -
           }
      -  182   -
       
      -  183   -
           /**
      -  184   -
            * Returns the analysis phase under which the analyzer runs.
      -  185   -
            *
      -  186   -
            * @return the phase under which this analyzer runs
      -  187   -
            */
      -  188   -
           @Override
      -  189   -
           public AnalysisPhase getAnalysisPhase() {
      -  190  4
               return ANALYSIS_PHASE;
      -  191   -
           }
      -  192   -
       
      -  193   -
           /**
      -  194   -
            * The file filter used to determine which files this analyzer supports.
      -  195   -
            */
      -  196  1
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(SUPPORTED_EXTENSIONS).build();
      -  197   -
       
      -  198   -
           /**
      -  199   -
            * Returns the FileFilter
      -  200   -
            *
      -  201   -
            * @return the FileFilter
      -  202   -
            */
      -  203   -
           @Override
      -  204   -
           protected FileFilter getFileFilter() {
      -  205  859
               return FILTER;
      -  206   -
           }
      -  207   -
       
      -  208   -
           /**
      -  209   -
            * Performs the analysis.
      -  210   -
            *
      -  211   -
            * @param dependency the dependency to analyze
      -  212   -
            * @param engine the engine
      -  213   -
            * @throws AnalysisException when there's an exception during analysis
      -  214   -
            */
      -  215   -
           @Override
      -  216   -
           public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
      -  217  0
               if (!isEnabled()) {
      -  218  0
                   return;
      -  219  
               }
      -  220   +  162  0
           }
      +  163   +
       
      +  164   +
           /**
      +  165   +
            * Returns the analyzer's name.
      +  166   +
            *
      +  167   +
            * @return the name of the analyzer
      +  168   +
            */
      +  169   +
           @Override
      +  170   +
           public String getName() {
      +  171  22
               return ANALYZER_NAME;
      +  172   +
           }
      +  173   +
       
      +  174   +
           /**
      +  175   +
            * Returns the key used in the properties file to reference the analyzer's
      +  176   +
            * enabled property.
      +  177   +
            *
      +  178   +
            * @return the analyzer's enabled property setting key
      +  179   +
            */
      +  180   +
           @Override
      +  181   +
           protected String getAnalyzerEnabledSettingKey() {
      +  182  8
               return Settings.KEYS.ANALYZER_NEXUS_ENABLED;
      +  183   +
           }
      +  184   +
       
      +  185   +
           /**
      +  186   +
            * Returns the analysis phase under which the analyzer runs.
      +  187   +
            *
      +  188   +
            * @return the phase under which this analyzer runs
      +  189   +
            */
      +  190   +
           @Override
      +  191   +
           public AnalysisPhase getAnalysisPhase() {
      +  192  6
               return ANALYSIS_PHASE;
      +  193   +
           }
      +  194   +
       
      +  195   +
           /**
      +  196   +
            * The file filter used to determine which files this analyzer supports.
      +  197   +
            */
      +  198  1
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(SUPPORTED_EXTENSIONS).build();
      +  199   +
       
      +  200   +
           /**
      +  201   +
            * Returns the FileFilter
      +  202   +
            *
      +  203   +
            * @return the FileFilter
      +  204   +
            */
      +  205   +
           @Override
      +  206   +
           protected FileFilter getFileFilter() {
      +  207  862
               return FILTER;
      +  208   +
           }
      +  209   +
       
      +  210   +
           /**
      +  211   +
            * Performs the analysis.
      +  212   +
            *
      +  213   +
            * @param dependency the dependency to analyze
      +  214   +
            * @param engine the engine
      +  215   +
            * @throws AnalysisException when there's an exception during analysis
      +  216   +
            */
      +  217   +
           @Override
      +  218   +
           public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
      +  219  0
               if (!isEnabled()) {
      +  220  0
                   return;
      +  221   +
               }
      +  222  
               try {
      -  221  0
                   final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum());
      -  222  0
                   dependency.addAsEvidence("nexus", ma, Confidence.HIGH);
      -  223  0
                   boolean pomAnalyzed = false;
      -  224  0
                   LOGGER.debug("POM URL {}", ma.getPomUrl());
      -  225  0
                   for (Evidence e : dependency.getVendorEvidence()) {
      -  226  0
                       if ("pom".equals(e.getSource())) {
      -  227  0
                           pomAnalyzed = true;
      -  228  0
                           break;
      -  229   +  223  0
                   final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum());
      +  224  0
                   dependency.addAsEvidence("nexus", ma, Confidence.HIGH);
      +  225  0
                   boolean pomAnalyzed = false;
      +  226  0
                   LOGGER.debug("POM URL {}", ma.getPomUrl());
      +  227  0
                   for (Evidence e : dependency.getVendorEvidence()) {
      +  228  0
                       if ("pom".equals(e.getSource())) {
      +  229  0
                           pomAnalyzed = true;
      +  230  0
                           break;
      +  231  
                       }
      -  230  0
                   }
      -  231  0
                   if (!pomAnalyzed && ma.getPomUrl() != null) {
      -  232  0
                       File pomFile = null;
      -  233   +  232  0
                   }
      +  233  0
                   if (!pomAnalyzed && ma.getPomUrl() != null) {
      +  234  0
                       File pomFile = null;
      +  235  
                       try {
      -  234  0
                           final File baseDir = Settings.getTempDirectory();
      -  235  0
                           pomFile = File.createTempFile("pom", ".xml", baseDir);
      -  236  0
                           if (!pomFile.delete()) {
      -  237  0
                               LOGGER.warn("Unable to fetch pom.xml for {} from Nexus repository; "
      -  238  0
                                       + "this could result in undetected CPE/CVEs.", dependency.getFileName());
      -  239  0
                               LOGGER.debug("Unable to delete temp file");
      -  240   +  236  0
                           final File baseDir = Settings.getTempDirectory();
      +  237  0
                           pomFile = File.createTempFile("pom", ".xml", baseDir);
      +  238  0
                           if (!pomFile.delete()) {
      +  239  0
                               LOGGER.warn("Unable to fetch pom.xml for {} from Nexus repository; "
      +  240  0
                                       + "this could result in undetected CPE/CVEs.", dependency.getFileName());
      +  241  0
                               LOGGER.debug("Unable to delete temp file");
      +  242  
                           }
      -  241  0
                           LOGGER.debug("Downloading {}", ma.getPomUrl());
      -  242  0
                           Downloader.fetchFile(new URL(ma.getPomUrl()), pomFile);
      -  243  0
                           PomUtils.analyzePOM(dependency, pomFile);
      -  244  0
                       } catch (DownloadFailedException ex) {
      -  245  0
                           LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; "
      -  246  0
                                   + "this could result in undetected CPE/CVEs.", dependency.getFileName());
      -  247   +  243  0
                           LOGGER.debug("Downloading {}", ma.getPomUrl());
      +  244  0
                           Downloader.fetchFile(new URL(ma.getPomUrl()), pomFile);
      +  245  0
                           PomUtils.analyzePOM(dependency, pomFile);
      +  246  0
                       } catch (DownloadFailedException ex) {
      +  247  0
                           LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; "
      +  248  0
                                   + "this could result in undetected CPE/CVEs.", dependency.getFileName());
      +  249  
                       } finally {
      -  248  0
                           if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
      -  249  0
                               LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString());
      -  250  0
                               pomFile.deleteOnExit();
      -  251   -
                           }
      -  252   -
                       }
      +  250  0
                           if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
      +  251  0
                               LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString());
      +  252  0
                               pomFile.deleteOnExit();
       253   -
                   }
      -  254  0
               } catch (IllegalArgumentException iae) {
      +
                           }
      +  254   +
                       }
       255   +
                   }
      +  256  0
               } catch (IllegalArgumentException iae) {
      +  257  
                   //dependency.addAnalysisException(new AnalysisException("Invalid SHA-1"));
      -  256  0
                   LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName());
      -  257  0
               } catch (FileNotFoundException fnfe) {
      -  258   +  258  0
                   LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName());
      +  259  0
               } catch (FileNotFoundException fnfe) {
      +  260  
                   //dependency.addAnalysisException(new AnalysisException("Artifact not found on repository"));
      -  259  0
                   LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName());
      -  260  0
                   LOGGER.debug(fnfe.getMessage(), fnfe);
      -  261  0
               } catch (IOException ioe) {
      -  262   +  261  0
                   LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName());
      +  262  0
                   LOGGER.debug(fnfe.getMessage(), fnfe);
      +  263  0
               } catch (IOException ioe) {
      +  264  
                   //dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe));
      -  263  0
                   LOGGER.debug("Could not connect to nexus repository", ioe);
      -  264  0
               }
      -  265  0
           }
      -  266   +  265  0
                   LOGGER.debug("Could not connect to nexus repository", ioe);
      +  266  0
               }
      +  267  0
           }
      +  268   +
           
      +  269   +
           /**
      +  270   +
            * Determine if a proxy should be used.
      +  271   +
            *
      +  272   +
            * @return {@code true} if a proxy should be used
      +  273   +
            */
      +  274   +
           public static boolean useProxy() {
      +  275   +
               try {
      +  276  0
                   return Settings.getString(Settings.KEYS.PROXY_SERVER) != null
      +  277  0
                           && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
      +  278  0
               } catch (InvalidSettingException ise) {
      +  279  0
                   LOGGER.warn("Failed to parse proxy settings.", ise);
      +  280  0
                   return false;
      +  281   +
               }
      +  282   +
           }
      +  283  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NodePackageAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NodePackageAnalyzer.html index 0ec6c82fe..ea964fc47 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NodePackageAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NodePackageAnalyzer.html @@ -115,7 +115,7 @@
        */
       49  
       @Experimental
      -  50  9
       public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
      +  50  11
       public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
       51  
       
       52   @@ -178,7 +178,7 @@
           @Override
       83  
           protected FileFilter getFileFilter() {
      -  84  860
               return PACKAGE_JSON_FILTER;
      +  84  863
               return PACKAGE_JSON_FILTER;
       85  
           }
       86   @@ -206,7 +206,7 @@
           @Override
       98  
           public String getName() {
      -  99  15
               return ANALYZER_NAME;
      +  99  21
               return ANALYZER_NAME;
       100  
           }
       101   @@ -225,7 +225,7 @@
           @Override
       108  
           public AnalysisPhase getAnalysisPhase() {
      -  109  4
               return ANALYSIS_PHASE;
      +  109  6
               return ANALYSIS_PHASE;
       110  
           }
       111   @@ -246,7 +246,7 @@
           @Override
       119  
           protected String getAnalyzerEnabledSettingKey() {
      -  120  9
               return Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED;
      +  120  11
               return Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED;
       121  
           }
       122   @@ -348,6 +348,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NuspecAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NuspecAnalyzer.html index c4b5d80db..7a68506f5 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NuspecAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NuspecAnalyzer.html @@ -103,7 +103,7 @@
        * @author colezlaw
       43  
        */
      -  44  9
       public class NuspecAnalyzer extends AbstractFileTypeAnalyzer {
      +  44  11
       public class NuspecAnalyzer extends AbstractFileTypeAnalyzer {
       45  
       
       46   @@ -175,7 +175,7 @@
           @Override
       81  
           public String getName() {
      -  82  17
               return ANALYZER_NAME;
      +  82  23
               return ANALYZER_NAME;
       83  
           }
       84   @@ -196,7 +196,7 @@
           @Override
       92  
           protected String getAnalyzerEnabledSettingKey() {
      -  93  9
               return Settings.KEYS.ANALYZER_NUSPEC_ENABLED;
      +  93  11
               return Settings.KEYS.ANALYZER_NUSPEC_ENABLED;
       94  
           }
       95   @@ -215,7 +215,7 @@
           @Override
       102  
           public AnalysisPhase getAnalysisPhase() {
      -  103  5
               return ANALYSIS_PHASE;
      +  103  7
               return ANALYSIS_PHASE;
       104  
           }
       105   @@ -244,7 +244,7 @@
           @Override
       118  
           protected FileFilter getFileFilter() {
      -  119  861
               return FILTER;
      +  119  863
               return FILTER;
       120  
           }
       121   @@ -315,6 +315,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NvdCveAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NvdCveAnalyzer.html index 98357ff14..66637e2ef 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NvdCveAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.NvdCveAnalyzer.html @@ -93,7 +93,7 @@
        * @author Jeremy Long
       38  
        */
      -  39  6
       public class NvdCveAnalyzer implements Analyzer {
      +  39  8
       public class NvdCveAnalyzer extends AbstractAnalyzer {
       40  
           /**
       41   @@ -169,7 +169,7 @@
            */
       80  
           public boolean isOpen() {
      -  81  6
               return cveDB != null;
      +  81  4
               return cveDB != null;
       82  
           }
       83   @@ -188,12 +188,12 @@
           @Override
       90  
           protected void finalize() throws Throwable {
      -  91  6
               super.finalize();
      -  92  6
               if (isOpen()) {
      +  91  4
               super.finalize();
      +  92  4
               if (isOpen()) {
       93  0
                   close();
       94  
               }
      -  95  6
           }
      +  95  4
           }
       96  
       
       97   @@ -215,19 +215,19 @@  105  
           public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
       106  4
               for (Identifier id : dependency.getIdentifiers()) {
      -  107  3
                   if ("cpe".equals(id.getType())) {
      +  107  4
                   if ("cpe".equals(id.getType())) {
       108  
                       try {
      -  109  3
                           final String value = id.getValue();
      -  110  3
                           final List<Vulnerability> vulns = cveDB.getVulnerabilities(value);
      -  111  3
                           dependency.getVulnerabilities().addAll(vulns);
      +  109  4
                           final String value = id.getValue();
      +  110  4
                           final List<Vulnerability> vulns = cveDB.getVulnerabilities(value);
      +  111  4
                           dependency.getVulnerabilities().addAll(vulns);
       112  0
                       } catch (DatabaseException ex) {
       113  0
                           throw new AnalysisException(ex);
      -  114  3
                       }
      +  114  4
                       }
       115  
                   }
      -  116  3
               }
      -  117  4
               for (Identifier id : dependency.getSuppressedIdentifiers()) {
      +  116  4
               }
      +  117  3
               for (Identifier id : dependency.getSuppressedIdentifiers()) {
       118  0
                   if ("cpe".equals(id.getType())) {
       119  
                       try {
      @@ -257,7 +257,7 @@
           @Override
       136  
           public String getName() {
      -  137  16
               return "NVD CVE Analyzer";
      +  137  26
               return "NVD CVE Analyzer";
       138  
           }
       139   @@ -276,7 +276,7 @@
           @Override
       146  
           public AnalysisPhase getAnalysisPhase() {
      -  147  4
               return AnalysisPhase.FINDING_ANALYSIS;
      +  147  6
               return AnalysisPhase.FINDING_ANALYSIS;
       148  
           }
       149   @@ -316,6 +316,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.OpenSSLAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.OpenSSLAnalyzer.html index 126a97005..d341f226c 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.OpenSSLAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.OpenSSLAnalyzer.html @@ -97,7 +97,7 @@
        * @author Dale Visser
       40  
        */
      -  41  10
       public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
      +  41  12
       public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
       42  
       
       43   @@ -250,7 +250,7 @@
           @Override
       122  
           public String getName() {
      -  123  17
               return "OpenSSL Source Analyzer";
      +  123  23
               return "OpenSSL Source Analyzer";
       124  
           }
       125   @@ -269,7 +269,7 @@
           @Override
       132  
           public AnalysisPhase getAnalysisPhase() {
      -  133  4
               return AnalysisPhase.INFORMATION_COLLECTION;
      +  133  6
               return AnalysisPhase.INFORMATION_COLLECTION;
       134  
           }
       135   @@ -288,7 +288,7 @@
           @Override
       142  
           protected FileFilter getFileFilter() {
      -  143  860
               return OPENSSLV_FILTER;
      +  143  863
               return OPENSSLV_FILTER;
       144  
           }
       145   @@ -405,13 +405,13 @@
           @Override
       211  
           protected String getAnalyzerEnabledSettingKey() {
      -  212  10
               return Settings.KEYS.ANALYZER_OPENSSL_ENABLED;
      +  212  12
               return Settings.KEYS.ANALYZER_OPENSSL_ENABLED;
       213  
           }
       214  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonDistributionAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonDistributionAnalyzer.html index 74ecc5351..33210a790 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonDistributionAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonDistributionAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      PythonDistributionAnalyzer
      80%
      96/119
      61%
      32/52
      3.769
      PythonDistributionAnalyzer
      79%
      96/121
      55%
      32/58
      4
       
      @@ -112,602 +112,606 @@  47  
       import org.owasp.dependencycheck.utils.UrlStringUtils;
       48   -
       
      +
       import java.util.concurrent.atomic.AtomicInteger;
       49   -
       /**
      +
       
       50   -
        * Used to analyze a Wheel or egg distribution files, or their contents in
      +
       /**
       51   -
        * unzipped form, and collect information that can be used to determine the
      +
        * Used to analyze a Wheel or egg distribution files, or their contents in
       52   -
        * associated CPE.
      +
        * unzipped form, and collect information that can be used to determine the
       53   -
        *
      +
        * associated CPE.
       54   -
        * @author Dale Visser
      +
        *
       55   -
        */
      +
        * @author Dale Visser
       56   +
        */
      +  57  
       @Experimental
      -  57  14
       public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
      -  58   -
       
      +  58  16
       public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
       59   -
           /**
      +
       
       60   -
            * Name of egg metadata files to analyze.
      +
           /**
       61   -
            */
      +
            * Name of egg metadata files to analyze.
       62   -
           private static final String PKG_INFO = "PKG-INFO";
      +
            */
       63   -
       
      +
           private static final String PKG_INFO = "PKG-INFO";
       64   -
           /**
      +
       
       65   -
            * Name of wheel metadata files to analyze.
      +
           /**
       66   -
            */
      +
            * Name of wheel metadata files to analyze.
       67   -
           private static final String METADATA = "METADATA";
      +
            */
       68   -
       
      +
           private static final String METADATA = "METADATA";
       69   -
           /**
      +
       
       70   -
            * The logger.
      +
           /**
       71   +
            * The logger.
      +  72  
            */
      -  72  1
           private static final Logger LOGGER = LoggerFactory
      -  73  1
                   .getLogger(PythonDistributionAnalyzer.class);
      -  74   -
       
      +  73  1
           private static final Logger LOGGER = LoggerFactory
      +  74  1
                   .getLogger(PythonDistributionAnalyzer.class);
       75   -
           /**
      +
       
       76   -
            * The count of directories created during analysis. This is used for
      +
           /**
       77   -
            * creating temporary directories.
      +
            * The count of directories created during analysis. This is used for
       78   +
            * creating temporary directories.
      +  79  
            */
      -  79  1
           private static int dirCount = 0;
      -  80   -
       
      +  80  1
           private static final AtomicInteger DIR_COUNT = new AtomicInteger(0);
       81   -
           /**
      +
       
       82   -
            * The name of the analyzer.
      +
           /**
       83   -
            */
      +
            * The name of the analyzer.
       84   -
           private static final String ANALYZER_NAME = "Python Distribution Analyzer";
      +
            */
       85   -
           /**
      +
           private static final String ANALYZER_NAME = "Python Distribution Analyzer";
       86   -
            * The phase that this analyzer is intended to run in.
      +
           /**
       87   +
            * The phase that this analyzer is intended to run in.
      +  88  
            */
      -  88  1
           private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
      -  89   -
       
      +  89  1
           private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
       90   -
           /**
      +
       
       91   -
            * The set of file extensions supported by this analyzer.
      +
           /**
       92   +
            * The set of file extensions supported by this analyzer.
      +  93  
            */
      -  93  1
           private static final String[] EXTENSIONS = {"whl", "egg", "zip"};
      -  94   -
       
      +  94  1
           private static final String[] EXTENSIONS = {"whl", "egg", "zip"};
       95   -
           /**
      +
       
       96   -
            * Used to match on egg archive candidate extensions.
      +
           /**
       97   +
            * Used to match on egg archive candidate extensions.
      +  98  
            */
      -  98  1
           private static final FileFilter EGG_OR_ZIP = FileFilterBuilder.newInstance().addExtensions("egg", "zip").build();
      -  99   -
       
      +  99  1
           private static final FileFilter EGG_OR_ZIP = FileFilterBuilder.newInstance().addExtensions("egg", "zip").build();
       100   -
           /**
      +
       
       101   -
            * Used to detect files with a .whl extension.
      +
           /**
       102   +
            * Used to detect files with a .whl extension.
      +  103  
            */
      -  103  1
           private static final FileFilter WHL_FILTER = FileFilterBuilder.newInstance().addExtensions("whl").build();
      -  104   -
       
      +  104  1
           private static final FileFilter WHL_FILTER = FileFilterBuilder.newInstance().addExtensions("whl").build();
       105   -
           /**
      +
       
       106   -
            * The parent directory for the individual directories per archive.
      +
           /**
       107   -
            */
      +
            * The parent directory for the individual directories per archive.
       108   -
           private File tempFileLocation;
      +
            */
       109   -
       
      +
           private File tempFileLocation;
       110   -
           /**
      +
       
       111   -
            * Filter that detects *.dist-info files (but doesn't verify they are
      +
           /**
       112   -
            * directories.
      +
            * Filter that detects *.dist-info files (but doesn't verify they are
       113   +
            * directories.
      +  114  
            */
      -  114  1
           private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter(
      -  115   -
                   ".dist-info");
      +  115  1
           private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter(
       116   -
       
      +
                   ".dist-info");
       117   -
           /**
      +
       
       118   -
            * Filter that detects files named "METADATA".
      +
           /**
       119   -
            */
      -  120  1
           private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter(
      -  121   -
                   "EGG-INFO");
      -  122   -
       
      -  123   -
           /**
      -  124  
            * Filter that detects files named "METADATA".
      +  120   +
            */
      +  121  1
           private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter(
      +  122   +
                   "EGG-INFO");
      +  123   +
       
      +  124   +
           /**
       125   +
            * Filter that detects files named "METADATA".
      +  126  
            */
      -  126  1
           private static final NameFileFilter METADATA_FILTER = new NameFileFilter(
      -  127   -
                   METADATA);
      +  127  1
           private static final NameFileFilter METADATA_FILTER = new NameFileFilter(
       128   -
       
      +
                   METADATA);
       129   -
           /**
      +
       
       130   -
            * Filter that detects files named "PKG-INFO".
      +
           /**
       131   +
            * Filter that detects files named "PKG-INFO".
      +  132  
            */
      -  132  1
           private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter(
      -  133   -
                   PKG_INFO);
      +  133  1
           private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter(
       134   -
       
      +
                   PKG_INFO);
       135   -
           /**
      +
       
       136   -
            * The file filter used to determine which files this analyzer supports.
      +
           /**
       137   +
            * The file filter used to determine which files this analyzer supports.
      +  138  
            */
      -  138  2
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFileFilters(
      -  139  1
                   METADATA_FILTER, PKG_INFO_FILTER).addExtensions(EXTENSIONS).build();
      -  140   -
       
      +  139  2
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFileFilters(
      +  140  1
                   METADATA_FILTER, PKG_INFO_FILTER).addExtensions(EXTENSIONS).build();
       141   -
           /**
      +
       
       142   -
            * Returns the FileFilter
      +
           /**
       143   -
            *
      +
            * Returns the FileFilter
       144   -
            * @return the FileFilter
      +
            *
       145   -
            */
      +
            * @return the FileFilter
       146   -
           @Override
      +
            */
       147   +
           @Override
      +  148  
           protected FileFilter getFileFilter() {
      -  148  864
               return FILTER;
      -  149   -
           }
      +  149  867
               return FILTER;
       150   -
       
      +
           }
       151   -
           /**
      +
       
       152   -
            * Returns the name of the analyzer.
      +
           /**
       153   -
            *
      +
            * Returns the name of the analyzer.
       154   -
            * @return the name of the analyzer.
      +
            *
       155   -
            */
      +
            * @return the name of the analyzer.
       156   -
           @Override
      +
            */
       157   +
           @Override
      +  158  
           public String getName() {
      -  158  15
               return ANALYZER_NAME;
      -  159   -
           }
      +  159  21
               return ANALYZER_NAME;
       160   -
       
      +
           }
       161   -
           /**
      +
       
       162   -
            * Returns the phase that the analyzer is intended to run in.
      +
           /**
       163   -
            *
      +
            * Returns the phase that the analyzer is intended to run in.
       164   -
            * @return the phase that the analyzer is intended to run in.
      +
            *
       165   -
            */
      +
            * @return the phase that the analyzer is intended to run in.
       166   -
           @Override
      +
            */
       167   +
           @Override
      +  168  
           public AnalysisPhase getAnalysisPhase() {
      -  168  4
               return ANALYSIS_PHASE;
      -  169   -
           }
      +  169  6
               return ANALYSIS_PHASE;
       170   -
       
      +
           }
       171   -
           /**
      +
       
       172   -
            * Returns the key used in the properties file to reference the analyzer's
      +
           /**
       173   -
            * enabled property.
      +
            * Returns the key used in the properties file to reference the analyzer's
       174   -
            *
      +
            * enabled property.
       175   -
            * @return the analyzer's enabled property setting key
      +
            *
       176   -
            */
      +
            * @return the analyzer's enabled property setting key
       177   -
           @Override
      +
            */
       178   +
           @Override
      +  179  
           protected String getAnalyzerEnabledSettingKey() {
      -  179  14
               return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED;
      -  180   -
           }
      +  180  16
               return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED;
       181   -
       
      +
           }
       182   -
           @Override
      +
       
       183   -
           protected void analyzeFileType(Dependency dependency, Engine engine)
      +
           @Override
       184   +
           protected void analyzeFileType(Dependency dependency, Engine engine)
      +  185  
                   throws AnalysisException {
      -  185  6
               final File actualFile = dependency.getActualFile();
      -  186  6
               if (WHL_FILTER.accept(actualFile)) {
      -  187  1
                   collectMetadataFromArchiveFormat(dependency, DIST_INFO_FILTER,
      -  188   +  186  6
               final File actualFile = dependency.getActualFile();
      +  187  6
               if (WHL_FILTER.accept(actualFile)) {
      +  188  1
                   collectMetadataFromArchiveFormat(dependency, DIST_INFO_FILTER,
      +  189  
                           METADATA_FILTER);
      -  189  5
               } else if (EGG_OR_ZIP.accept(actualFile)) {
      -  190  2
                   collectMetadataFromArchiveFormat(dependency, EGG_INFO_FILTER,
      -  191   -
                           PKG_INFO_FILTER);
      +  190  5
               } else if (EGG_OR_ZIP.accept(actualFile)) {
      +  191  2
                   collectMetadataFromArchiveFormat(dependency, EGG_INFO_FILTER,
       192   +
                           PKG_INFO_FILTER);
      +  193  
               } else {
      -  193  3
                   final String name = actualFile.getName();
      -  194  3
                   final boolean metadata = METADATA.equals(name);
      -  195  3
                   if (metadata || PKG_INFO.equals(name)) {
      -  196  3
                       final File parent = actualFile.getParentFile();
      -  197  3
                       final String parentName = parent.getName();
      -  198  3
                       dependency.setDisplayFileName(parentName + "/" + name);
      -  199  3
                       if (parent.isDirectory()
      -  200  1
                               && (metadata && parentName.endsWith(".dist-info")
      -  201  2
                               || parentName.endsWith(".egg-info") || "EGG-INFO"
      -  202  1
                               .equals(parentName))) {
      -  203  3
                           collectWheelMetadata(dependency, actualFile);
      -  204   -
                       }
      +  194  3
                   final String name = actualFile.getName();
      +  195  3
                   final boolean metadata = METADATA.equals(name);
      +  196  3
                   if (metadata || PKG_INFO.equals(name)) {
      +  197  3
                       final File parent = actualFile.getParentFile();
      +  198  3
                       final String parentName = parent.getName();
      +  199  3
                       dependency.setDisplayFileName(parentName + "/" + name);
      +  200  3
                       if (parent.isDirectory()
      +  201  1
                               && (metadata && parentName.endsWith(".dist-info")
      +  202  2
                               || parentName.endsWith(".egg-info") || "EGG-INFO"
      +  203  1
                               .equals(parentName))) {
      +  204  3
                           collectWheelMetadata(dependency, actualFile);
       205   -
                   }
      -  206   -
               }
      -  207  6
           }
      -  208   -
       
      -  209   -
           /**
      -  210   -
            * Collects the meta data from an archive.
      -  211   -
            *
      -  212   -
            * @param dependency the archive being scanned
      -  213   -
            * @param folderFilter the filter to apply to the folder
      -  214   -
            * @param metadataFilter the filter to apply to the meta data
      -  215   -
            * @throws AnalysisException thrown when there is a problem analyzing the
      -  216   -
            * dependency
      -  217   -
            */
      -  218   -
           private void collectMetadataFromArchiveFormat(Dependency dependency,
      -  219   -
                   FilenameFilter folderFilter, FilenameFilter metadataFilter)
      -  220   -
                   throws AnalysisException {
      -  221  3
               final File temp = getNextTempDirectory();
      -  222  3
               LOGGER.debug("{} exists? {}", temp, temp.exists());
      -  223   -
               try {
      -  224  6
                   ExtractionUtil.extractFilesUsingFilter(
      -  225  3
                           new File(dependency.getActualFilePath()), temp,
      -  226   -
                           metadataFilter);
      -  227  0
               } catch (ExtractionException ex) {
      -  228  0
                   throw new AnalysisException(ex);
      -  229  3
               }
      -  230   -
       
      -  231  3
               File matchingFile = getMatchingFile(temp, folderFilter);
      -  232  3
               if (matchingFile != null) {
      -  233  3
                   matchingFile = getMatchingFile(matchingFile, metadataFilter);
      -  234  3
                   if (matchingFile != null) {
      -  235  3
                       collectWheelMetadata(dependency, matchingFile);
      -  236   -
                   }
      -  237   -
               }
      -  238  3
           }
      -  239   -
       
      -  240   -
           /**
      -  241   -
            * Makes sure a usable temporary directory is available.
      -  242   -
            *
      -  243   -
            * @throws InitializationException an AnalyzeException is thrown when the
      -  244   -
            * temp directory cannot be created
      -  245   -
            */
      -  246   -
           @Override
      -  247   -
           protected void initializeFileTypeAnalyzer() throws InitializationException {
      -  248   -
               try {
      -  249  8
                   final File baseDir = Settings.getTempDirectory();
      -  250  8
                   tempFileLocation = File.createTempFile("check", "tmp", baseDir);
      -  251  8
                   if (!tempFileLocation.delete()) {
      -  252  0
                       setEnabled(false);
      -  253  0
                       final String msg = String.format(
      -  254   -
                               "Unable to delete temporary file '%s'.",
      -  255  0
                               tempFileLocation.getAbsolutePath());
      -  256  0
                       throw new InitializationException(msg);
      -  257   -
                   }
      -  258  8
                   if (!tempFileLocation.mkdirs()) {
      -  259  0
                       setEnabled(false);
      -  260  0
                       final String msg = String.format(
      -  261   -
                               "Unable to create directory '%s'.",
      -  262  0
                               tempFileLocation.getAbsolutePath());
      -  263  0
                       throw new InitializationException(msg);
      -  264   -
                   }
      -  265  0
               } catch (IOException ex) {
      -  266  0
                   setEnabled(false);
      -  267  0
                   throw new InitializationException("Unable to create a temporary file", ex);
      -  268  8
               }
      -  269  8
           }
      -  270   -
       
      -  271   -
           /**
      -  272   -
            * Deletes any files extracted from the Wheel during analysis.
      -  273   -
            */
      -  274   -
           @Override
      -  275   -
           public void close() {
      -  276  10
               if (tempFileLocation != null && tempFileLocation.exists()) {
      -  277  8
                   LOGGER.debug("Attempting to delete temporary files");
      -  278  8
                   final boolean success = FileUtils.delete(tempFileLocation);
      -  279  8
                   if (!success) {
      -  280  0
                       LOGGER.warn(
      -  281   -
                               "Failed to delete some temporary files, see the log for more details");
      -  282   -
                   }
      -  283   -
               }
      -  284  10
           }
      -  285   -
       
      -  286   -
           /**
      -  287   -
            * Gathers evidence from the METADATA file.
      -  288   -
            *
      -  289   -
            * @param dependency the dependency being analyzed
      -  290   -
            * @param file a reference to the manifest/properties file
      -  291   -
            */
      -  292   -
           private static void collectWheelMetadata(Dependency dependency, File file) {
      -  293  6
               final InternetHeaders headers = getManifestProperties(file);
      -  294  6
               addPropertyToEvidence(headers, dependency.getVersionEvidence(),
      -  295   -
                       "Version", Confidence.HIGHEST);
      -  296  6
               addPropertyToEvidence(headers, dependency.getProductEvidence(), "Name",
      -  297   -
                       Confidence.HIGHEST);
      -  298  6
               final String url = headers.getHeader("Home-page", null);
      -  299  6
               final EvidenceCollection vendorEvidence = dependency
      -  300  6
                       .getVendorEvidence();
      -  301  6
               if (StringUtils.isNotBlank(url)) {
      -  302  6
                   if (UrlStringUtils.isUrl(url)) {
      -  303  6
                       vendorEvidence.addEvidence(METADATA, "vendor", url,
      -  304   -
                               Confidence.MEDIUM);
      -  305   -
                   }
      -  306   -
               }
      -  307  6
               addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW);
      -  308  6
               final String summary = headers.getHeader("Summary", null);
      -  309  6
               if (StringUtils.isNotBlank(summary)) {
      -  310  6
                   JarAnalyzer
      -  311  6
                           .addDescription(dependency, summary, METADATA, "summary");
      -  312   -
               }
      -  313  6
           }
      -  314   -
       
      -  315   -
           /**
      -  316   -
            * Adds a value to the evidence collection.
      -  317   -
            *
      -  318   -
            * @param headers the properties collection
      -  319   -
            * @param evidence the evidence collection to add the value
      -  320   -
            * @param property the property name
      -  321   -
            * @param confidence the confidence of the evidence
      -  322   -
            */
      -  323   -
           private static void addPropertyToEvidence(InternetHeaders headers,
      -  324   -
                   EvidenceCollection evidence, String property, Confidence confidence) {
      -  325  18
               final String value = headers.getHeader(property, null);
      -  326  18
               LOGGER.debug("Property: {}, Value: {}", property, value);
      -  327  18
               if (StringUtils.isNotBlank(value)) {
      -  328  18
                   evidence.addEvidence(METADATA, property, value, confidence);
      -  329   -
               }
      -  330  18
           }
      -  331   -
       
      -  332   -
           /**
      -  333   -
            * Returns a list of files that match the given filter, this does not
      -  334   -
            * recursively scan the directory.
      -  335   -
            *
      -  336   -
            * @param folder the folder to filter
      -  337   -
            * @param filter the filter to apply to the files in the directory
      -  338   -
            * @return the list of Files in the directory that match the provided filter
      -  339   -
            */
      -  340   -
           private static File getMatchingFile(File folder, FilenameFilter filter) {
      -  341  6
               File result = null;
      -  342  6
               final File[] matches = folder.listFiles(filter);
      -  343  6
               if (null != matches && 1 == matches.length) {
      -  344  6
                   result = matches[0];
      -  345   -
               }
      -  346  6
               return result;
      -  347   -
           }
      -  348   -
       
      -  349   -
           /**
      -  350   -
            * Reads the manifest entries from the provided file.
      -  351   -
            *
      -  352   -
            * @param manifest the manifest
      -  353   -
            * @return the manifest entries
      -  354   -
            */
      -  355   -
           private static InternetHeaders getManifestProperties(File manifest) {
      -  356  6
               final InternetHeaders result = new InternetHeaders();
      -  357  6
               if (null == manifest) {
      -  358  0
                   LOGGER.debug("Manifest file not found.");
      -  359   -
               } else {
      -  360  6
                   InputStream in = null;
      -  361   -
                   try {
      -  362  6
                       in = new BufferedInputStream(new FileInputStream(manifest));
      -  363  6
                       result.load(in);
      -  364  0
                   } catch (MessagingException e) {
      -  365  0
                       LOGGER.warn(e.getMessage(), e);
      -  366  0
                   } catch (FileNotFoundException e) {
      -  367  0
                       LOGGER.warn(e.getMessage(), e);
      -  368   -
                   } finally {
      -  369  6
                       if (in != null) {
      -  370   -
                           try {
      -  371  6
                               in.close();
      -  372  0
                           } catch (IOException ex) {
      -  373  0
                               LOGGER.debug("failed to close input stream", ex);
      -  374  6
                           }
      -  375  
                       }
      -  376   +  206  
                   }
      -  377   +  207  
               }
      -  378  6
               return result;
      -  379   -
           }
      -  380   +  208  6
           }
      +  209  
       
      -  381   +  210  
           /**
      -  382   -
            * Retrieves the next temporary destination directory for extracting an
      -  383   -
            * archive.
      -  384   +  211   +
            * Collects the meta data from an archive.
      +  212  
            *
      -  385   -
            * @return a directory
      -  386   -
            * @throws AnalysisException thrown if unable to create temporary directory
      -  387   +  213   +
            * @param dependency the archive being scanned
      +  214   +
            * @param folderFilter the filter to apply to the folder
      +  215   +
            * @param metadataFilter the filter to apply to the meta data
      +  216   +
            * @throws AnalysisException thrown when there is a problem analyzing the
      +  217   +
            * dependency
      +  218  
            */
      -  388   -
           private File getNextTempDirectory() throws AnalysisException {
      -  389   -
               File directory;
      -  390   +  219   +
           private void collectMetadataFromArchiveFormat(Dependency dependency,
      +  220   +
                   FilenameFilter folderFilter, FilenameFilter metadataFilter)
      +  221   +
                   throws AnalysisException {
      +  222  3
               final File temp = getNextTempDirectory();
      +  223  3
               LOGGER.debug("{} exists? {}", temp, temp.exists());
      +  224   +
               try {
      +  225  6
                   ExtractionUtil.extractFilesUsingFilter(
      +  226  3
                           new File(dependency.getActualFilePath()), temp,
      +  227   +
                           metadataFilter);
      +  228  0
               } catch (ExtractionException ex) {
      +  229  0
                   throw new AnalysisException(ex);
      +  230  3
               }
      +  231  
       
      -  391   -
               // getting an exception for some directories not being able to be
      -  392   -
               // created; might be because the directory already exists?
      -  393   -
               do {
      -  394  3
                   dirCount += 1;
      -  395  3
                   directory = new File(tempFileLocation, String.valueOf(dirCount));
      -  396  3
               } while (directory.exists());
      -  397  3
               if (!directory.mkdirs()) {
      -  398  0
                   throw new AnalysisException(String.format(
      -  399   -
                           "Unable to create temp directory '%s'.",
      -  400  0
                           directory.getAbsolutePath()));
      -  401   +  232  3
               File matchingFile = getMatchingFile(temp, folderFilter);
      +  233  3
               if (matchingFile != null) {
      +  234  3
                   matchingFile = getMatchingFile(matchingFile, metadataFilter);
      +  235  3
                   if (matchingFile != null) {
      +  236  3
                       collectWheelMetadata(dependency, matchingFile);
      +  237   +
                   }
      +  238  
               }
      -  402  3
               return directory;
      -  403   +  239  3
           }
      +  240   +
       
      +  241   +
           /**
      +  242   +
            * Makes sure a usable temporary directory is available.
      +  243   +
            *
      +  244   +
            * @throws InitializationException an AnalyzeException is thrown when the
      +  245   +
            * temp directory cannot be created
      +  246   +
            */
      +  247   +
           @Override
      +  248   +
           protected void initializeFileTypeAnalyzer() throws InitializationException {
      +  249   +
               try {
      +  250  8
                   final File baseDir = Settings.getTempDirectory();
      +  251  8
                   tempFileLocation = File.createTempFile("check", "tmp", baseDir);
      +  252  8
                   if (!tempFileLocation.delete()) {
      +  253  0
                       setEnabled(false);
      +  254  0
                       final String msg = String.format(
      +  255   +
                               "Unable to delete temporary file '%s'.",
      +  256  0
                               tempFileLocation.getAbsolutePath());
      +  257  0
                       throw new InitializationException(msg);
      +  258   +
                   }
      +  259  8
                   if (!tempFileLocation.mkdirs()) {
      +  260  0
                       setEnabled(false);
      +  261  0
                       final String msg = String.format(
      +  262   +
                               "Unable to create directory '%s'.",
      +  263  0
                               tempFileLocation.getAbsolutePath());
      +  264  0
                       throw new InitializationException(msg);
      +  265   +
                   }
      +  266  0
               } catch (IOException ex) {
      +  267  0
                   setEnabled(false);
      +  268  0
                   throw new InitializationException("Unable to create a temporary file", ex);
      +  269  8
               }
      +  270  8
           }
      +  271   +
       
      +  272   +
           /**
      +  273   +
            * Deletes any files extracted from the Wheel during analysis.
      +  274   +
            */
      +  275   +
           @Override
      +  276   +
           public void close() {
      +  277  10
               if (tempFileLocation != null && tempFileLocation.exists()) {
      +  278  8
                   LOGGER.debug("Attempting to delete temporary files");
      +  279  8
                   final boolean success = FileUtils.delete(tempFileLocation);
      +  280  8
                   if (!success && tempFileLocation.exists()) {
      +  281  0
                       final String[] l = tempFileLocation.list();
      +  282  0
                       if (l != null && l.length > 0) {
      +  283  0
                           LOGGER.warn("Failed to delete some temporary files, see the log for more details");
      +  284   +
                       }
      +  285   +
                   }
      +  286   +
               }
      +  287  10
           }
      +  288   +
       
      +  289   +
           /**
      +  290   +
            * Gathers evidence from the METADATA file.
      +  291   +
            *
      +  292   +
            * @param dependency the dependency being analyzed
      +  293   +
            * @param file a reference to the manifest/properties file
      +  294   +
            */
      +  295   +
           private static void collectWheelMetadata(Dependency dependency, File file) {
      +  296  6
               final InternetHeaders headers = getManifestProperties(file);
      +  297  6
               addPropertyToEvidence(headers, dependency.getVersionEvidence(),
      +  298   +
                       "Version", Confidence.HIGHEST);
      +  299  6
               addPropertyToEvidence(headers, dependency.getProductEvidence(), "Name",
      +  300   +
                       Confidence.HIGHEST);
      +  301  6
               final String url = headers.getHeader("Home-page", null);
      +  302  6
               final EvidenceCollection vendorEvidence = dependency
      +  303  6
                       .getVendorEvidence();
      +  304  6
               if (StringUtils.isNotBlank(url)) {
      +  305  6
                   if (UrlStringUtils.isUrl(url)) {
      +  306  6
                       vendorEvidence.addEvidence(METADATA, "vendor", url,
      +  307   +
                               Confidence.MEDIUM);
      +  308   +
                   }
      +  309   +
               }
      +  310  6
               addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW);
      +  311  6
               final String summary = headers.getHeader("Summary", null);
      +  312  6
               if (StringUtils.isNotBlank(summary)) {
      +  313  6
                   JarAnalyzer
      +  314  6
                           .addDescription(dependency, summary, METADATA, "summary");
      +  315   +
               }
      +  316  6
           }
      +  317   +
       
      +  318   +
           /**
      +  319   +
            * Adds a value to the evidence collection.
      +  320   +
            *
      +  321   +
            * @param headers the properties collection
      +  322   +
            * @param evidence the evidence collection to add the value
      +  323   +
            * @param property the property name
      +  324   +
            * @param confidence the confidence of the evidence
      +  325   +
            */
      +  326   +
           private static void addPropertyToEvidence(InternetHeaders headers,
      +  327   +
                   EvidenceCollection evidence, String property, Confidence confidence) {
      +  328  18
               final String value = headers.getHeader(property, null);
      +  329  18
               LOGGER.debug("Property: {}, Value: {}", property, value);
      +  330  18
               if (StringUtils.isNotBlank(value)) {
      +  331  18
                   evidence.addEvidence(METADATA, property, value, confidence);
      +  332   +
               }
      +  333  18
           }
      +  334   +
       
      +  335   +
           /**
      +  336   +
            * Returns a list of files that match the given filter, this does not
      +  337   +
            * recursively scan the directory.
      +  338   +
            *
      +  339   +
            * @param folder the folder to filter
      +  340   +
            * @param filter the filter to apply to the files in the directory
      +  341   +
            * @return the list of Files in the directory that match the provided filter
      +  342   +
            */
      +  343   +
           private static File getMatchingFile(File folder, FilenameFilter filter) {
      +  344  6
               File result = null;
      +  345  6
               final File[] matches = folder.listFiles(filter);
      +  346  6
               if (null != matches && 1 == matches.length) {
      +  347  6
                   result = matches[0];
      +  348   +
               }
      +  349  6
               return result;
      +  350  
           }
      +  351   +
       
      +  352   +
           /**
      +  353   +
            * Reads the manifest entries from the provided file.
      +  354   +
            *
      +  355   +
            * @param manifest the manifest
      +  356   +
            * @return the manifest entries
      +  357   +
            */
      +  358   +
           private static InternetHeaders getManifestProperties(File manifest) {
      +  359  6
               final InternetHeaders result = new InternetHeaders();
      +  360  6
               if (null == manifest) {
      +  361  0
                   LOGGER.debug("Manifest file not found.");
      +  362   +
               } else {
      +  363  6
                   InputStream in = null;
      +  364   +
                   try {
      +  365  6
                       in = new BufferedInputStream(new FileInputStream(manifest));
      +  366  6
                       result.load(in);
      +  367  0
                   } catch (MessagingException e) {
      +  368  0
                       LOGGER.warn(e.getMessage(), e);
      +  369  0
                   } catch (FileNotFoundException e) {
      +  370  0
                       LOGGER.warn(e.getMessage(), e);
      +  371   +
                   } finally {
      +  372  6
                       if (in != null) {
      +  373   +
                           try {
      +  374  6
                               in.close();
      +  375  0
                           } catch (IOException ex) {
      +  376  0
                               LOGGER.debug("failed to close input stream", ex);
      +  377  6
                           }
      +  378   +
                       }
      +  379   +
                   }
      +  380   +
               }
      +  381  6
               return result;
      +  382   +
           }
      +  383   +
       
      +  384   +
           /**
      +  385   +
            * Retrieves the next temporary destination directory for extracting an
      +  386   +
            * archive.
      +  387   +
            *
      +  388   +
            * @return a directory
      +  389   +
            * @throws AnalysisException thrown if unable to create temporary directory
      +  390   +
            */
      +  391   +
           private File getNextTempDirectory() throws AnalysisException {
      +  392   +
               File directory;
      +  393   +
       
      +  394   +
               // getting an exception for some directories not being able to be
      +  395   +
               // created; might be because the directory already exists?
      +  396   +
               do {
      +  397  3
                   final int dirCount = DIR_COUNT.incrementAndGet();
      +  398  3
                   directory = new File(tempFileLocation, String.valueOf(dirCount));
      +  399  3
               } while (directory.exists());
      +  400  3
               if (!directory.mkdirs()) {
      +  401  0
                   throw new AnalysisException(String.format(
      +  402   +
                           "Unable to create temp directory '%s'.",
      +  403  0
                           directory.getAbsolutePath()));
       404   +
               }
      +  405  3
               return directory;
      +  406   +
           }
      +  407  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonPackageAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonPackageAnalyzer.html index d2619abc2..6a88689c2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonPackageAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.PythonPackageAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      PythonPackageAnalyzer
      91%
      66/72
      77%
      14/18
      2
      PythonPackageAnalyzer
      95%
      66/69
      77%
      14/18
      2
       
      @@ -88,513 +88,504 @@  35  
       import java.nio.charset.Charset;
       36   -
       import java.util.ArrayList;
      -  37   -
       import java.util.List;
      -  38  
       import java.util.regex.Matcher;
      -  39   +  37  
       import java.util.regex.Pattern;
      -  40   +  38  
       import org.owasp.dependencycheck.exception.InitializationException;
      -  41   +  39  
       
      -  42   +  40  
       /**
      -  43   +  41  
        * Used to analyze a Python package, and collect information that can be used to
      -  44   +  42  
        * determine the associated CPE.
      -  45   +  43  
        *
      -  46   +  44  
        * @author Dale Visser
      -  47   +  45  
        */
      -  48   +  46  
       @Experimental
      -  49  9
       public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
      +  47  11
       public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
      +  48   +
       
      +  49   +
           /**
       50   -
       
      -  51   -
           /**
      -  52  
            * Used when compiling file scanning regex patterns.
      -  53   +  51  
            */
      -  54   +  52  
           private static final int REGEX_OPTIONS = Pattern.DOTALL
      -  55   +  53  
                   | Pattern.CASE_INSENSITIVE;
      +  54   +
       
      +  55   +
           /**
       56   -
       
      -  57   -
           /**
      -  58  
            * Filename extensions for files to be analyzed.
      -  59   +  57  
            */
      -  60   +  58  
           private static final String EXTENSIONS = "py";
      +  59   +
       
      +  60   +
           /**
       61   -
       
      -  62   -
           /**
      -  63  
            * Pattern for matching the module docstring in a source file.
      +  62   +
            */
      +  63  1
           private static final Pattern MODULE_DOCSTRING = Pattern.compile(
       64   -
            */
      -  65  1
           private static final Pattern MODULE_DOCSTRING = Pattern.compile(
      -  66  
                   "^(['\\\"]{3})(.*?)\\1", REGEX_OPTIONS);
      +  65   +
       
      +  66   +
           /**
       67   -
       
      -  68   -
           /**
      -  69  
            * Matches assignments to version variables in Python source code.
      +  68   +
            */
      +  69  1
           private static final Pattern VERSION_PATTERN = Pattern.compile(
       70   -
            */
      -  71  1
           private static final Pattern VERSION_PATTERN = Pattern.compile(
      -  72  
                   "\\b(__)?version(__)? *= *(['\"]+)(\\d+\\.\\d+.*?)\\3",
      -  73   +  71  
                   REGEX_OPTIONS);
      +  72   +
       
      +  73   +
           /**
       74   -
       
      -  75   -
           /**
      -  76  
            * Matches assignments to title variables in Python source code.
      +  75   +
            */
      +  76  1
           private static final Pattern TITLE_PATTERN = compileAssignPattern("title");
       77   -
            */
      -  78  1
           private static final Pattern TITLE_PATTERN = compileAssignPattern("title");
      +
       
      +  78   +
           /**
       79   -
       
      -  80   -
           /**
      -  81  
            * Matches assignments to summary variables in Python source code.
      +  80   +
            */
      +  81  1
           private static final Pattern SUMMARY_PATTERN = compileAssignPattern("summary");
       82   -
            */
      -  83  1
           private static final Pattern SUMMARY_PATTERN = compileAssignPattern("summary");
      +
       
      +  83   +
           /**
       84   -
       
      -  85   -
           /**
      -  86  
            * Matches assignments to URL/URL variables in Python source code.
      +  85   +
            */
      +  86  1
           private static final Pattern URI_PATTERN = compileAssignPattern("ur[il]");
       87   -
            */
      -  88  1
           private static final Pattern URI_PATTERN = compileAssignPattern("ur[il]");
      +
       
      +  88   +
           /**
       89   -
       
      -  90   -
           /**
      -  91  
            * Matches assignments to home page variables in Python source code.
      +  90   +
            */
      +  91  1
           private static final Pattern HOMEPAGE_PATTERN = compileAssignPattern("home_?page");
       92   -
            */
      -  93  1
           private static final Pattern HOMEPAGE_PATTERN = compileAssignPattern("home_?page");
      +
       
      +  93   +
           /**
       94   -
       
      -  95   -
           /**
      -  96  
            * Matches assignments to author variables in Python source code.
      +  95   +
            */
      +  96  1
           private static final Pattern AUTHOR_PATTERN = compileAssignPattern("author");
       97   -
            */
      -  98  1
           private static final Pattern AUTHOR_PATTERN = compileAssignPattern("author");
      +
       
      +  98   +
           /**
       99   -
       
      -  100   -
           /**
      -  101  
            * Filter that detects files named "__init__.py".
      +  100   +
            */
      +  101  1
           private static final FileFilter INIT_PY_FILTER = new NameFileFilter("__init__.py");
       102   -
            */
      -  103  1
           private static final FileFilter INIT_PY_FILTER = new NameFileFilter("__init__.py");
      +
       
      +  103   +
           /**
       104   -
       
      -  105   -
           /**
      -  106  
            * The file filter for python files.
      +  105   +
            */
      +  106  1
           private static final FileFilter PY_FILTER = new SuffixFileFilter(".py");
       107   -
            */
      -  108  1
           private static final FileFilter PY_FILTER = new SuffixFileFilter(".py");
      +
       
      +  108   +
           /**
       109   -
       
      -  110   -
           /**
      -  111  
            * Returns the name of the Python Package Analyzer.
      -  112   +  110  
            *
      -  113   +  111  
            * @return the name of the analyzer
      +  112   +
            */
      +  113   +
           @Override
       114   -
            */
      -  115   -
           @Override
      -  116  
           public String getName() {
      -  117  15
               return "Python Package Analyzer";
      +  115  21
               return "Python Package Analyzer";
      +  116   +
           }
      +  117   +
       
       118   -
           }
      +
           /**
       119   -
       
      -  120   -
           /**
      -  121  
            * Tell that we are used for information collection.
      -  122   +  120  
            *
      -  123   +  121  
            * @return INFORMATION_COLLECTION
      +  122   +
            */
      +  123   +
           @Override
       124   -
            */
      -  125   -
           @Override
      -  126  
           public AnalysisPhase getAnalysisPhase() {
      -  127  4
               return AnalysisPhase.INFORMATION_COLLECTION;
      +  125  6
               return AnalysisPhase.INFORMATION_COLLECTION;
      +  126   +
           }
      +  127   +
       
       128   -
           }
      +
           /**
       129   -
       
      -  130   -
           /**
      -  131  
            * The file filter used to determine which files this analyzer supports.
      +  130   +
            */
      +  131  1
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build();
       132   -
            */
      -  133  1
           private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build();
      +
       
      +  133   +
           /**
       134   -
       
      -  135   -
           /**
      -  136  
            * Returns the FileFilter
      -  137   +  135  
            *
      -  138   +  136  
            * @return the FileFilter
      +  137   +
            */
      +  138   +
           @Override
       139   -
            */
      -  140   -
           @Override
      -  141  
           protected FileFilter getFileFilter() {
      -  142  860
               return FILTER;
      -  143   +  140  863
               return FILTER;
      +  141  
           }
      +  142   +
       
      +  143   +
           /**
       144   -
       
      -  145   -
           /**
      -  146  
            * No-op initializer implementation.
      -  147   +  145  
            *
      -  148   +  146  
            * @throws InitializationException never thrown
      -  149   +  147  
            */
      -  150   +  148  
           @Override
      -  151   +  149  
           protected void initializeFileTypeAnalyzer() throws InitializationException {
      -  152   +  150  
               // Nothing to do here.
      -  153  3
           }
      -  154   +  151  3
           }
      +  152  
       
      -  155   +  153  
           /**
      -  156   +  154  
            * Utility function to create a regex pattern matcher.
      -  157   +  155  
            *
      -  158   +  156  
            * @param name the value to use when constructing the assignment pattern
      -  159   +  157  
            * @return the compiled Pattern
      -  160   +  158  
            */
      -  161   +  159  
           private static Pattern compileAssignPattern(String name) {
      -  162  10
               return Pattern.compile(
      -  163  5
                       String.format("\\b(__)?%s(__)?\\b *= *(['\"]+)(.*?)\\3", name),
      -  164   +  160  10
               return Pattern.compile(
      +  161  5
                       String.format("\\b(__)?%s(__)?\\b *= *(['\"]+)(.*?)\\3", name),
      +  162  
                       REGEX_OPTIONS);
      +  163   +
           }
      +  164   +
       
       165   -
           }
      +
           /**
       166   -
       
      -  167   -
           /**
      -  168  
            * Analyzes python packages and adds evidence to the dependency.
      +  167   +
            *
      +  168   +
            * @param dependency the dependency being analyzed
       169   -
            *
      -  170   -
            * @param dependency the dependency being analyzed
      -  171  
            * @param engine the engine being used to perform the scan
      -  172   +  170  
            * @throws AnalysisException thrown if there is an unrecoverable error
      -  173   +  171  
            * analyzing the dependency
      +  172   +
            */
      +  173   +
           @Override
       174   -
            */
      -  175   -
           @Override
      -  176  
           protected void analyzeFileType(Dependency dependency, Engine engine)
      -  177   +  175  
                   throws AnalysisException {
      -  178  1
               final File file = dependency.getActualFile();
      -  179  1
               final File parent = file.getParentFile();
      -  180  1
               final String parentName = parent.getName();
      -  181  1
               if (INIT_PY_FILTER.accept(file)) {
      -  182   +  176  1
               final File file = dependency.getActualFile();
      +  177  1
               final File parent = file.getParentFile();
      +  178  1
               final String parentName = parent.getName();
      +  179  1
               if (INIT_PY_FILTER.accept(file)) {
      +  180  
                   //by definition, the containing folder of __init__.py is considered the package, even the file is empty:
      -  183   +  181  
                   //"The __init__.py files are required to make Python treat the directories as containing packages"
      -  184   +  182  
                   //see section "6.4 Packages" from https://docs.python.org/2/tutorial/modules.html;
      -  185  1
                   dependency.setDisplayFileName(parentName + "/__init__.py");
      -  186  1
                   dependency.getProductEvidence().addEvidence(file.getName(),
      -  187   +  183  1
                   dependency.setDisplayFileName(parentName + "/__init__.py");
      +  184  1
                   dependency.getProductEvidence().addEvidence(file.getName(),
      +  185  
                           "PackageName", parentName, Confidence.HIGHEST);
      -  188   +  186  
       
      -  189  1
                   final File[] fileList = parent.listFiles(PY_FILTER);
      -  190  1
                   if (fileList != null) {
      -  191  4
                       for (final File sourceFile : fileList) {
      -  192  3
                           analyzeFileContents(dependency, sourceFile);
      -  193   +  187  1
                   final File[] fileList = parent.listFiles(PY_FILTER);
      +  188  1
                   if (fileList != null) {
      +  189  4
                       for (final File sourceFile : fileList) {
      +  190  3
                           analyzeFileContents(dependency, sourceFile);
      +  191  
                       }
      -  194   +  192  
                   }
      -  195  1
               } else {
      -  196   -
                   // copy, alter and set in case some other thread is iterating over
      -  197  0
                   final List<Dependency> dependencies = new ArrayList<Dependency>(
      -  198  0
                           engine.getDependencies());
      -  199  0
                   dependencies.remove(dependency);
      -  200  0
                   engine.setDependencies(dependencies);
      -  201   +  193  1
               } else {
      +  194  0
                   engine.getDependencies().remove(dependency);
      +  195  
               }
      -  202  1
           }
      -  203   +  196  1
           }
      +  197  
       
      -  204   +  198  
           /**
      -  205   +  199  
            * This should gather information from leading docstrings, file comments,
      -  206   +  200  
            * and assignments to __version__, __title__, __summary__, __uri__, __url__,
      -  207   +  201  
            * __home*page__, __author__, and their all caps equivalents.
      -  208   +  202  
            *
      -  209   +  203  
            * @param dependency the dependency being analyzed
      -  210   +  204  
            * @param file the file name to analyze
      -  211   +  205  
            * @return whether evidence was found
      -  212   +  206  
            * @throws AnalysisException thrown if there is an unrecoverable error
      -  213   +  207  
            */
      -  214   +  208  
           private boolean analyzeFileContents(Dependency dependency, File file)
      -  215   +  209  
                   throws AnalysisException {
      -  216   +  210  
               String contents;
      -  217   +  211  
               try {
      -  218  3
                   contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
      -  219  0
               } catch (IOException e) {
      -  220  0
                   throw new AnalysisException(
      -  221   +  212  3
                   contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
      +  213  0
               } catch (IOException e) {
      +  214  0
                   throw new AnalysisException(
      +  215  
                           "Problem occurred while reading dependency file.", e);
      -  222  3
               }
      -  223  3
               boolean found = false;
      -  224  3
               if (!contents.isEmpty()) {
      -  225  3
                   final String source = file.getName();
      -  226  6
                   found = gatherEvidence(VERSION_PATTERN, contents, source,
      -  227  3
                           dependency.getVersionEvidence(), "SourceVersion",
      -  228   +  216  3
               }
      +  217  3
               boolean found = false;
      +  218  3
               if (!contents.isEmpty()) {
      +  219  3
                   final String source = file.getName();
      +  220  6
                   found = gatherEvidence(VERSION_PATTERN, contents, source,
      +  221  3
                           dependency.getVersionEvidence(), "SourceVersion",
      +  222  
                           Confidence.MEDIUM);
      -  229  3
                   found |= addSummaryInfo(dependency, SUMMARY_PATTERN, 4, contents,
      -  230   +  223  3
                   found |= addSummaryInfo(dependency, SUMMARY_PATTERN, 4, contents,
      +  224  
                           source, "summary");
      -  231  3
                   if (INIT_PY_FILTER.accept(file)) {
      -  232  1
                       found |= addSummaryInfo(dependency, MODULE_DOCSTRING, 2,
      -  233   +  225  3
                   if (INIT_PY_FILTER.accept(file)) {
      +  226  1
                       found |= addSummaryInfo(dependency, MODULE_DOCSTRING, 2,
      +  227  
                               contents, source, "docstring");
      -  234   +  228  
                   }
      -  235  6
                   found |= gatherEvidence(TITLE_PATTERN, contents, source,
      -  236  3
                           dependency.getProductEvidence(), "SourceTitle",
      -  237   +  229  6
                   found |= gatherEvidence(TITLE_PATTERN, contents, source,
      +  230  3
                           dependency.getProductEvidence(), "SourceTitle",
      +  231  
                           Confidence.LOW);
      -  238  3
                   final EvidenceCollection vendorEvidence = dependency
      -  239  3
                           .getVendorEvidence();
      -  240  3
                   found |= gatherEvidence(AUTHOR_PATTERN, contents, source,
      -  241   +  232  3
                   final EvidenceCollection vendorEvidence = dependency
      +  233  3
                           .getVendorEvidence();
      +  234  3
                   found |= gatherEvidence(AUTHOR_PATTERN, contents, source,
      +  235  
                           vendorEvidence, "SourceAuthor", Confidence.MEDIUM);
      -  242  3
                   found |= gatherHomePageEvidence(URI_PATTERN, vendorEvidence,
      -  243   +  236  3
                   found |= gatherHomePageEvidence(URI_PATTERN, vendorEvidence,
      +  237  
                           source, "URL", contents);
      -  244  3
                   found |= gatherHomePageEvidence(HOMEPAGE_PATTERN,
      -  245   +  238  3
                   found |= gatherHomePageEvidence(HOMEPAGE_PATTERN,
      +  239  
                           vendorEvidence, source, "HomePage", contents);
      -  246   +  240  
               }
      -  247  3
               return found;
      -  248   +  241  3
               return found;
      +  242  
           }
      -  249   +  243  
       
      -  250   +  244  
           /**
      -  251   +  245  
            * Adds summary information to the dependency
      -  252   +  246  
            *
      -  253   +  247  
            * @param dependency the dependency being analyzed
      -  254   +  248  
            * @param pattern the pattern used to perform analysis
      -  255   +  249  
            * @param group the group from the pattern that indicates the data to use
      -  256   +  250  
            * @param contents the data being analyzed
      -  257   +  251  
            * @param source the source name to use when recording the evidence
      -  258   +  252  
            * @param key the key name to use when recording the evidence
      -  259   +  253  
            * @return true if evidence was collected; otherwise false
      -  260   +  254  
            */
      -  261   +  255  
           private boolean addSummaryInfo(Dependency dependency, Pattern pattern,
      -  262   +  256  
                   int group, String contents, String source, String key) {
      -  263  4
               final Matcher matcher = pattern.matcher(contents);
      -  264  4
               final boolean found = matcher.find();
      -  265  4
               if (found) {
      -  266  1
                   JarAnalyzer.addDescription(dependency, matcher.group(group),
      -  267   +  257  4
               final Matcher matcher = pattern.matcher(contents);
      +  258  4
               final boolean found = matcher.find();
      +  259  4
               if (found) {
      +  260  1
                   JarAnalyzer.addDescription(dependency, matcher.group(group),
      +  261  
                           source, key);
      -  268   +  262  
               }
      -  269  4
               return found;
      -  270   +  263  4
               return found;
      +  264  
           }
      -  271   +  265  
       
      -  272   +  266  
           /**
      -  273   +  267  
            * Collects evidence from the home page URL.
      -  274   +  268  
            *
      -  275   +  269  
            * @param pattern the pattern to match
      -  276   +  270  
            * @param evidence the evidence collection to add the evidence to
      -  277   +  271  
            * @param source the source of the evidence
      -  278   +  272  
            * @param name the name of the evidence
      -  279   +  273  
            * @param contents the home page URL
      -  280   +  274  
            * @return true if evidence was collected; otherwise false
      -  281   +  275  
            */
      -  282   +  276  
           private boolean gatherHomePageEvidence(Pattern pattern,
      -  283   +  277  
                   EvidenceCollection evidence, String source, String name,
      -  284   +  278  
                   String contents) {
      -  285  6
               final Matcher matcher = pattern.matcher(contents);
      -  286  6
               boolean found = false;
      -  287  6
               if (matcher.find()) {
      -  288  1
                   final String url = matcher.group(4);
      -  289  1
                   if (UrlStringUtils.isUrl(url)) {
      -  290  1
                       found = true;
      -  291  1
                       evidence.addEvidence(source, name, url, Confidence.MEDIUM);
      -  292   +  279  6
               final Matcher matcher = pattern.matcher(contents);
      +  280  6
               boolean found = false;
      +  281  6
               if (matcher.find()) {
      +  282  1
                   final String url = matcher.group(4);
      +  283  1
                   if (UrlStringUtils.isUrl(url)) {
      +  284  1
                       found = true;
      +  285  1
                       evidence.addEvidence(source, name, url, Confidence.MEDIUM);
      +  286  
                   }
      -  293   +  287  
               }
      -  294  6
               return found;
      -  295   +  288  6
               return found;
      +  289  
           }
      -  296   +  290  
       
      -  297   +  291  
           /**
      -  298   +  292  
            * Gather evidence from a Python source file using the given string
      -  299   +  293  
            * assignment regex pattern.
      -  300   +  294  
            *
      -  301   +  295  
            * @param pattern to scan contents with
      -  302   +  296  
            * @param contents of Python source file
      -  303   +  297  
            * @param source for storing evidence
      -  304   +  298  
            * @param evidence to store evidence in
      -  305   +  299  
            * @param name of evidence
      -  306   +  300  
            * @param confidence in evidence
      -  307   +  301  
            * @return whether evidence was found
      -  308   +  302  
            */
      -  309   +  303  
           private boolean gatherEvidence(Pattern pattern, String contents,
      -  310   +  304  
                   String source, EvidenceCollection evidence, String name,
      -  311   +  305  
                   Confidence confidence) {
      -  312  9
               final Matcher matcher = pattern.matcher(contents);
      -  313  9
               final boolean found = matcher.find();
      -  314  9
               if (found) {
      -  315  3
                   evidence.addEvidence(source, name, matcher.group(4), confidence);
      -  316   +  306  9
               final Matcher matcher = pattern.matcher(contents);
      +  307  9
               final boolean found = matcher.find();
      +  308  9
               if (found) {
      +  309  3
                   evidence.addEvidence(source, name, matcher.group(4), confidence);
      +  310  
               }
      -  317  9
               return found;
      -  318   +  311  9
               return found;
      +  312  
           }
      -  319   +  313  
       
      -  320   +  314  
           @Override
      -  321   +  315  
           protected String getAnalyzerEnabledSettingKey() {
      -  322  9
               return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED;
      -  323   +  316  11
               return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED;
      +  317  
           }
      -  324   +  318  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer.html index e07591f28..68c4c05a0 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      RubyBundleAuditAnalyzer
      14%
      32/221
      2%
      2/78
      6.154
      RubyBundleAuditAnalyzer
      14%
      32/221
      2%
      2/80
      6.231
       
      @@ -123,7 +123,7 @@
        */
       53  
       @Experimental
      -  54  12
       public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
      +  54  14
       public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
       55  
       
       56   @@ -213,7 +213,7 @@
           @Override
       100  
           protected FileFilter getFileFilter() {
      -  101  858
               return FILTER;
      +  101  861
               return FILTER;
       102  
           }
       103   @@ -386,7 +386,7 @@
           @Override
       221  
           public String getName() {
      -  222  15
               return ANALYZER_NAME;
      +  222  19
               return ANALYZER_NAME;
       223  
           }
       224   @@ -405,7 +405,7 @@
           @Override
       231  
           public AnalysisPhase getAnalysisPhase() {
      -  232  4
               return ANALYSIS_PHASE;
      +  232  6
               return ANALYSIS_PHASE;
       233  
           }
       234   @@ -426,7 +426,7 @@
           @Override
       242  
           protected String getAnalyzerEnabledSettingKey() {
      -  243  12
               return Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED;
      +  243  14
               return Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED;
       244  
           }
       245   @@ -441,7 +441,7 @@
            * {@link RubyGemspecAnalyzer}.
       250  
            */
      -  251  12
           private boolean needToDisableGemspecAnalyzer = true;
      +  251  14
           private boolean needToDisableGemspecAnalyzer = true;
       252  
       
       253   @@ -495,7 +495,7 @@  286  0
               } catch (InterruptedException ie) {
       287  0
                   throw new AnalysisException("bundle-audit process interrupted", ie);
       288  0
               }
      -  289  0
               if (exitValue != 0) {
      +  289  0
               if (exitValue < 0 || exitValue > 1) {
       290  0
                   final String msg = String.format("Unexpected exit code from bundle-audit process; exit code: %s", exitValue);
       291  0
                   throw new AnalysisException(msg);
       292   @@ -808,6 +808,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer.html index 16abdfcd7..70f462ea4 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer.html @@ -114,7 +114,7 @@
        */
       48  
       @Experimental
      -  49  9
       public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
      +  49  11
       public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
       50  
       
       51   @@ -161,7 +161,7 @@
           @Override
       72  
           public String getName() {
      -  73  15
               return ANALYZER_NAME;
      +  73  22
               return ANALYZER_NAME;
       74  
           }
       75   @@ -186,15 +186,15 @@
           public boolean accept(File pathname) {
       85  
       
      -  86  861
               boolean accepted = super.accept(pathname);
      -  87  861
               if (accepted) {
      +  86  864
               boolean accepted = super.accept(pathname);
      +  87  864
               if (accepted) {
       88  4
                   final File parentDir = pathname.getParentFile();
       89  4
                   accepted = parentDir != null && parentDir.getName().equals(SPECIFICATIONS);
       90  
               }
       91  
       
      -  92  861
               return accepted;
      +  92  864
               return accepted;
       93  
           }
       94   @@ -269,6 +269,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer.html index 13fbc9c16..7085cb2c7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer.html @@ -114,7 +114,7 @@
        */
       48  
       @Experimental
      -  49  18
       public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
      +  49  22
       public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
       50  
       
       51   @@ -188,7 +188,7 @@
           @Override
       87  
           protected FileFilter getFileFilter() {
      -  88  1721
               return FILTER;
      +  88  1727
               return FILTER;
       89  
           }
       90   @@ -216,7 +216,7 @@
           @Override
       102  
           public String getName() {
      -  103  15
               return ANALYZER_NAME;
      +  103  22
               return ANALYZER_NAME;
       104  
           }
       105   @@ -235,7 +235,7 @@
           @Override
       112  
           public AnalysisPhase getAnalysisPhase() {
      -  113  8
               return ANALYSIS_PHASE;
      +  113  12
               return ANALYSIS_PHASE;
       114  
           }
       115   @@ -256,7 +256,7 @@
           @Override
       123  
           protected String getAnalyzerEnabledSettingKey() {
      -  124  18
               return Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED;
      +  124  22
               return Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED;
       125  
           }
       126   @@ -451,6 +451,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer.html index 2ac91fe9a..5d52397ac 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.SwiftPackageManagerAnalyzer.html @@ -103,7 +103,7 @@
        */
       43  
       @Experimental
      -  44  12
       public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
      +  44  14
       public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
       45  
       
       46   @@ -169,7 +169,7 @@
           @Override
       78  
           protected FileFilter getFileFilter() {
      -  79  860
               return SPM_FILE_FILTER;
      +  79  862
               return SPM_FILE_FILTER;
       80  
           }
       81   @@ -197,7 +197,7 @@
           @Override
       93  
           public String getName() {
      -  94  15
               return ANALYZER_NAME;
      +  94  21
               return ANALYZER_NAME;
       95  
           }
       96   @@ -216,7 +216,7 @@
           @Override
       103  
           public AnalysisPhase getAnalysisPhase() {
      -  104  4
               return ANALYSIS_PHASE;
      +  104  6
               return ANALYSIS_PHASE;
       105  
           }
       106   @@ -237,7 +237,7 @@
           @Override
       114  
           protected String getAnalyzerEnabledSettingKey() {
      -  115  12
               return Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED;
      +  115  14
               return Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED;
       116  
           }
       117   @@ -363,6 +363,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer.html index 9fd8fdd81..2d8b742bd 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer.html @@ -77,7 +77,7 @@
        * @author Jeremy Long
       30  
        */
      -  31  6
       public class VulnerabilitySuppressionAnalyzer extends AbstractSuppressionAnalyzer {
      +  31  8
       public class VulnerabilitySuppressionAnalyzer extends AbstractSuppressionAnalyzer {
       32  
       
       33   @@ -113,7 +113,7 @@
           @Override
       49  
           public String getName() {
      -  50  16
               return ANALYZER_NAME;
      +  50  26
               return ANALYZER_NAME;
       51  
           }
       52   @@ -132,7 +132,7 @@
           @Override
       59  
           public AnalysisPhase getAnalysisPhase() {
      -  60  4
               return ANALYSIS_PHASE;
      +  60  6
               return ANALYSIS_PHASE;
       61  
           }
       62   @@ -152,13 +152,13 @@  70  
       
       71  4
               for (final SuppressionRule rule : getRules()) {
      -  72  228
                   rule.process(dependency);
      -  73  228
               }
      +  72  240
                   rule.process(dependency);
      +  73  240
               }
       74  4
           }
       75  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.exception.AnalysisException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.exception.AnalysisException.html index ee241d6f1..4668d32ab 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.exception.AnalysisException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.exception.AnalysisException.html @@ -143,6 +143,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException.html index 0dbd92e12..2790ca61a 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException.html @@ -143,6 +143,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.central.CentralSearch.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.central.CentralSearch.html index c30a9b6d9..b989cafbc 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.central.CentralSearch.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.central.CentralSearch.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      CentralSearch
      86%
      53/61
      87%
      21/24
      9.5
      CentralSearch
      87%
      55/63
      87%
      21/24
      9.5
       
      @@ -124,7 +124,7 @@  53  
            */
       54   -
           private boolean useProxy;
      +
           private final boolean useProxy;
       55  
       
       56   @@ -221,79 +221,79 @@  111  3
                   boolean missing = false;
       112  
                   try {
      -  113   -
                       final DocumentBuilder builder = DocumentBuilderFactory
      -  114  3
                               .newInstance().newDocumentBuilder();
      -  115  3
                       final Document doc = builder.parse(conn.getInputStream());
      -  116  3
                       final XPath xpath = XPathFactory.newInstance().newXPath();
      -  117  3
                       final String numFound = xpath.evaluate("/response/result/@numFound", doc);
      -  118  3
                       if ("0".equals(numFound)) {
      -  119  1
                           missing = true;
      -  120   +  113  3
                       final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      +  114  3
                       factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +  115  3
                       final DocumentBuilder builder = factory.newDocumentBuilder();
      +  116  3
                       final Document doc = builder.parse(conn.getInputStream());
      +  117  3
                       final XPath xpath = XPathFactory.newInstance().newXPath();
      +  118  3
                       final String numFound = xpath.evaluate("/response/result/@numFound", doc);
      +  119  3
                       if ("0".equals(numFound)) {
      +  120  1
                           missing = true;
      +  121  
                       } else {
      -  121  2
                           result = new ArrayList<MavenArtifact>();
      -  122  2
                           final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
      -  123  5
                           for (int i = 0; i < docs.getLength(); i++) {
      -  124  3
                               final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
      -  125  3
                               LOGGER.trace("GroupId: {}", g);
      -  126  3
                               final String a = xpath.evaluate("./str[@name='a']", docs.item(i));
      -  127  3
                               LOGGER.trace("ArtifactId: {}", a);
      -  128  3
                               final String v = xpath.evaluate("./str[@name='v']", docs.item(i));
      -  129  3
                               NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET);
      -  130  3
                               boolean pomAvailable = false;
      -  131  3
                               boolean jarAvailable = false;
      -  132  14
                               for (int x = 0; x < atts.getLength(); x++) {
      -  133  11
                                   final String tmp = xpath.evaluate(".", atts.item(x));
      -  134  11
                                   if (".pom".equals(tmp)) {
      -  135  3
                                       pomAvailable = true;
      -  136  8
                                   } else if (".jar".equals(tmp)) {
      -  137  3
                                       jarAvailable = true;
      -  138   -
                                   }
      +  122  2
                           result = new ArrayList<MavenArtifact>();
      +  123  2
                           final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
      +  124  5
                           for (int i = 0; i < docs.getLength(); i++) {
      +  125  3
                               final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
      +  126  3
                               LOGGER.trace("GroupId: {}", g);
      +  127  3
                               final String a = xpath.evaluate("./str[@name='a']", docs.item(i));
      +  128  3
                               LOGGER.trace("ArtifactId: {}", a);
      +  129  3
                               final String v = xpath.evaluate("./str[@name='v']", docs.item(i));
      +  130  3
                               NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET);
      +  131  3
                               boolean pomAvailable = false;
      +  132  3
                               boolean jarAvailable = false;
      +  133  14
                               for (int x = 0; x < atts.getLength(); x++) {
      +  134  11
                                   final String tmp = xpath.evaluate(".", atts.item(x));
      +  135  11
                                   if (".pom".equals(tmp)) {
      +  136  3
                                       pomAvailable = true;
      +  137  8
                                   } else if (".jar".equals(tmp)) {
      +  138  3
                                       jarAvailable = true;
       139   -
                               }
      -  140   -
       
      -  141  3
                               atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET);
      -  142  3
                               boolean useHTTPS = false;
      -  143  21
                               for (int x = 0; x < atts.getLength(); x++) {
      -  144  18
                                   final String tmp = xpath.evaluate(".", atts.item(x));
      -  145  18
                                   if ("https".equals(tmp)) {
      -  146  0
                                       useHTTPS = true;
      -  147  
                                   }
      -  148   +  140  
                               }
      -  149  3
                               LOGGER.trace("Version: {}", v);
      -  150  3
                               result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS));
      -  151   -
                           }
      -  152   -
                       }
      -  153  0
                   } catch (Throwable e) {
      -  154   -
                       // Anything else is jacked up XML stuff that we really can't recover from well
      -  155  0
                       throw new IOException(e.getMessage(), e);
      -  156  3
                   }
      -  157   +  141  
       
      -  158  3
                   if (missing) {
      -  159  1
                       throw new FileNotFoundException("Artifact not found in Central");
      -  160   +  142  3
                               atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET);
      +  143  3
                               boolean useHTTPS = false;
      +  144  21
                               for (int x = 0; x < atts.getLength(); x++) {
      +  145  18
                                   final String tmp = xpath.evaluate(".", atts.item(x));
      +  146  18
                                   if ("https".equals(tmp)) {
      +  147  0
                                       useHTTPS = true;
      +  148   +
                                   }
      +  149   +
                               }
      +  150  3
                               LOGGER.trace("Version: {}", v);
      +  151  3
                               result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS));
      +  152   +
                           }
      +  153   +
                       }
      +  154  0
                   } catch (Throwable e) {
      +  155   +
                       // Anything else is jacked up XML stuff that we really can't recover from well
      +  156  0
                       throw new IOException(e.getMessage(), e);
      +  157  3
                   }
      +  158   +
       
      +  159  3
                   if (missing) {
      +  160  1
                       throw new FileNotFoundException("Artifact not found in Central");
      +  161  
                   }
      -  161  2
               } else {
      -  162  0
                   LOGGER.debug("Could not connect to Central received response code: {} {}",
      -  163  0
                           conn.getResponseCode(), conn.getResponseMessage());
      -  164  0
                   throw new IOException("Could not connect to Central");
      -  165   +  162  2
               } else {
      +  163  0
                   LOGGER.debug("Could not connect to Central received response code: {} {}",
      +  164  0
                           conn.getResponseCode(), conn.getResponseMessage());
      +  165  0
                   throw new IOException("Could not connect to Central");
      +  166  
               }
      -  166  2
               return result;
      -  167   -
           }
      +  167  2
               return result;
       168   +
           }
      +  169  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerDependency.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerDependency.html index 1cc5ed73c..ba38075c3 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerDependency.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerDependency.html @@ -217,6 +217,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerException.html index 3d7d61ae5..2f39b42b7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerException.html @@ -127,6 +127,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerLockParser.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerLockParser.html index 29f43e080..a96650828 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerLockParser.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.composer.ComposerLockParser.html @@ -228,6 +228,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.CpeMemoryIndex.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.CpeMemoryIndex.html index 01ddf49bc..876a6739c 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.CpeMemoryIndex.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.CpeMemoryIndex.html @@ -385,14 +385,14 @@  211  2
                       for (Pair<String, String> pair : data) {
       212  
                           //todo figure out why there are null products
      -  213  52334
                           if (pair.getLeft() != null && pair.getRight() != null) {
      -  214  52332
                               v.setStringValue(pair.getLeft());
      -  215  52332
                               p.setStringValue(pair.getRight());
      -  216  52332
                               indexWriter.addDocument(doc);
      -  217  52332
                               resetFieldAnalyzer();
      +  213  52774
                           if (pair.getLeft() != null && pair.getRight() != null) {
      +  214  52772
                               v.setStringValue(pair.getLeft());
      +  215  52772
                               p.setStringValue(pair.getRight());
      +  216  52772
                               indexWriter.addDocument(doc);
      +  217  52772
                               resetFieldAnalyzer();
       218  
                           }
      -  219  52334
                       }
      +  219  52774
                       }
       220  0
                   } catch (DatabaseException ex) {
       221  0
                       LOGGER.debug("", ex);
       222  0
                       throw new IndexException("Error reading CPE data", ex);
      @@ -437,15 +437,15 @@
            */
       251  
           private void resetFieldAnalyzer() {
      -  252  52343
               if (productFieldAnalyzer != null) {
      -  253  52343
                   productFieldAnalyzer.clear();
      +  252  52783
               if (productFieldAnalyzer != null) {
      +  253  52783
                   productFieldAnalyzer.clear();
       254  
               }
      -  255  52343
               if (vendorFieldAnalyzer != null) {
      -  256  52343
                   vendorFieldAnalyzer.clear();
      +  255  52783
               if (vendorFieldAnalyzer != null) {
      +  256  52783
                   vendorFieldAnalyzer.clear();
       257  
               }
      -  258  52343
           }
      +  258  52783
           }
       259  
       
       260   @@ -523,7 +523,7 @@
            */
       300  
           public Document getDocument(int documentId) throws IOException {
      -  301  18
               return indexSearcher.doc(documentId);
      +  301  20
               return indexSearcher.doc(documentId);
       302  
           }
       303   @@ -551,6 +551,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.Fields.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.Fields.html index 33a8e420c..5abc697c2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.Fields.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.Fields.html @@ -107,6 +107,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.IndexEntry.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.IndexEntry.html index ea7a1e540..8842af660 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.IndexEntry.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.IndexEntry.html @@ -73,7 +73,7 @@
        * @author Jeremy Long
       28  
        */
      -  29  1610
       public class IndexEntry implements Serializable {
      +  29  1690
       public class IndexEntry implements Serializable {
       30  
       
       31   @@ -151,7 +151,7 @@
            */
       70  
           public String getVendor() {
      -  71  31
               return vendor;
      +  71  42
               return vendor;
       72  
           }
       73   @@ -168,8 +168,8 @@
            */
       79  
           public void setVendor(String vendor) {
      -  80  1612
               this.vendor = vendor;
      -  81  1612
           }
      +  80  1692
               this.vendor = vendor;
      +  81  1692
           }
       82  
           /**
       83   @@ -192,7 +192,7 @@
            */
       92  
           public String getProduct() {
      -  93  39
               return product;
      +  93  46
               return product;
       94  
           }
       95   @@ -209,8 +209,8 @@
            */
       101  
           public void setProduct(String product) {
      -  102  1611
               this.product = product;
      -  103  1611
           }
      +  102  1691
               this.product = product;
      +  103  1691
           }
       104  
           /**
       105   @@ -250,8 +250,8 @@
            */
       123  
           public void setSearchScore(float searchScore) {
      -  124  18
               this.searchScore = searchScore;
      -  125  18
           }
      +  124  20
               this.searchScore = searchScore;
      +  125  20
           }
       126  
       
       127   @@ -320,21 +320,21 @@
           @Override
       164  
           public boolean equals(Object obj) {
      -  165  72
               if (obj == null) {
      +  165  90
               if (obj == null) {
       166  0
                   return false;
       167  
               }
      -  168  72
               if (getClass() != obj.getClass()) {
      +  168  90
               if (getClass() != obj.getClass()) {
       169  0
                   return false;
       170  
               }
      -  171  72
               final IndexEntry other = (IndexEntry) obj;
      -  172  72
               if ((this.vendor == null) ? (other.vendor != null) : !this.vendor.equals(other.vendor)) {
      -  173  70
                   return false;
      +  171  90
               final IndexEntry other = (IndexEntry) obj;
      +  172  90
               if ((this.vendor == null) ? (other.vendor != null) : !this.vendor.equals(other.vendor)) {
      +  173  87
                   return false;
       174  
               }
      -  175  2
               if ((this.product == null) ? (other.product != null) : !this.product.equals(other.product)) {
      -  176  2
                   return false;
      +  175  3
               if ((this.product == null) ? (other.product != null) : !this.product.equals(other.product)) {
      +  176  3
                   return false;
       177  
               }
       178  0
               return true;
      @@ -363,6 +363,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.IndexException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.IndexException.html index ed5ec7688..d977699eb 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.IndexException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cpe.IndexException.html @@ -143,6 +143,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cwe.CweDB.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cwe.CweDB.html index fe7d7c8cd..3aea7b56c 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cwe.CweDB.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cwe.CweDB.html @@ -186,6 +186,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cwe.CweHandler.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cwe.CweHandler.html index d014da909..0e736122e 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cwe.CweHandler.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.cwe.CweHandler.html @@ -121,6 +121,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.AbstractTokenizingFilter.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.AbstractTokenizingFilter.html index 4e831504a..2c4fffea1 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.AbstractTokenizingFilter.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.AbstractTokenizingFilter.html @@ -85,7 +85,7 @@
            * The char term attribute.
       34  
            */
      -  35  15
           private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
      +  35  19
           private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
       36  
       
       37   @@ -100,7 +100,7 @@
            */
       42  
           protected CharTermAttribute getTermAtt() {
      -  43  599757
               return termAtt;
      +  43  605054
               return termAtt;
       44  
           }
       45   @@ -125,7 +125,7 @@
            */
       55  
           protected LinkedList<String> getTokens() {
      -  56  599755
               return tokens;
      +  56  605051
               return tokens;
       57  
           }
       58   @@ -142,9 +142,9 @@
            */
       64  
           public AbstractTokenizingFilter(TokenStream stream) {
      -  65  15
               super(stream);
      -  66  15
               tokens = new LinkedList<String>();
      -  67  15
           }
      +  65  19
               super(stream);
      +  66  19
               tokens = new LinkedList<String>();
      +  67  19
           }
       68  
       
       69   @@ -159,20 +159,20 @@
            */
       74  
           protected boolean addTerm() {
      -  75  599686
               final boolean termAdded = !tokens.isEmpty();
      -  76  599686
               if (termAdded) {
      -  77  206546
                   final String term = tokens.pop();
      -  78  206548
                   clearAttributes();
      -  79  206551
                   termAtt.append(term);
      +  75  604999
               final boolean termAdded = !tokens.isEmpty();
      +  76  605001
               if (termAdded) {
      +  77  207956
                   final String term = tokens.pop();
      +  78  207956
                   clearAttributes();
      +  79  207953
                   termAtt.append(term);
       80  
               }
      -  81  599702
               return termAdded;
      +  81  605000
               return termAdded;
       82  
           }
       83  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.AlphaNumericTokenizer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.AlphaNumericTokenizer.html index 4afec0b8a..66256f094 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.AlphaNumericTokenizer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.AlphaNumericTokenizer.html @@ -91,8 +91,8 @@
            */
       37  
           public AlphaNumericTokenizer(Version matchVersion, Reader in) {
      -  38  11
               super(matchVersion, in);
      -  39  11
           }
      +  38  15
               super(matchVersion, in);
      +  39  15
           }
       40  
       
       41   @@ -131,13 +131,13 @@
           @Override
       59  
           protected boolean isTokenChar(int c) {
      -  60  1258696
               return Character.isLetter(c) || Character.isDigit(c);
      +  60  1271270
               return Character.isLetter(c) || Character.isDigit(c);
       61  
           }
       62  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.DependencySimilarity.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.DependencySimilarity.html index 9125d2cf7..142192d28 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.DependencySimilarity.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.DependencySimilarity.html @@ -111,6 +111,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.FieldAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.FieldAnalyzer.html index 3ea7005fa..c37b5efe2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.FieldAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.FieldAnalyzer.html @@ -178,6 +178,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.LuceneUtils.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.LuceneUtils.html index 80e276b25..c8be04cf3 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.LuceneUtils.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.LuceneUtils.html @@ -124,15 +124,15 @@
                   final CharSequence text) {
       55  
       
      -  56  111
               if (text == null || buf == null) {
      +  56  112
               if (text == null || buf == null) {
       57  1
                   return;
       58  
               }
       59  
       
      -  60  1327
               for (int i = 0; i < text.length(); i++) {
      -  61  1217
                   final char c = text.charAt(i);
      -  62  1217
                   switch (c) {
      +  60  1336
               for (int i = 0; i < text.length(); i++) {
      +  61  1225
                   final char c = text.charAt(i);
      +  62  1225
                   switch (c) {
       63  
                       case '+':
       64   @@ -174,14 +174,14 @@  82  44
                           buf.append('\\');
       83  
                       default:
      -  84  1217
                           buf.append(c);
      +  84  1225
                           buf.append(c);
       85  
                           break;
       86  
                   }
       87  
               }
      -  88  110
           }
      +  88  111
           }
       89  
       
       90   @@ -212,6 +212,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer.html index cefe3df20..6f977e89e 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer.html @@ -140,13 +140,13 @@
           @Override
       63  
           protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
      -  64  10
               final Tokenizer source = new AlphaNumericTokenizer(version, reader);
      +  64  14
               final Tokenizer source = new AlphaNumericTokenizer(version, reader);
       65  
       
      -  66  10
               TokenStream stream = source;
      +  66  14
               TokenStream stream = source;
       67  
       
      -  68  10
               stream = new WordDelimiterFilter(stream,
      +  68  14
               stream = new WordDelimiterFilter(stream,
       69  
                       WordDelimiterFilter.GENERATE_WORD_PARTS
       70   @@ -161,14 +161,14 @@
                       | WordDelimiterFilter.STEM_ENGLISH_POSSESSIVE, null);
       75  
       
      -  76  10
               stream = new LowerCaseFilter(version, stream);
      -  77  10
               stream = new UrlTokenizingFilter(stream);
      -  78  10
               concatenatingFilter = new TokenPairConcatenatingFilter(stream);
      -  79  10
               stream = concatenatingFilter;
      -  80  10
               stream = new StopFilter(version, stream, StopAnalyzer.ENGLISH_STOP_WORDS_SET);
      +  76  14
               stream = new LowerCaseFilter(version, stream);
      +  77  14
               stream = new UrlTokenizingFilter(stream);
      +  78  14
               concatenatingFilter = new TokenPairConcatenatingFilter(stream);
      +  79  14
               stream = concatenatingFilter;
      +  80  14
               stream = new StopFilter(version, stream, StopAnalyzer.ENGLISH_STOP_WORDS_SET);
       81  
       
      -  82  10
               return new TokenStreamComponents(source, stream);
      +  82  14
               return new TokenStreamComponents(source, stream);
       83  
           }
       84   @@ -187,15 +187,15 @@
            */
       91  
           public void clear() {
      -  92  104688
               if (concatenatingFilter != null) {
      -  93  104688
                   concatenatingFilter.clear();
      +  92  105568
               if (concatenatingFilter != null) {
      +  93  105568
                   concatenatingFilter.clear();
       94  
               }
      -  95  104688
           }
      +  95  105568
           }
       96  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.TokenPairConcatenatingFilter.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.TokenPairConcatenatingFilter.html index 318fcfff3..14082126e 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.TokenPairConcatenatingFilter.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.TokenPairConcatenatingFilter.html @@ -93,7 +93,7 @@
            * The char term attribute.
       38  
            */
      -  39  12
           private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
      +  39  16
           private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
       40  
           /**
       41   @@ -158,9 +158,9 @@
            */
       72  
           public TokenPairConcatenatingFilter(TokenStream stream) {
      -  73  12
               super(stream);
      -  74  12
               words = new LinkedList<String>();
      -  75  12
           }
      +  73  16
               super(stream);
      +  74  16
               words = new LinkedList<String>();
      +  75  16
           }
       76  
       
       77   @@ -185,35 +185,35 @@
       
       87  
               //collect all the terms into the words collection
      -  88  580669
               while (input.incrementToken()) {
      -  89  193508
                   final String word = new String(termAtt.buffer(), 0, termAtt.length());
      -  90  193508
                   words.add(word);
      -  91  193508
               }
      +  88  586499
               while (input.incrementToken()) {
      +  89  195451
                   final String word = new String(termAtt.buffer(), 0, termAtt.length());
      +  90  195451
                   words.add(word);
      +  91  195451
               }
       92  
       
       93  
               //if we have a previousTerm - write it out as its own token concatenated
       94  
               // with the current word (if one is available).
      -  95  387161
               if (previousWord != null && !words.isEmpty()) {
      -  96  88818
                   final String word = words.getFirst();
      -  97  88818
                   clearAttributes();
      -  98  88818
                   termAtt.append(previousWord).append(word);
      -  99  88818
                   previousWord = null;
      -  100  88818
                   return true;
      +  95  391048
               if (previousWord != null && !words.isEmpty()) {
      +  96  89881
                   final String word = words.getFirst();
      +  97  89881
                   clearAttributes();
      +  98  89881
                   termAtt.append(previousWord).append(word);
      +  99  89881
                   previousWord = null;
      +  100  89881
                   return true;
       101  
               }
       102  
               //if we have words, write it out as a single token
      -  103  298343
               if (!words.isEmpty()) {
      -  104  193508
                   final String word = words.removeFirst();
      -  105  193508
                   clearAttributes();
      -  106  193508
                   termAtt.append(word);
      -  107  193508
                   previousWord = word;
      -  108  193508
                   return true;
      +  103  301167
               if (!words.isEmpty()) {
      +  104  195451
                   final String word = words.removeFirst();
      +  105  195451
                   clearAttributes();
      +  106  195451
                   termAtt.append(word);
      +  107  195451
                   previousWord = word;
      +  108  195451
                   return true;
       109  
               }
      -  110  104835
               return false;
      +  110  105716
               return false;
       111  
           }
       112   @@ -232,9 +232,9 @@
            */
       119  
           public void clear() {
      -  120  104689
               previousWord = null;
      -  121  104689
               words.clear();
      -  122  104689
           }
      +  120  105569
               previousWord = null;
      +  121  105569
               words.clear();
      +  122  105569
           }
       123  
       
       124   @@ -306,6 +306,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.UrlTokenizingFilter.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.UrlTokenizingFilter.html index 79a180269..a752b0672 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.UrlTokenizingFilter.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.lucene.UrlTokenizingFilter.html @@ -116,8 +116,8 @@
            */
       50  
           public UrlTokenizingFilter(TokenStream stream) {
      -  51  15
               super(stream);
      -  52  15
           }
      +  51  19
               super(stream);
      +  52  19
           }
       53  
       
       54   @@ -138,11 +138,11 @@
           @Override
       62  
           public boolean incrementToken() throws IOException {
      -  63  599755
               final LinkedList<String> tokens = getTokens();
      -  64  599757
               final CharTermAttribute termAtt = getTermAtt();
      -  65  599759
               if (tokens.isEmpty() && input.incrementToken()) {
      -  66  206541
                   final String text = new String(termAtt.buffer(), 0, termAtt.length());
      -  67  206548
                   if (UrlStringUtils.containsUrl(text)) {
      +  63  605049
               final LinkedList<String> tokens = getTokens();
      +  64  605055
               final CharTermAttribute termAtt = getTermAtt();
      +  65  605054
               if (tokens.isEmpty() && input.incrementToken()) {
      +  66  207951
                   final String text = new String(termAtt.buffer(), 0, termAtt.length());
      +  67  207951
                   if (UrlStringUtils.containsUrl(text)) {
       68  6
                       final String[] parts = text.split("\\s");
       69  12
                       for (String part : parts) {
       70  6
                           if (UrlStringUtils.isUrl(part)) {
      @@ -162,18 +162,18 @@  81  
                       }
       82  6
                   } else {
      -  83  206539
                       tokens.add(text);
      +  83  207945
                       tokens.add(text);
       84  
                   }
       85  
               }
      -  86  599684
               return addTerm();
      +  86  605000
               return addTerm();
       87  
           }
       88  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nexus.MavenArtifact.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nexus.MavenArtifact.html index 152817e29..b8698ba55 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nexus.MavenArtifact.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nexus.MavenArtifact.html @@ -426,6 +426,6 @@
       // vim: cc=120:sw=4:ts=4:sts=4
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nexus.NexusSearch.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nexus.NexusSearch.html index bd3c01253..ff906f379 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nexus.NexusSearch.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nexus.NexusSearch.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      NexusSearch
      0%
      0/64
      0%
      0/24
      8.667
      NexusSearch
      0%
      0/58
      0%
      0/19
      7.667
       
      @@ -72,261 +72,263 @@  27  
       import javax.xml.xpath.XPathFactory;
       28   -
       import org.owasp.dependencycheck.utils.InvalidSettingException;
      +
       
       29   -
       import org.owasp.dependencycheck.utils.Settings;
      +
       import org.owasp.dependencycheck.utils.InvalidSettingException;
       30   -
       import org.owasp.dependencycheck.utils.URLConnectionFactory;
      +
       import org.owasp.dependencycheck.utils.Settings;
       31   -
       import org.slf4j.Logger;
      +
       import org.owasp.dependencycheck.utils.URLConnectionFactory;
       32   -
       import org.slf4j.LoggerFactory;
      +
       import org.slf4j.Logger;
       33   -
       import org.w3c.dom.Document;
      +
       import org.slf4j.LoggerFactory;
       34   -
       
      +
       import org.w3c.dom.Document;
       35   -
       /**
      +
       
       36   -
        * Class of methods to search Nexus repositories.
      +
       /**
       37   -
        *
      +
        * Class of methods to search Nexus repositories.
       38   -
        * @author colezlaw
      +
        *
       39   -
        */
      +
        * @author colezlaw
       40   -
       public class NexusSearch {
      +
        */
       41   -
       
      +
       public class NexusSearch {
       42   -
           /**
      +
       
       43   -
            * The root URL for the Nexus repository service.
      +
           /**
       44   -
            */
      +
            * The root URL for the Nexus repository service.
       45   -
           private final URL rootURL;
      +
            */
       46   -
       
      +
           private final URL rootURL;
       47   -
           /**
      +
       
       48   -
            * Whether to use the Proxy when making requests.
      +
           /**
       49   -
            */
      +
            * Whether to use the Proxy when making requests.
       50   -
           private boolean useProxy;
      +
            */
       51   -
           /**
      +
           private final boolean useProxy;
       52   -
            * Used for logging.
      +
           /**
       53   +
            * Used for logging.
      +  54  
            */
      -  54  0
           private static final Logger LOGGER = LoggerFactory.getLogger(NexusSearch.class);
      -  55   -
       
      +  55  0
           private static final Logger LOGGER = LoggerFactory.getLogger(NexusSearch.class);
       56   -
           /**
      -  57   -
            * Creates a NexusSearch for the given repository URL.
      -  58   -
            *
      -  59   -
            * @param rootURL the root URL of the repository on which searches should execute. full URL's are calculated relative to this
      -  60   -
            * URL, so it should end with a /
      -  61   -
            */
      -  62  0
           public NexusSearch(URL rootURL) {
      -  63  0
               this.rootURL = rootURL;
      -  64   -
               try {
      -  65  0
                   if (null != Settings.getString(Settings.KEYS.PROXY_SERVER)
      -  66  0
                           && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY)) {
      -  67  0
                       useProxy = true;
      -  68  0
                       LOGGER.debug("Using proxy");
      -  69   -
                   } else {
      -  70  0
                       useProxy = false;
      -  71  0
                       LOGGER.debug("Not using proxy");
      -  72   -
                   }
      -  73  0
               } catch (InvalidSettingException ise) {
      -  74  0
                   useProxy = false;
      -  75  0
               }
      -  76  0
           }
      -  77  
       
      -  78   +  57  
           /**
      -  79   -
            * Searches the configured Nexus repository for the given sha1 hash. If the artifact is found, a <code>MavenArtifact</code> is
      -  80   -
            * populated with the coordinate information.
      -  81   +  58   +
            * Creates a NexusSearch for the given repository URL.
      +  59  
            *
      -  82   -
            * @param sha1 The SHA-1 hash string for which to search
      -  83   -
            * @return the populated Maven coordinates
      -  84   -
            * @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not found.
      -  85   +  60   +
            * @param rootURL the root URL of the repository on which searches should
      +  61   +
            * execute. full URL's are calculated relative to this URL, so it should end
      +  62   +
            * with a /
      +  63   +
            * @param useProxy flag indicating if the proxy settings should be used
      +  64  
            */
      -  86   +  65  0
           public NexusSearch(URL rootURL, boolean useProxy) {
      +  66  0
               this.rootURL = rootURL;
      +  67  0
               this.useProxy = useProxy;
      +  68  0
               LOGGER.debug("Using proxy: {}", useProxy);
      +  69  0
           }
      +  70   +
       
      +  71   +
           /**
      +  72   +
            * Searches the configured Nexus repository for the given sha1 hash. If the
      +  73   +
            * artifact is found, a <code>MavenArtifact</code> is populated with the
      +  74   +
            * coordinate information.
      +  75   +
            *
      +  76   +
            * @param sha1 The SHA-1 hash string for which to search
      +  77   +
            * @return the populated Maven coordinates
      +  78   +
            * @throws IOException if it's unable to connect to the specified repository
      +  79   +
            * or if the specified artifact is not found.
      +  80   +
            */
      +  81  
           public MavenArtifact searchSha1(String sha1) throws IOException {
      -  87  0
               if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
      -  88  0
                   throw new IllegalArgumentException("Invalid SHA1 format");
      -  89   +  82  0
               if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
      +  83  0
                   throw new IllegalArgumentException("Invalid SHA1 format");
      +  84  
               }
      +  85   +
       
      +  86  0
               final URL url = new URL(rootURL, String.format("identify/sha1/%s",
      +  87  0
                       sha1.toLowerCase()));
      +  88   +
       
      +  89  0
               LOGGER.debug("Searching Nexus url {}", url);
       90  
       
      -  91  0
               final URL url = new URL(rootURL, String.format("identify/sha1/%s",
      -  92  0
                       sha1.toLowerCase()));
      -  93   -
       
      -  94  0
               LOGGER.debug("Searching Nexus url {}", url);
      -  95   -
       
      -  96   +  91  
               // Determine if we need to use a proxy. The rules:
      -  97   +  92  
               // 1) If the proxy is set, AND the setting is set to true, use the proxy
      -  98   +  93  
               // 2) Otherwise, don't use the proxy (either the proxy isn't configured,
      -  99   +  94  
               // or proxy is specifically set to false
      -  100   +  95  
               HttpURLConnection conn;
      -  101  0
               conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
      -  102  0
               conn.setDoOutput(true);
      +  96  0
               conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
      +  97  0
               conn.setDoOutput(true);
      +  98   +
       
      +  99   +
               // JSON would be more elegant, but there's not currently a dependency
      +  100   +
               // on JSON, so don't want to add one just for this
      +  101  0
               conn.addRequestProperty("Accept", "application/xml");
      +  102  0
               conn.connect();
       103  
       
      -  104   -
               // JSON would be more elegant, but there's not currently a dependency
      +  104  0
               switch (conn.getResponseCode()) {
       105   -
               // on JSON, so don't want to add one just for this
      -  106  0
               conn.addRequestProperty("Accept", "application/xml");
      -  107  0
               conn.connect();
      -  108   -
       
      -  109  0
               if (conn.getResponseCode() == 200) {
      -  110   -
                   try {
      -  111   -
                       final DocumentBuilder builder = DocumentBuilderFactory
      -  112  0
                               .newInstance().newDocumentBuilder();
      -  113  0
                       final Document doc = builder.parse(conn.getInputStream());
      -  114  0
                       final XPath xpath = XPathFactory.newInstance().newXPath();
      -  115  0
                       final String groupId = xpath
      -  116  0
                               .evaluate(
      +
                   case 200:
      +  106   +
                       try {
      +  107  0
                           final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      +  108  0
                           factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +  109  0
                           final DocumentBuilder builder = factory.newDocumentBuilder();
      +  110  0
                           final Document doc = builder.parse(conn.getInputStream());
      +  111  0
                           final XPath xpath = XPathFactory.newInstance().newXPath();
      +  112  0
                           final String groupId = xpath
      +  113  0
                                   .evaluate(
      +  114   +
                                           "/org.sonatype.nexus.rest.model.NexusArtifact/groupId",
      +  115   +
                                           doc);
      +  116  0
                           final String artifactId = xpath.evaluate(
       117   -
                                       "/org.sonatype.nexus.rest.model.NexusArtifact/groupId",
      +
                                   "/org.sonatype.nexus.rest.model.NexusArtifact/artifactId",
       118   -
                                       doc);
      -  119  0
                       final String artifactId = xpath.evaluate(
      -  120   -
                               "/org.sonatype.nexus.rest.model.NexusArtifact/artifactId",
      +
                                   doc);
      +  119  0
                           final String version = xpath
      +  120  0
                                   .evaluate(
       121   -
                               doc);
      -  122  0
                       final String version = xpath
      -  123  0
                               .evaluate(
      -  124   -
                                       "/org.sonatype.nexus.rest.model.NexusArtifact/version",
      +
                                           "/org.sonatype.nexus.rest.model.NexusArtifact/version",
      +  122   +
                                           doc);
      +  123  0
                           final String link = xpath
      +  124  0
                                   .evaluate(
       125   -
                                       doc);
      -  126  0
                       final String link = xpath
      -  127  0
                               .evaluate(
      -  128   -
                                       "/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink",
      +
                                           "/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink",
      +  126   +
                                           doc);
      +  127  0
                           final String pomLink = xpath
      +  128  0
                                   .evaluate(
       129   -
                                       doc);
      -  130  0
                       final String pomLink = xpath
      -  131  0
                               .evaluate(
      -  132   -
                                       "/org.sonatype.nexus.rest.model.NexusArtifact/pomLink",
      -  133   -
                                       doc);
      -  134  0
                       final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version);
      -  135  0
                       if (link != null && !link.isEmpty()) {
      -  136  0
                           ma.setArtifactUrl(link);
      +
                                           "/org.sonatype.nexus.rest.model.NexusArtifact/pomLink",
      +  130   +
                                           doc);
      +  131  0
                           final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version);
      +  132  0
                           if (link != null && !link.isEmpty()) {
      +  133  0
                               ma.setArtifactUrl(link);
      +  134   +
                           }
      +  135  0
                           if (pomLink != null && !pomLink.isEmpty()) {
      +  136  0
                               ma.setPomUrl(pomLink);
       137   -
                       }
      -  138  0
                       if (pomLink != null && !pomLink.isEmpty()) {
      -  139  0
                           ma.setPomUrl(pomLink);
      +
                           }
      +  138  0
                           return ma;
      +  139  0
                       } catch (Throwable e) {
       140   -
                       }
      -  141  0
                       return ma;
      -  142  0
                   } catch (Throwable e) {
      +
                           // Anything else is jacked-up XML stuff that we really can't recover
      +  141   +
                           // from well
      +  142  0
                           throw new IOException(e.getMessage(), e);
       143   -
                       // Anything else is jacked-up XML stuff that we really can't recover
      +
                       }
       144   -
                       // from well
      -  145  0
                       throw new IOException(e.getMessage(), e);
      +
                   case 404:
      +  145  0
                       throw new FileNotFoundException("Artifact not found in Nexus");
       146   -
                   }
      -  147  0
               } else if (conn.getResponseCode() == 404) {
      -  148  0
                   throw new FileNotFoundException("Artifact not found in Nexus");
      -  149   -
               } else {
      -  150  0
                   LOGGER.debug("Could not connect to Nexus received response code: {} {}",
      -  151  0
                           conn.getResponseCode(), conn.getResponseMessage());
      -  152  0
                   throw new IOException("Could not connect to Nexus");
      -  153   +
                   default:
      +  147  0
                       LOGGER.debug("Could not connect to Nexus received response code: {} {}",
      +  148  0
                               conn.getResponseCode(), conn.getResponseMessage());
      +  149  0
                       throw new IOException("Could not connect to Nexus");
      +  150  
               }
      -  154   +  151  
           }
      -  155   +  152  
       
      -  156   +  153  
           /**
      -  157   +  154  
            * Do a preflight request to see if the repository is actually working.
      -  158   +  155  
            *
      -  159   -
            * @return whether the repository is listening and returns the /status URL correctly
      -  160   +  156   +
            * @return whether the repository is listening and returns the /status URL
      +  157   +
            * correctly
      +  158  
            */
      -  161   +  159  
           public boolean preflightRequest() {
      -  162   +  160  
               HttpURLConnection conn;
      -  163   +  161  
               try {
      -  164  0
                   final URL url = new URL(rootURL, "status");
      -  165  0
                   conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
      -  166  0
                   conn.addRequestProperty("Accept", "application/xml");
      -  167  0
                   conn.connect();
      -  168  0
                   if (conn.getResponseCode() != 200) {
      -  169  0
                       LOGGER.warn("Expected 200 result from Nexus, got {}", conn.getResponseCode());
      -  170  0
                       return false;
      -  171   +  162  0
                   final URL url = new URL(rootURL, "status");
      +  163  0
                   conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
      +  164  0
                   conn.addRequestProperty("Accept", "application/xml");
      +  165  0
                   conn.connect();
      +  166  0
                   if (conn.getResponseCode() != 200) {
      +  167  0
                       LOGGER.warn("Expected 200 result from Nexus, got {}", conn.getResponseCode());
      +  168  0
                       return false;
      +  169  
                   }
      -  172  0
                   final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
      -  173  0
                   final Document doc = builder.parse(conn.getInputStream());
      -  174  0
                   if (!"status".equals(doc.getDocumentElement().getNodeName())) {
      -  175  0
                       LOGGER.warn("Expected root node name of status, got {}", doc.getDocumentElement().getNodeName());
      -  176  0
                       return false;
      -  177   +  170  0
                   final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
      +  171  0
                   final Document doc = builder.parse(conn.getInputStream());
      +  172  0
                   if (!"status".equals(doc.getDocumentElement().getNodeName())) {
      +  173  0
                       LOGGER.warn("Expected root node name of status, got {}", doc.getDocumentElement().getNodeName());
      +  174  0
                       return false;
      +  175  
                   }
      -  178  0
               } catch (Throwable e) {
      -  179  0
                   return false;
      -  180  0
               }
      +  176  0
               } catch (Throwable e) {
      +  177  0
                   return false;
      +  178  0
               }
      +  179   +
       
      +  180  0
               return true;
       181   -
       
      -  182  0
               return true;
      -  183  
           }
      -  184   +  182  
       }
      -  185   +  183  
       
      -  186   +  184  
       // vim: cc=120:sw=4:ts=4:sts=4
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NugetPackage.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NugetPackage.html index 2e13db31f..86a0975f2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NugetPackage.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NugetPackage.html @@ -352,6 +352,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NuspecParseException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NuspecParseException.html index dc7e0d8f4..589605ed5 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NuspecParseException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NuspecParseException.html @@ -147,6 +147,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NuspecParser.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NuspecParser.html index 0ab9765cf..6d83da5d4 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NuspecParser.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.NuspecParser.html @@ -93,6 +93,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.XPathNuspecParser.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.XPathNuspecParser.html index 45b765e47..63528ce2a 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.XPathNuspecParser.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nuget.XPathNuspecParser.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      XPathNuspecParser
      95%
      20/21
      60%
      6/10
      6
      XPathNuspecParser
      95%
      22/23
      60%
      6/10
      6
       
      @@ -93,73 +93,79 @@  38  
            * @param n the node to test
       39   -
            * @return the string content of the node, or null if the node itself is null
      +
            * @return the string content of the node, or null if the node itself is
       40   -
            */
      +
            * null
       41   -
           private String getOrNull(Node n) {
      -  42  3
               if (n != null) {
      -  43  3
                   return n.getTextContent();
      -  44   -
               } else {
      -  45  0
                   return null;
      -  46   -
               }
      -  47   -
           }
      -  48   -
       
      -  49   -
           /**
      -  50   -
            * Parse an input stream and return the resulting {@link NugetPackage}.
      -  51   -
            *
      -  52   -
            * @param stream the input stream to parse
      -  53   -
            * @return the populated bean
      -  54   -
            * @throws NuspecParseException when an exception occurs
      -  55  
            */
      -  56   -
           @Override
      -  57   -
           public NugetPackage parse(InputStream stream) throws NuspecParseException {
      -  58   -
               try {
      -  59  3
                   final Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream);
      -  60  2
                   final XPath xpath = XPathFactory.newInstance().newXPath();
      -  61  2
                   final NugetPackage nuspec = new NugetPackage();
      -  62   -
       
      -  63  2
                   if (xpath.evaluate("/package/metadata/id", d, XPathConstants.NODE) == null
      -  64  1
                           || xpath.evaluate("/package/metadata/version", d, XPathConstants.NODE) == null
      -  65  1
                           || xpath.evaluate("/package/metadata/authors", d, XPathConstants.NODE) == null
      -  66  1
                           || xpath.evaluate("/package/metadata/description", d, XPathConstants.NODE) == null) {
      -  67  1
                       throw new NuspecParseException("Invalid Nuspec format");
      -  68   -
                   }
      -  69   -
       
      -  70  1
                   nuspec.setId(xpath.evaluate("/package/metadata/id", d));
      -  71  1
                   nuspec.setVersion(xpath.evaluate("/package/metadata/version", d));
      -  72  1
                   nuspec.setAuthors(xpath.evaluate("/package/metadata/authors", d));
      -  73  1
                   nuspec.setOwners(getOrNull((Node) xpath.evaluate("/package/metadata/owners", d, XPathConstants.NODE)));
      -  74  1
                   nuspec.setLicenseUrl(getOrNull((Node) xpath.evaluate("/package/metadata/licenseUrl", d, XPathConstants.NODE)));
      -  75  1
                   nuspec.setTitle(getOrNull((Node) xpath.evaluate("/package/metadata/title", d, XPathConstants.NODE)));
      -  76  1
                   return nuspec;
      -  77  2
               } catch (Throwable e) {
      -  78  2
                   throw new NuspecParseException("Unable to parse nuspec", e);
      -  79   +  42   +
           private String getOrNull(Node n) {
      +  43  3
               if (n != null) {
      +  44  3
                   return n.getTextContent();
      +  45   +
               } else {
      +  46  0
                   return null;
      +  47  
               }
      -  80   +  48  
           }
      -  81   +  49   +
       
      +  50   +
           /**
      +  51   +
            * Parse an input stream and return the resulting {@link NugetPackage}.
      +  52   +
            *
      +  53   +
            * @param stream the input stream to parse
      +  54   +
            * @return the populated bean
      +  55   +
            * @throws NuspecParseException when an exception occurs
      +  56   +
            */
      +  57   +
           @Override
      +  58   +
           public NugetPackage parse(InputStream stream) throws NuspecParseException {
      +  59   +
               try {
      +  60  3
                   final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      +  61  3
                   factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +  62  3
                   final Document d = factory.newDocumentBuilder().parse(stream);
      +  63   +
       
      +  64  2
                   final XPath xpath = XPathFactory.newInstance().newXPath();
      +  65  2
                   final NugetPackage nuspec = new NugetPackage();
      +  66   +
       
      +  67  2
                   if (xpath.evaluate("/package/metadata/id", d, XPathConstants.NODE) == null
      +  68  1
                           || xpath.evaluate("/package/metadata/version", d, XPathConstants.NODE) == null
      +  69  1
                           || xpath.evaluate("/package/metadata/authors", d, XPathConstants.NODE) == null
      +  70  1
                           || xpath.evaluate("/package/metadata/description", d, XPathConstants.NODE) == null) {
      +  71  1
                       throw new NuspecParseException("Invalid Nuspec format");
      +  72   +
                   }
      +  73   +
       
      +  74  1
                   nuspec.setId(xpath.evaluate("/package/metadata/id", d));
      +  75  1
                   nuspec.setVersion(xpath.evaluate("/package/metadata/version", d));
      +  76  1
                   nuspec.setAuthors(xpath.evaluate("/package/metadata/authors", d));
      +  77  1
                   nuspec.setOwners(getOrNull((Node) xpath.evaluate("/package/metadata/owners", d, XPathConstants.NODE)));
      +  78  1
                   nuspec.setLicenseUrl(getOrNull((Node) xpath.evaluate("/package/metadata/licenseUrl", d, XPathConstants.NODE)));
      +  79  1
                   nuspec.setTitle(getOrNull((Node) xpath.evaluate("/package/metadata/title", d, XPathConstants.NODE)));
      +  80  1
                   return nuspec;
      +  81  2
               } catch (Throwable e) {
      +  82  2
                   throw new NuspecParseException("Unable to parse nuspec", e);
      +  83   +
               }
      +  84   +
           }
      +  85  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.ConnectionFactory.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.ConnectionFactory.html index e1fb006ff..29e107c5b 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.ConnectionFactory.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.ConnectionFactory.html @@ -207,8 +207,8 @@
           public static void initialize() throws DatabaseException {
       99  
               //this only needs to be called once.
      -  100  19
               if (connectionString != null) {
      -  101  17
                   return;
      +  100  21
               if (connectionString != null) {
      +  101  19
                   return;
       102  
               }
       103  2
               Connection conn = null;
      @@ -644,6 +644,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.CorruptDatabaseException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.CorruptDatabaseException.html index a25963e0a..7c79a3ae3 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.CorruptDatabaseException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.CorruptDatabaseException.html @@ -115,6 +115,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.CveDB.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.CveDB.html index ea7f55c29..dae116f8e 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.CveDB.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.CveDB.html @@ -220,7 +220,7 @@
            */
       111  
           protected Connection getConnection() {
      -  112  45
               return conn;
      +  112  47
               return conn;
       113  
           }
       114   @@ -240,7 +240,7 @@  121  
            */
       122   -
           public final void open() throws DatabaseException {
      +
           public final synchronized void open() throws DatabaseException {
       123  26
               if (!isOpen()) {
       124  13
                   conn = ConnectionFactory.getConnection();
       125   @@ -257,8 +257,8 @@  131  
            */
       132   -
           public void close() {
      -  133  26
               if (conn != null) {
      +
           public synchronized void close() {
      +  133  22
               if (conn != null) {
       134  
                   try {
       135  13
                       conn.close();
      @@ -272,7 +272,7 @@  143  13
                   conn = null;
       144  
               }
      -  145  26
           }
      +  145  22
           }
       146  
       
       147   @@ -286,7 +286,7 @@  151  
            */
       152   -
           public boolean isOpen() {
      +
           public synchronized boolean isOpen() {
       153  26
               return conn != null;
       154  
           }
      @@ -303,7 +303,7 @@  160  
            */
       161   -
           public void commit() throws SQLException {
      +
           public synchronized void commit() throws SQLException {
       162  
               //temporary remove this as autocommit is on.
       163   @@ -331,10 +331,10 @@
           @SuppressWarnings("FinalizeDeclaration")
       175  
           protected void finalize() throws Throwable {
      -  176  13
               LOGGER.debug("Entering finalize");
      -  177  13
               close();
      -  178  13
               super.finalize();
      -  179  13
           }
      +  176  9
               LOGGER.debug("Entering finalize");
      +  177  9
               close();
      +  178  9
               super.finalize();
      +  179  9
           }
       180  
           /**
       181   @@ -385,32 +385,32 @@  204  
            */
       205   -
           public Set<VulnerableSoftware> getCPEs(String vendor, String product) {
      -  206  3
               final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>();
      -  207  3
               ResultSet rs = null;
      -  208  3
               PreparedStatement ps = null;
      +
           public synchronized Set<VulnerableSoftware> getCPEs(String vendor, String product) {
      +  206  4
               final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>();
      +  207  4
               ResultSet rs = null;
      +  208  4
               PreparedStatement ps = null;
       209  
               try {
      -  210  3
                   ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES"));
      -  211  3
                   ps.setString(1, vendor);
      -  212  3
                   ps.setString(2, product);
      -  213  3
                   rs = ps.executeQuery();
      +  210  4
                   ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES"));
      +  211  4
                   ps.setString(1, vendor);
      +  212  4
                   ps.setString(2, product);
      +  213  4
                   rs = ps.executeQuery();
       214  
       
      -  215  112
                   while (rs.next()) {
      -  216  109
                       final VulnerableSoftware vs = new VulnerableSoftware();
      -  217  109
                       vs.setCpe(rs.getString(1));
      -  218  109
                       cpe.add(vs);
      -  219  109
                   }
      +  215  134
                   while (rs.next()) {
      +  216  130
                       final VulnerableSoftware vs = new VulnerableSoftware();
      +  217  130
                       vs.setCpe(rs.getString(1));
      +  218  130
                       cpe.add(vs);
      +  219  130
                   }
       220  0
               } catch (SQLException ex) {
       221  0
                   LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
       222  0
                   LOGGER.debug("", ex);
       223  
               } finally {
      -  224  3
                   DBUtils.closeResultSet(rs);
      -  225  3
                   DBUtils.closeStatement(ps);
      -  226  3
               }
      -  227  3
               return cpe;
      +  224  4
                   DBUtils.closeResultSet(rs);
      +  225  4
                   DBUtils.closeStatement(ps);
      +  226  4
               }
      +  227  4
               return cpe;
       228  
           }
       229   @@ -430,7 +430,7 @@  236  
            */
       237   -
           public Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
      +
           public synchronized Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
       238  2
               final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>();
       239  2
               ResultSet rs = null;
       240  2
               PreparedStatement ps = null;
      @@ -438,8 +438,8 @@
               try {
       242  2
                   ps = getConnection().prepareStatement(statementBundle.getString("SELECT_VENDOR_PRODUCT_LIST"));
       243  2
                   rs = ps.executeQuery();
      -  244  52336
                   while (rs.next()) {
      -  245  52334
                       data.add(new Pair<String, String>(rs.getString(1), rs.getString(2)));
      +  244  52776
                   while (rs.next()) {
      +  245  52774
                       data.add(new Pair<String, String>(rs.getString(1), rs.getString(2)));
       246  
                   }
       247  0
               } catch (SQLException ex) {
      @@ -466,7 +466,7 @@  261  
            */
       262   -
           Properties getProperties() {
      +
           synchronized Properties getProperties() {
       263  13
               final Properties prop = new Properties();
       264  13
               PreparedStatement ps = null;
       265  13
               ResultSet rs = null;
      @@ -504,7 +504,7 @@  287  
            */
       288   -
           void saveProperty(String key, String value) {
      +
           synchronized void saveProperty(String key, String value) {
       289  
               try {
       290   @@ -564,55 +564,55 @@  330  
            */
       331   -
           public List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException {
      -  332  3
               final VulnerableSoftware cpe = new VulnerableSoftware();
      +
           public synchronized List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException {
      +  332  4
               final VulnerableSoftware cpe = new VulnerableSoftware();
       333  
               try {
      -  334  3
                   cpe.parseName(cpeStr);
      +  334  4
                   cpe.parseName(cpeStr);
       335  0
               } catch (UnsupportedEncodingException ex) {
       336  0
                   LOGGER.trace("", ex);
      -  337  3
               }
      -  338  3
               final DependencyVersion detectedVersion = parseDependencyVersion(cpe);
      -  339  3
               final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>();
      +  337  4
               }
      +  338  4
               final DependencyVersion detectedVersion = parseDependencyVersion(cpe);
      +  339  4
               final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>();
       340  
       
      -  341  3
               PreparedStatement ps = null;
      -  342  3
               ResultSet rs = null;
      +  341  4
               PreparedStatement ps = null;
      +  342  4
               ResultSet rs = null;
       343  
               try {
      -  344  3
                   ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE"));
      -  345  3
                   ps.setString(1, cpe.getVendor());
      -  346  3
                   ps.setString(2, cpe.getProduct());
      -  347  3
                   rs = ps.executeQuery();
      -  348  3
                   String currentCVE = "";
      +  344  4
                   ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE"));
      +  345  4
                   ps.setString(1, cpe.getVendor());
      +  346  4
                   ps.setString(2, cpe.getProduct());
      +  347  4
                   rs = ps.executeQuery();
      +  348  4
                   String currentCVE = "";
       349  
       
      -  350  3
                   final Map<String, Boolean> vulnSoftware = new HashMap<String, Boolean>();
      -  351  282
                   while (rs.next()) {
      -  352  279
                       final String cveId = rs.getString(1);
      -  353  279
                       if (!currentCVE.equals(cveId)) { //check for match and add
      -  354  10
                           final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion);
      -  355  10
                           if (matchedCPE != null) {
      +  350  4
                   final Map<String, Boolean> vulnSoftware = new HashMap<String, Boolean>();
      +  351  309
                   while (rs.next()) {
      +  352  305
                       final String cveId = rs.getString(1);
      +  353  305
                       if (!currentCVE.equals(cveId)) { //check for match and add
      +  354  12
                           final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion);
      +  355  12
                           if (matchedCPE != null) {
       356  6
                               final Vulnerability v = getVulnerability(currentCVE);
       357  6
                               v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null);
       358  6
                               vulnerabilities.add(v);
       359  
                           }
      -  360  10
                           vulnSoftware.clear();
      -  361  10
                           currentCVE = cveId;
      +  360  12
                           vulnSoftware.clear();
      +  361  12
                           currentCVE = cveId;
       362  
                       }
       363  
       
      -  364  279
                       final String cpeId = rs.getString(2);
      -  365  279
                       final String previous = rs.getString(3);
      -  366  279
                       final Boolean p = previous != null && !previous.isEmpty();
      -  367  279
                       vulnSoftware.put(cpeId, p);
      -  368  279
                   }
      +  364  305
                       final String cpeId = rs.getString(2);
      +  365  305
                       final String previous = rs.getString(3);
      +  366  305
                       final Boolean p = previous != null && !previous.isEmpty();
      +  367  305
                       vulnSoftware.put(cpeId, p);
      +  368  305
                   }
       369  
                   //remember to process the last set of CVE/CPE entries
      -  370  3
                   final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion);
      -  371  3
                   if (matchedCPE != null) {
      +  370  4
                   final Entry<String, Boolean> matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion);
      +  371  4
                   if (matchedCPE != null) {
       372  2
                       final Vulnerability v = getVulnerability(currentCVE);
       373  2
                       v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null);
       374  2
                       vulnerabilities.add(v);
      @@ -622,10 +622,10 @@  377  0
                   throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex);
       378  
               } finally {
      -  379  3
                   DBUtils.closeResultSet(rs);
      -  380  3
                   DBUtils.closeStatement(ps);
      -  381  3
               }
      -  382  3
               return vulnerabilities;
      +  379  4
                   DBUtils.closeResultSet(rs);
      +  380  4
                   DBUtils.closeStatement(ps);
      +  381  4
               }
      +  382  4
               return vulnerabilities;
       383  
           }
       384   @@ -645,7 +645,7 @@  391  
            */
       392   -
           public Vulnerability getVulnerability(String cve) throws DatabaseException {
      +
           public synchronized Vulnerability getVulnerability(String cve) throws DatabaseException {
       393  8
               PreparedStatement psV = null;
       394  8
               PreparedStatement psR = null;
       395  8
               PreparedStatement psS = null;
      @@ -738,7 +738,7 @@  464  
            */
       465   -
           public void updateVulnerability(Vulnerability vuln) throws DatabaseException {
      +
           public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException {
       466  0
               PreparedStatement selectVulnerabilityId = null;
       467  0
               PreparedStatement deleteVulnerability = null;
       468  0
               PreparedStatement deleteReferences = null;
      @@ -959,7 +959,7 @@  640  
            */
       641   -
           public boolean dataExists() {
      +
           public synchronized boolean dataExists() {
       642  2
               Statement cs = null;
       643  2
               ResultSet rs = null;
       644   @@ -1012,7 +1012,7 @@  676  
            */
       677   -
           public void cleanupDatabase() {
      +
           public synchronized void cleanupDatabase() {
       678  0
               PreparedStatement ps = null;
       679  
               try {
      @@ -1065,19 +1065,19 @@
                   DependencyVersion identifiedVersion) {
       708  
       
      -  709  13
               final boolean isVersionTwoADifferentProduct = "apache".equals(vendor) && "struts".equals(product);
      +  709  16
               final boolean isVersionTwoADifferentProduct = "apache".equals(vendor) && "struts".equals(product);
       710  
       
      -  711  13
               final Set<String> majorVersionsAffectingAllPrevious = new HashSet<String>();
      -  712  13
               final boolean matchesAnyPrevious = identifiedVersion == null || "-".equals(identifiedVersion.toString());
      -  713  13
               String majorVersionMatch = null;
      -  714  13
               for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
      -  715  279
                   final DependencyVersion v = parseDependencyVersion(entry.getKey());
      -  716  279
                   if (v == null || "-".equals(v.toString())) { //all versions
      +  711  16
               final Set<String> majorVersionsAffectingAllPrevious = new HashSet<String>();
      +  712  16
               final boolean matchesAnyPrevious = identifiedVersion == null || "-".equals(identifiedVersion.toString());
      +  713  16
               String majorVersionMatch = null;
      +  714  16
               for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
      +  715  305
                   final DependencyVersion v = parseDependencyVersion(entry.getKey());
      +  716  305
                   if (v == null || "-".equals(v.toString())) { //all versions
       717  0
                       return entry;
       718  
                   }
      -  719  279
                   if (entry.getValue()) {
      +  719  305
                   if (entry.getValue()) {
       720  8
                       if (matchesAnyPrevious) {
       721  0
                           return entry;
       722   @@ -1089,24 +1089,24 @@  726  8
                       majorVersionsAffectingAllPrevious.add(v.getVersionParts().get(0));
       727  
                   }
      -  728  279
               }
      -  729  13
               if (matchesAnyPrevious) {
      +  728  305
               }
      +  729  16
               if (matchesAnyPrevious) {
       730  0
                   return null;
       731  
               }
       732  
       
      -  733  13
               final boolean canSkipVersions = majorVersionMatch != null && majorVersionsAffectingAllPrevious.size() > 1;
      +  733  16
               final boolean canSkipVersions = majorVersionMatch != null && majorVersionsAffectingAllPrevious.size() > 1;
       734  
               //yes, we are iterating over this twice. The first time we are skipping versions those that affect all versions
       735  
               //then later we process those that affect all versions. This could be done with sorting...
      -  736  13
               for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
      -  737  237
                   if (!entry.getValue()) {
      -  738  229
                       final DependencyVersion v = parseDependencyVersion(entry.getKey());
      +  736  16
               for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
      +  737  263
                   if (!entry.getValue()) {
      +  738  255
                       final DependencyVersion v = parseDependencyVersion(entry.getKey());
       739  
                       //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this.
      -  740  229
                       if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) {
      +  740  255
                       if (canSkipVersions && !majorVersionMatch.equals(v.getVersionParts().get(0))) {
       741  8
                           continue;
       742  
                       }
      @@ -1114,15 +1114,15 @@
                       //this can't dereference a null 'identifiedVersion' because if it was null we would have exited
       744  
                       //in the above loop or just after loop (if matchesAnyPrevious return null).
      -  745  221
                       if (identifiedVersion.equals(v)) {
      +  745  247
                       if (identifiedVersion.equals(v)) {
       746  8
                           return entry;
       747  
                       }
       748  
                   }
      -  749  221
               }
      -  750  5
               for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
      -  751  56
                   if (entry.getValue()) {
      +  749  247
               }
      +  750  8
               for (Entry<String, Boolean> entry : vulnerableSoftware.entrySet()) {
      +  751  82
                   if (entry.getValue()) {
       752  0
                       final DependencyVersion v = parseDependencyVersion(entry.getKey());
       753  
                       //this can't dereference a null 'majorVersionMatch' as canSkipVersions accounts for this.
      @@ -1143,8 +1143,8 @@
                       }
       764  
                   }
      -  765  56
               }
      -  766  5
               return null;
      +  765  82
               }
      +  766  8
               return null;
       767  
           }
       768   @@ -1165,16 +1165,16 @@
            */
       776  
           private DependencyVersion parseDependencyVersion(String cpeStr) {
      -  777  508
               final VulnerableSoftware cpe = new VulnerableSoftware();
      +  777  560
               final VulnerableSoftware cpe = new VulnerableSoftware();
       778  
               try {
      -  779  508
                   cpe.parseName(cpeStr);
      +  779  560
                   cpe.parseName(cpeStr);
       780  0
               } catch (UnsupportedEncodingException ex) {
       781  
                   //never going to happen.
       782  0
                   LOGGER.trace("", ex);
      -  783  508
               }
      -  784  508
               return parseDependencyVersion(cpe);
      +  783  560
               }
      +  784  560
               return parseDependencyVersion(cpe);
       785  
           }
       786   @@ -1197,22 +1197,22 @@
           private DependencyVersion parseDependencyVersion(VulnerableSoftware cpe) {
       795  
               final DependencyVersion cpeVersion;
      -  796  511
               if (cpe.getVersion() != null && !cpe.getVersion().isEmpty()) {
      +  796  564
               if (cpe.getVersion() != null && !cpe.getVersion().isEmpty()) {
       797  
                   final String versionText;
      -  798  511
                   if (cpe.getUpdate() != null && !cpe.getUpdate().isEmpty()) {
      +  798  564
                   if (cpe.getUpdate() != null && !cpe.getUpdate().isEmpty()) {
       799  113
                       versionText = String.format("%s.%s", cpe.getVersion(), cpe.getUpdate());
       800  
                   } else {
      -  801  398
                       versionText = cpe.getVersion();
      +  801  451
                       versionText = cpe.getVersion();
       802  
                   }
      -  803  511
                   cpeVersion = DependencyVersionUtil.parseVersion(versionText);
      -  804  511
               } else {
      +  803  564
                   cpeVersion = DependencyVersionUtil.parseVersion(versionText);
      +  804  564
               } else {
       805  0
                   cpeVersion = new DependencyVersion("-");
       806  
               }
      -  807  511
               return cpeVersion;
      +  807  564
               return cpeVersion;
       808  
           }
       809   @@ -1228,7 +1228,7 @@  814  
            */
       815   -
           public void deleteUnusedCpe() {
      +
           public synchronized void deleteUnusedCpe() {
       816  0
               PreparedStatement ps = null;
       817  
               try {
      @@ -1264,7 +1264,7 @@  836  
            */
       837   -
           public void addCpe(String cpe, String vendor, String product) {
      +
           public synchronized void addCpe(String cpe, String vendor, String product) {
       838  0
               PreparedStatement ps = null;
       839  
               try {
      @@ -1284,6 +1284,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DatabaseException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DatabaseException.html index 9c3d5e85c..7c07e2d31 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DatabaseException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DatabaseException.html @@ -131,6 +131,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DatabaseProperties.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DatabaseProperties.html index e64d238c4..258405de5 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DatabaseProperties.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DatabaseProperties.html @@ -352,6 +352,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverLoadException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverLoadException.html index 8758dcc93..d777765f0 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverLoadException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverLoadException.html @@ -131,6 +131,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverLoader.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverLoader.html index 04d7c987e..d0f6df8f7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverLoader.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverLoader.html @@ -269,6 +269,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverShim.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverShim.html index 671867816..675a6606b 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverShim.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.nvdcve.DriverShim.html @@ -394,6 +394,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.BaseUpdater.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.BaseUpdater.html index cce113631..c708219a1 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.BaseUpdater.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.BaseUpdater.html @@ -171,6 +171,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.CachedWebDataSource.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.CachedWebDataSource.html index 71cefd94d..57b7a84e5 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.CachedWebDataSource.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.CachedWebDataSource.html @@ -93,6 +93,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.CpeUpdater.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.CpeUpdater.html index f4d4a2c2d..4e113c816 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.CpeUpdater.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.CpeUpdater.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      CpeUpdater
      0%
      0/77
      0%
      0/28
      6.8
      CpeUpdater
      0%
      0/78
      0%
      0/28
      6.8
       
      @@ -110,242 +110,257 @@  46  
        *
       47   -
        * This class is currently unused and if enabled will likely not work on MySQL as the MERGE statement is used.
      +
        * This class is currently unused and if enabled will likely not work on MySQL
       48   -
        *
      +
        * as the MERGE statement is used.
       49   -
        * The CpeUpdater is designed to download the CPE data file from NIST and import the data into the database. However, as this
      -  50   -
        * currently adds no beneficial data, compared to what is in the CPE data contained in the CVE data files, this class is not
      -  51   -
        * currently used. The code is being kept as a future update may utilize more data from the CPE xml files.
      -  52  
        *
      +  50   +
        * The CpeUpdater is designed to download the CPE data file from NIST and import
      +  51   +
        * the data into the database. However, as this currently adds no beneficial
      +  52   +
        * data, compared to what is in the CPE data contained in the CVE data files,
       53   -
        * @author Jeremy Long
      +
        * this class is not currently used. The code is being kept as a future update
       54   -
        */
      -  55  0
       public class CpeUpdater extends BaseUpdater implements CachedWebDataSource {
      +
        * may utilize more data from the CPE XML files.
      +  55   +
        *
       56   -
       
      +
        * @author Jeremy Long
       57   -
           /**
      -  58   -
            * Static logger.
      +
        */
      +  58  0
       public class CpeUpdater extends BaseUpdater implements CachedWebDataSource {
       59   -
            */
      -  60  0
           private static final Logger LOGGER = LoggerFactory.getLogger(CpeUpdater.class);
      +
       
      +  60   +
           /**
       61   -
       
      +
            * Static logger.
       62   -
           @Override
      -  63   -
           public void update() throws UpdateException {
      +
            */
      +  63  0
           private static final Logger LOGGER = LoggerFactory.getLogger(CpeUpdater.class);
       64   +
       
      +  65   +
           @Override
      +  66   +
           public void update() throws UpdateException {
      +  67  
               try {
      -  65  0
                   openDataStores();
      -  66  0
                   if (updateNeeded()) {
      -  67  0
                       LOGGER.info("Updating the Common Platform Enumeration (CPE)");
      -  68  0
                       final File xml = downloadCpe();
      -  69  0
                       final List<Cpe> cpes = processXML(xml);
      -  70  0
                       getCveDB().deleteUnusedCpe();
      -  71  0
                       for (Cpe cpe : cpes) {
      -  72  0
                           getCveDB().addCpe(cpe.getValue(), cpe.getVendor(), cpe.getProduct());
      -  73  0
                       }
      -  74  0
                       final long now = System.currentTimeMillis();
      -  75  0
                       getProperties().save(LAST_CPE_UPDATE, Long.toString(now));
      -  76  0
                       LOGGER.info("CPE update complete");
      -  77   +  68  0
                   openDataStores();
      +  69  0
                   if (updateNeeded()) {
      +  70  0
                       LOGGER.info("Updating the Common Platform Enumeration (CPE)");
      +  71  0
                       final File xml = downloadCpe();
      +  72  0
                       final List<Cpe> cpes = processXML(xml);
      +  73  0
                       getCveDB().deleteUnusedCpe();
      +  74  0
                       for (Cpe cpe : cpes) {
      +  75  0
                           getCveDB().addCpe(cpe.getValue(), cpe.getVendor(), cpe.getProduct());
      +  76  0
                       }
      +  77  0
                       final long now = System.currentTimeMillis();
      +  78  0
                       getProperties().save(LAST_CPE_UPDATE, Long.toString(now));
      +  79  0
                       LOGGER.info("CPE update complete");
      +  80  
                   }
      -  78   +  81  
               } finally {
      -  79  0
                   closeDataStores();
      -  80  0
               }
      -  81  0
           }
      -  82   -
       
      -  83   -
           /**
      -  84   -
            * Downloads the CPE XML file.
      +  82  0
                   closeDataStores();
      +  83  0
               }
      +  84  0
           }
       85   -
            *
      +
       
       86   -
            * @return the file reference to the CPE.xml file
      +
           /**
       87   -
            * @throws UpdateException thrown if there is an issue downloading the XML file
      +
            * Downloads the CPE XML file.
       88   -
            */
      +
            *
       89   -
           private File downloadCpe() throws UpdateException {
      +
            * @return the file reference to the CPE.xml file
       90   -
               File xml;
      +
            * @throws UpdateException thrown if there is an issue downloading the XML
       91   -
               final URL url;
      +
            * file
       92   +
            */
      +  93   +
           private File downloadCpe() throws UpdateException {
      +  94   +
               File xml;
      +  95   +
               final URL url;
      +  96  
               try {
      -  93  0
                   url = new URL(Settings.getString(Settings.KEYS.CPE_URL));
      -  94  0
                   xml = File.createTempFile("cpe", ".xml", Settings.getTempDirectory());
      -  95  0
                   Downloader.fetchFile(url, xml);
      -  96  0
                   if (url.toExternalForm().endsWith(".xml.gz")) {
      -  97  0
                       extractGzip(xml);
      -  98   +  97  0
                   url = new URL(Settings.getString(Settings.KEYS.CPE_URL));
      +  98  0
                   xml = File.createTempFile("cpe", ".xml", Settings.getTempDirectory());
      +  99  0
                   Downloader.fetchFile(url, xml);
      +  100  0
                   if (url.toExternalForm().endsWith(".xml.gz")) {
      +  101  0
                       extractGzip(xml);
      +  102  
                   }
      -  99   +  103  
       
      -  100  0
               } catch (MalformedURLException ex) {
      -  101  0
                   throw new UpdateException("Invalid CPE URL", ex);
      -  102  0
               } catch (DownloadFailedException ex) {
      -  103  0
                   throw new UpdateException("Unable to download CPE XML file", ex);
      -  104  0
               } catch (IOException ex) {
      -  105  0
                   throw new UpdateException("Unable to create temporary file to download CPE", ex);
      -  106  0
               }
      -  107  0
               return xml;
      -  108   -
           }
      -  109   -
       
      -  110   -
           /**
      -  111   -
            * Parses the CPE XML file to return a list of CPE entries.
      +  104  0
               } catch (MalformedURLException ex) {
      +  105  0
                   throw new UpdateException("Invalid CPE URL", ex);
      +  106  0
               } catch (DownloadFailedException ex) {
      +  107  0
                   throw new UpdateException("Unable to download CPE XML file", ex);
      +  108  0
               } catch (IOException ex) {
      +  109  0
                   throw new UpdateException("Unable to create temporary file to download CPE", ex);
      +  110  0
               }
      +  111  0
               return xml;
       112   -
            *
      +
           }
       113   -
            * @param xml the CPE data file
      +
       
       114   -
            * @return the list of CPE entries
      +
           /**
       115   -
            * @throws UpdateException thrown if there is an issue with parsing the XML file
      +
            * Parses the CPE XML file to return a list of CPE entries.
       116   -
            */
      +
            *
       117   -
           private List<Cpe> processXML(final File xml) throws UpdateException {
      +
            * @param xml the CPE data file
       118   +
            * @return the list of CPE entries
      +  119   +
            * @throws UpdateException thrown if there is an issue with parsing the XML
      +  120   +
            * file
      +  121   +
            */
      +  122   +
           private List<Cpe> processXML(final File xml) throws UpdateException {
      +  123  
               try {
      -  119  0
                   final SAXParserFactory factory = SAXParserFactory.newInstance();
      -  120  0
                   final SAXParser saxParser = factory.newSAXParser();
      -  121  0
                   final CPEHandler handler = new CPEHandler();
      -  122  0
                   saxParser.parse(xml, handler);
      -  123  0
                   return handler.getData();
      -  124  0
               } catch (ParserConfigurationException ex) {
      -  125  0
                   throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Issue", ex);
      -  126  0
               } catch (SAXException ex) {
      -  127  0
                   throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Exception", ex);
      -  128  0
               } catch (IOException ex) {
      -  129  0
                   throw new UpdateException("Unable to parse CPE XML file due to IO Failure", ex);
      -  130   -
               }
      -  131   -
           }
      -  132   -
       
      -  133   -
           /**
      -  134   -
            * Checks to find the last time the CPE data was refreshed and if it needs to be updated.
      -  135   -
            *
      +  124  0
                   final SAXParserFactory factory = SAXParserFactory.newInstance();
      +  125  0
                   factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +  126  0
                   final SAXParser saxParser = factory.newSAXParser();
      +  127  0
                   final CPEHandler handler = new CPEHandler();
      +  128  0
                   saxParser.parse(xml, handler);
      +  129  0
                   return handler.getData();
      +  130  0
               } catch (ParserConfigurationException ex) {
      +  131  0
                   throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Issue", ex);
      +  132  0
               } catch (SAXException ex) {
      +  133  0
                   throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Exception", ex);
      +  134  0
               } catch (IOException ex) {
      +  135  0
                   throw new UpdateException("Unable to parse CPE XML file due to IO Failure", ex);
       136   -
            * @return true if the CPE data should be refreshed
      +
               }
       137   -
            */
      -  138   -
           private boolean updateNeeded() {
      -  139  0
               final long now = System.currentTimeMillis();
      -  140  0
               final int days = Settings.getInt(Settings.KEYS.CPE_MODIFIED_VALID_FOR_DAYS, 30);
      -  141  0
               long timestamp = 0;
      -  142  0
               final String ts = getProperties().getProperty(LAST_CPE_UPDATE);
      -  143  0
               if (ts != null && ts.matches("^[0-9]+$")) {
      -  144  0
                   timestamp = Long.parseLong(ts);
      -  145   -
               }
      -  146  0
               return !DateUtil.withinDateRange(timestamp, now, days);
      -  147  
           }
      -  148   +  138  
       
      -  149   +  139  
           /**
      -  150   -
            * Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file specified.
      -  151   +  140   +
            * Checks to find the last time the CPE data was refreshed and if it needs
      +  141   +
            * to be updated.
      +  142  
            *
      -  152   -
            * @param file the archive file
      -  153   -
            * @throws FileNotFoundException thrown if the file does not exist
      -  154   -
            * @throws IOException thrown if there is an error extracting the file.
      -  155   +  143   +
            * @return true if the CPE data should be refreshed
      +  144  
            */
      +  145   +
           private boolean updateNeeded() {
      +  146  0
               final long now = System.currentTimeMillis();
      +  147  0
               final int days = Settings.getInt(Settings.KEYS.CPE_MODIFIED_VALID_FOR_DAYS, 30);
      +  148  0
               long timestamp = 0;
      +  149  0
               final String ts = getProperties().getProperty(LAST_CPE_UPDATE);
      +  150  0
               if (ts != null && ts.matches("^[0-9]+$")) {
      +  151  0
                   timestamp = Long.parseLong(ts);
      +  152   +
               }
      +  153  0
               return !DateUtil.withinDateRange(timestamp, now, days);
      +  154   +
           }
      +  155   +
       
       156   -
           private void extractGzip(File file) throws FileNotFoundException, IOException {
      +
           /**
       157   -
               //TODO - move this to a util class as it is duplicative of (copy of) code in the DownloadTask
      -  158  0
               final String originalPath = file.getPath();
      -  159  0
               final File gzip = new File(originalPath + ".gz");
      -  160  0
               if (gzip.isFile() && !gzip.delete()) {
      -  161  0
                   LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString());
      -  162  0
                   gzip.deleteOnExit();
      +
            * Extracts the file contained in a gzip archive. The extracted file is
      +  158   +
            * placed in the exact same path as the file specified.
      +  159   +
            *
      +  160   +
            * @param file the archive file
      +  161   +
            * @throws FileNotFoundException thrown if the file does not exist
      +  162   +
            * @throws IOException thrown if there is an error extracting the file.
       163   +
            */
      +  164   +
           private void extractGzip(File file) throws FileNotFoundException, IOException {
      +  165   +
               //TODO - move this to a util class as it is duplicative of (copy of) code in the DownloadTask
      +  166  0
               final String originalPath = file.getPath();
      +  167  0
               final File gzip = new File(originalPath + ".gz");
      +  168  0
               if (gzip.isFile() && !gzip.delete()) {
      +  169  0
                   LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString());
      +  170  0
                   gzip.deleteOnExit();
      +  171  
               }
      -  164  0
               if (!file.renameTo(gzip)) {
      -  165  0
                   throw new IOException("Unable to rename '" + file.getPath() + "'");
      -  166   +  172  0
               if (!file.renameTo(gzip)) {
      +  173  0
                   throw new IOException("Unable to rename '" + file.getPath() + "'");
      +  174  
               }
      -  167  0
               final File newfile = new File(originalPath);
      -  168   -
       
      -  169  0
               final byte[] buffer = new byte[4096];
      -  170   -
       
      -  171  0
               GZIPInputStream cin = null;
      -  172  0
               FileOutputStream out = null;
      -  173   -
               try {
      -  174  0
                   cin = new GZIPInputStream(new FileInputStream(gzip));
      -  175  0
                   out = new FileOutputStream(newfile);
      +  175  0
               final File newfile = new File(originalPath);
       176  
       
      -  177   -
                   int len;
      -  178  0
                   while ((len = cin.read(buffer)) > 0) {
      -  179  0
                       out.write(buffer, 0, len);
      -  180   -
                   }
      +  177  0
               final byte[] buffer = new byte[4096];
      +  178   +
       
      +  179  0
               GZIPInputStream cin = null;
      +  180  0
               FileOutputStream out = null;
       181   -
               } finally {
      -  182  0
                   if (cin != null) {
      -  183   -
                       try {
      -  184  0
                           cin.close();
      -  185  0
                       } catch (IOException ex) {
      -  186  0
                           LOGGER.trace("ignore", ex);
      -  187  0
                       }
      +
               try {
      +  182  0
                   cin = new GZIPInputStream(new FileInputStream(gzip));
      +  183  0
                   out = new FileOutputStream(newfile);
      +  184   +
       
      +  185   +
                   int len;
      +  186  0
                   while ((len = cin.read(buffer)) > 0) {
      +  187  0
                       out.write(buffer, 0, len);
       188  
                   }
      -  189  0
                   if (out != null) {
      -  190   +  189   +
               } finally {
      +  190  0
                   if (cin != null) {
      +  191  
                       try {
      -  191  0
                           out.close();
      -  192  0
                       } catch (IOException ex) {
      -  193  0
                           LOGGER.trace("ignore", ex);
      -  194  0
                       }
      -  195   +  192  0
                           cin.close();
      +  193  0
                       } catch (IOException ex) {
      +  194  0
                           LOGGER.trace("ignore", ex);
      +  195  0
                       }
      +  196  
                   }
      -  196  0
                   if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) {
      -  197  0
                       LOGGER.debug("Failed to delete temporary file {}", gzip.toString());
      -  198  0
                       gzip.deleteOnExit();
      -  199   +  197  0
                   if (out != null) {
      +  198   +
                       try {
      +  199  0
                           out.close();
      +  200  0
                       } catch (IOException ex) {
      +  201  0
                           LOGGER.trace("ignore", ex);
      +  202  0
                       }
      +  203  
                   }
      -  200   +  204  0
                   if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) {
      +  205  0
                       LOGGER.debug("Failed to delete temporary file {}", gzip.toString());
      +  206  0
                       gzip.deleteOnExit();
      +  207   +
                   }
      +  208  
               }
      -  201  0
           }
      -  202   +  209  0
           }
      +  210  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.EngineVersionCheck.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.EngineVersionCheck.html index 551d44d1d..7cc77689d 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.EngineVersionCheck.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.EngineVersionCheck.html @@ -235,7 +235,7 @@
                   }
       119  0
               } catch (DatabaseException ex) {
       120  0
                   LOGGER.debug("Database Exception opening databases to retrieve properties", ex);
      -  121  0
                   throw new UpdateException("Error occured updating database properties.");
      +  121  0
                   throw new UpdateException("Error occurred updating database properties.");
       122  0
               } catch (InvalidSettingException ex) {
       123  0
                   LOGGER.debug("Unable to determine if autoupdate is enabled", ex);
       124   @@ -408,6 +408,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.NvdCveUpdater.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.NvdCveUpdater.html index c56aaabc7..403ee1df1 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.NvdCveUpdater.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.NvdCveUpdater.html @@ -550,6 +550,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.UpdateService.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.UpdateService.html index 107f822d3..c2b458d1d 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.UpdateService.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.UpdateService.html @@ -121,6 +121,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.cpe.CPEHandler.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.cpe.CPEHandler.html index 5d743af43..d563767e9 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.cpe.CPEHandler.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.cpe.CPEHandler.html @@ -722,6 +722,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.cpe.Cpe.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.cpe.Cpe.html index 6d4dfa5f6..594950513 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.cpe.Cpe.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.cpe.Cpe.html @@ -251,6 +251,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.exception.InvalidDataException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.exception.InvalidDataException.html index 60fb5c96b..8ca9ac311 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.exception.InvalidDataException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.exception.InvalidDataException.html @@ -115,6 +115,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.exception.UpdateException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.exception.UpdateException.html index 331554243..00a18491b 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.exception.UpdateException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.exception.UpdateException.html @@ -143,6 +143,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.DownloadTask.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.DownloadTask.html index 40a921585..f5265838a 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.DownloadTask.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.DownloadTask.html @@ -499,8 +499,8 @@
       
       287  
                   int len;
      -  288  591
                   while ((len = cin.read(buffer)) > 0) {
      -  289  589
                       out.write(buffer, 0, len);
      +  288  801
                   while ((len = cin.read(buffer)) > 0) {
      +  289  799
                       out.write(buffer, 0, len);
       290  
                   }
       291   @@ -535,6 +535,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCve12Handler.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCve12Handler.html index a2d7bd8a8..0aabbd2f0 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCve12Handler.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCve12Handler.html @@ -451,6 +451,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCve20Handler.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCve20Handler.html index d7f4d6914..b5ca71e7c 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCve20Handler.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCve20Handler.html @@ -866,6 +866,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCveInfo.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCveInfo.html index 32fa3bd14..f0a9780a2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCveInfo.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.NvdCveInfo.html @@ -276,6 +276,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.ProcessTask.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.ProcessTask.html index 5950499ff..32258bea7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.ProcessTask.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.ProcessTask.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      ProcessTask
      0%
      0/53
      N/A
      3.5
      ProcessTask
      0%
      0/54
      N/A
      3.5
       
      @@ -98,244 +98,257 @@  40  
       /**
       41   -
        * A callable task that will process a given set of NVD CVE xml files and update the Cve Database accordingly.
      +
        * A callable task that will process a given set of NVD CVE xml files and update
       42   -
        *
      +
        * the Cve Database accordingly.
       43   -
        * @author Jeremy Long
      +
        *
       44   +
        * @author Jeremy Long
      +  45  
        */
      -  45  0
       public class ProcessTask implements Callable<ProcessTask> {
      -  46   -
       
      +  46  0
       public class ProcessTask implements Callable<ProcessTask> {
       47   -
           /**
      +
       
       48   -
            * The logger.
      +
           /**
       49   +
            * The logger.
      +  50  
            */
      -  50  0
           private static final Logger LOGGER = LoggerFactory.getLogger(ProcessTask.class);
      -  51   -
           /**
      +  51  0
           private static final Logger LOGGER = LoggerFactory.getLogger(ProcessTask.class);
       52   -
            * A field to store any update exceptions that occur during the "call".
      +
           /**
       53   +
            * A field to store any update exceptions that occur during the "call".
      +  54  
            */
      -  54  0
           private UpdateException exception = null;
      -  55   -
       
      +  55  0
           private UpdateException exception = null;
       56   -
           /**
      +
       
       57   -
            * Get the value of exception.
      +
           /**
       58   -
            *
      +
            * Get the value of exception.
       59   -
            * @return the value of exception
      +
            *
       60   -
            */
      +
            * @return the value of exception
       61   +
            */
      +  62  
           public UpdateException getException() {
      -  62  0
               return exception;
      -  63   -
           }
      +  63  0
               return exception;
       64   -
       
      -  65   -
           /**
      -  66   -
            * Set the value of exception.
      -  67   -
            *
      -  68   -
            * @param exception new value of exception
      -  69   -
            */
      -  70   -
           public void setException(UpdateException exception) {
      -  71  0
               this.exception = exception;
      -  72  0
           }
      -  73   -
           /**
      -  74   -
            * A reference to the CveDB.
      -  75   -
            */
      -  76   -
           private final CveDB cveDB;
      -  77   -
           /**
      -  78   -
            * A reference to the callable download task.
      -  79   -
            */
      -  80   -
           private final DownloadTask filePair;
      -  81   -
           /**
      -  82   -
            * A reference to the properties.
      -  83   -
            */
      -  84   -
           private final DatabaseProperties properties;
      -  85   -
           /**
      -  86   -
            * A reference to the global settings object.
      -  87   -
            */
      -  88   -
           private final Settings settings;
      -  89   -
       
      -  90   -
           /**
      -  91   -
            * Constructs a new ProcessTask used to process an NVD CVE update.
      -  92   -
            *
      -  93   -
            * @param cveDB the data store object
      -  94   -
            * @param filePair the download task that contains the URL references to download
      -  95   -
            * @param settings a reference to the global settings object; this is necessary so that when the thread is started the
      -  96   -
            * dependencies have a correct reference to the global settings.
      -  97   -
            */
      -  98  0
           public ProcessTask(final CveDB cveDB, final DownloadTask filePair, Settings settings) {
      -  99  0
               this.cveDB = cveDB;
      -  100  0
               this.filePair = filePair;
      -  101  0
               this.properties = cveDB.getDatabaseProperties();
      -  102  0
               this.settings = settings;
      -  103  0
           }
      -  104   -
       
      -  105   -
           /**
      -  106   -
            * Implements the callable interface.
      -  107   -
            *
      -  108   -
            * @return this object
      -  109   -
            * @throws Exception thrown if there is an exception; note that any UpdateExceptions are simply added to the tasks exception
      -  110   -
            * collection
      -  111   -
            */
      -  112   -
           @Override
      -  113   -
           public ProcessTask call() throws Exception {
      -  114   -
               try {
      -  115  0
                   Settings.setInstance(settings);
      -  116  0
                   processFiles();
      -  117  0
               } catch (UpdateException ex) {
      -  118  0
                   this.exception = ex;
      -  119   -
               } finally {
      -  120  0
                   Settings.cleanup(false);
      -  121  0
               }
      -  122  0
               return this;
      -  123  
           }
      -  124   +  65  
       
      -  125   +  66  
           /**
      -  126   -
            * Imports the NVD CVE XML File into the Lucene Index.
      -  127   +  67   +
            * Set the value of exception.
      +  68  
            *
      -  128   -
            * @param file the file containing the NVD CVE XML
      -  129   -
            * @param oldVersion contains the file containing the NVD CVE XML 1.2
      -  130   -
            * @throws ParserConfigurationException is thrown if there is a parser configuration exception
      -  131   -
            * @throws SAXException is thrown if there is a SAXException
      -  132   -
            * @throws IOException is thrown if there is a IO Exception
      -  133   -
            * @throws SQLException is thrown if there is a SQL exception
      -  134   -
            * @throws DatabaseException is thrown if there is a database exception
      -  135   -
            * @throws ClassNotFoundException thrown if the h2 database driver cannot be loaded
      -  136   +  69   +
            * @param exception new value of exception
      +  70  
            */
      +  71   +
           public void setException(UpdateException exception) {
      +  72  0
               this.exception = exception;
      +  73  0
           }
      +  74   +
           /**
      +  75   +
            * A reference to the CveDB.
      +  76   +
            */
      +  77   +
           private final CveDB cveDB;
      +  78   +
           /**
      +  79   +
            * A reference to the callable download task.
      +  80   +
            */
      +  81   +
           private final DownloadTask filePair;
      +  82   +
           /**
      +  83   +
            * A reference to the properties.
      +  84   +
            */
      +  85   +
           private final DatabaseProperties properties;
      +  86   +
           /**
      +  87   +
            * A reference to the global settings object.
      +  88   +
            */
      +  89   +
           private final Settings settings;
      +  90   +
       
      +  91   +
           /**
      +  92   +
            * Constructs a new ProcessTask used to process an NVD CVE update.
      +  93   +
            *
      +  94   +
            * @param cveDB the data store object
      +  95   +
            * @param filePair the download task that contains the URL references to
      +  96   +
            * download
      +  97   +
            * @param settings a reference to the global settings object; this is
      +  98   +
            * necessary so that when the thread is started the dependencies have a
      +  99   +
            * correct reference to the global settings.
      +  100   +
            */
      +  101  0
           public ProcessTask(final CveDB cveDB, final DownloadTask filePair, Settings settings) {
      +  102  0
               this.cveDB = cveDB;
      +  103  0
               this.filePair = filePair;
      +  104  0
               this.properties = cveDB.getDatabaseProperties();
      +  105  0
               this.settings = settings;
      +  106  0
           }
      +  107   +
       
      +  108   +
           /**
      +  109   +
            * Implements the callable interface.
      +  110   +
            *
      +  111   +
            * @return this object
      +  112   +
            * @throws Exception thrown if there is an exception; note that any
      +  113   +
            * UpdateExceptions are simply added to the tasks exception collection
      +  114   +
            */
      +  115   +
           @Override
      +  116   +
           public ProcessTask call() throws Exception {
      +  117   +
               try {
      +  118  0
                   Settings.setInstance(settings);
      +  119  0
                   processFiles();
      +  120  0
               } catch (UpdateException ex) {
      +  121  0
                   this.exception = ex;
      +  122   +
               } finally {
      +  123  0
                   Settings.cleanup(false);
      +  124  0
               }
      +  125  0
               return this;
      +  126   +
           }
      +  127   +
       
      +  128   +
           /**
      +  129   +
            * Imports the NVD CVE XML File into the Lucene Index.
      +  130   +
            *
      +  131   +
            * @param file the file containing the NVD CVE XML
      +  132   +
            * @param oldVersion contains the file containing the NVD CVE XML 1.2
      +  133   +
            * @throws ParserConfigurationException is thrown if there is a parser
      +  134   +
            * configuration exception
      +  135   +
            * @throws SAXException is thrown if there is a SAXException
      +  136   +
            * @throws IOException is thrown if there is a IO Exception
       137   -
           protected void importXML(File file, File oldVersion) throws ParserConfigurationException,
      +
            * @throws SQLException is thrown if there is a SQL exception
       138   -
                   SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException {
      +
            * @throws DatabaseException is thrown if there is a database exception
       139   -
       
      -  140  0
               final SAXParserFactory factory = SAXParserFactory.newInstance();
      -  141  0
               final SAXParser saxParser = factory.newSAXParser();
      +
            * @throws ClassNotFoundException thrown if the h2 database driver cannot be
      +  140   +
            * loaded
      +  141   +
            */
       142   +
           protected void importXML(File file, File oldVersion) throws ParserConfigurationException,
      +  143   +
                   SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException {
      +  144  
       
      -  143  0
               final NvdCve12Handler cve12Handler = new NvdCve12Handler();
      -  144  0
               saxParser.parse(oldVersion, cve12Handler);
      -  145  0
               final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities();
      -  146   +  145  0
               final SAXParserFactory factory = SAXParserFactory.newInstance();
      +  146  0
               factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +  147  0
               final SAXParser saxParser = factory.newSAXParser();
      +  148  
       
      -  147  0
               final NvdCve20Handler cve20Handler = new NvdCve20Handler();
      -  148  0
               cve20Handler.setCveDB(cveDB);
      -  149  0
               cve20Handler.setPrevVersionVulnMap(prevVersionVulnMap);
      -  150  0
               saxParser.parse(file, cve20Handler);
      -  151  0
           }
      +  149  0
               final NvdCve12Handler cve12Handler = new NvdCve12Handler();
      +  150  0
               saxParser.parse(oldVersion, cve12Handler);
      +  151  0
               final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities();
       152  
       
      -  153   -
           /**
      -  154   -
            * Processes the NVD CVE XML file and imports the data into the DB.
      -  155   -
            *
      -  156   -
            * @throws UpdateException thrown if there is an error loading the data into the database
      -  157   -
            */
      +  153  0
               final NvdCve20Handler cve20Handler = new NvdCve20Handler();
      +  154  0
               cve20Handler.setCveDB(cveDB);
      +  155  0
               cve20Handler.setPrevVersionVulnMap(prevVersionVulnMap);
      +  156  0
               saxParser.parse(file, cve20Handler);
      +  157  0
           }
       158   -
           private void processFiles() throws UpdateException {
      -  159  0
               LOGGER.info("Processing Started for NVD CVE - {}", filePair.getNvdCveInfo().getId());
      -  160  0
               final long startProcessing = System.currentTimeMillis();
      +
       
      +  159   +
           /**
      +  160   +
            * Processes the NVD CVE XML file and imports the data into the DB.
       161   +
            *
      +  162   +
            * @throws UpdateException thrown if there is an error loading the data into
      +  163   +
            * the database
      +  164   +
            */
      +  165   +
           private void processFiles() throws UpdateException {
      +  166  0
               LOGGER.info("Processing Started for NVD CVE - {}", filePair.getNvdCveInfo().getId());
      +  167  0
               final long startProcessing = System.currentTimeMillis();
      +  168  
               try {
      -  162  0
                   importXML(filePair.getFirst(), filePair.getSecond());
      -  163  0
                   cveDB.commit();
      -  164  0
                   properties.save(filePair.getNvdCveInfo());
      -  165  0
               } catch (FileNotFoundException ex) {
      -  166  0
                   throw new UpdateException(ex);
      -  167  0
               } catch (ParserConfigurationException ex) {
      -  168  0
                   throw new UpdateException(ex);
      -  169  0
               } catch (SAXException ex) {
      -  170  0
                   throw new UpdateException(ex);
      -  171  0
               } catch (IOException ex) {
      -  172  0
                   throw new UpdateException(ex);
      -  173  0
               } catch (SQLException ex) {
      -  174  0
                   throw new UpdateException(ex);
      -  175  0
               } catch (DatabaseException ex) {
      -  176  0
                   throw new UpdateException(ex);
      -  177  0
               } catch (ClassNotFoundException ex) {
      -  178  0
                   throw new UpdateException(ex);
      -  179   +  169  0
                   importXML(filePair.getFirst(), filePair.getSecond());
      +  170  0
                   cveDB.commit();
      +  171  0
                   properties.save(filePair.getNvdCveInfo());
      +  172  0
               } catch (FileNotFoundException ex) {
      +  173  0
                   throw new UpdateException(ex);
      +  174  0
               } catch (ParserConfigurationException ex) {
      +  175  0
                   throw new UpdateException(ex);
      +  176  0
               } catch (SAXException ex) {
      +  177  0
                   throw new UpdateException(ex);
      +  178  0
               } catch (IOException ex) {
      +  179  0
                   throw new UpdateException(ex);
      +  180  0
               } catch (SQLException ex) {
      +  181  0
                   throw new UpdateException(ex);
      +  182  0
               } catch (DatabaseException ex) {
      +  183  0
                   throw new UpdateException(ex);
      +  184  0
               } catch (ClassNotFoundException ex) {
      +  185  0
                   throw new UpdateException(ex);
      +  186  
               } finally {
      -  180  0
                   filePair.cleanup();
      -  181  0
               }
      -  182  0
               LOGGER.info("Processing Complete for NVD CVE - {}  ({} ms)", filePair.getNvdCveInfo().getId(),
      -  183  0
                   System.currentTimeMillis() - startProcessing);
      -  184  0
           }
      -  185   +  187  0
                   filePair.cleanup();
      +  188  0
               }
      +  189  0
               LOGGER.info("Processing Complete for NVD CVE - {}  ({} ms)", filePair.getNvdCveInfo().getId(),
      +  190  0
                       System.currentTimeMillis() - startProcessing);
      +  191  0
           }
      +  192  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.UpdateableNvdCve.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.UpdateableNvdCve.html index 958e30ad4..152281de7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.UpdateableNvdCve.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.data.update.nvd.UpdateableNvdCve.html @@ -369,6 +369,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Confidence.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Confidence.html index cf0421329..729e7b8d9 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Confidence.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Confidence.html @@ -65,7 +65,7 @@
        * @author Jeremy Long
       24  
        */
      -  25  95
       public enum Confidence {
      +  25  96
       public enum Confidence {
       26  
       
       27   @@ -100,6 +100,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Dependency.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Dependency.html index d37592203..3299c4850 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Dependency.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Dependency.html @@ -266,15 +266,15 @@
            * Constructs a new Dependency object.
       127  
            */
      -  128  91
           public Dependency() {
      -  129  91
               vendorEvidence = new EvidenceCollection();
      -  130  91
               productEvidence = new EvidenceCollection();
      -  131  91
               versionEvidence = new EvidenceCollection();
      -  132  91
               identifiers = new TreeSet<Identifier>();
      -  133  91
               vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
      -  134  91
               suppressedIdentifiers = new TreeSet<Identifier>();
      -  135  91
               suppressedVulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
      -  136  91
           }
      +  128  94
           public Dependency() {
      +  129  94
               vendorEvidence = new EvidenceCollection();
      +  130  94
               productEvidence = new EvidenceCollection();
      +  131  94
               versionEvidence = new EvidenceCollection();
      +  132  94
               identifiers = new TreeSet<Identifier>();
      +  133  94
               vulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
      +  134  94
               suppressedIdentifiers = new TreeSet<Identifier>();
      +  135  94
               suppressedVulnerabilities = new TreeSet<Vulnerability>(new VulnerabilityComparator());
      +  136  94
           }
       137  
       
       138   @@ -289,13 +289,13 @@
            */
       143  
           public Dependency(File file) {
      -  144  70
               this();
      -  145  70
               this.actualFilePath = file.getAbsolutePath();
      -  146  70
               this.filePath = this.actualFilePath;
      -  147  70
               this.fileName = file.getName();
      -  148  70
               this.packagePath = filePath;
      -  149  70
               determineHashes(file);
      -  150  70
           }
      +  144  73
               this();
      +  145  73
               this.actualFilePath = file.getAbsolutePath();
      +  146  73
               this.filePath = this.actualFilePath;
      +  147  73
               this.fileName = file.getName();
      +  148  73
               this.packagePath = filePath;
      +  149  73
               determineHashes(file);
      +  150  73
           }
       151  
       
       152   @@ -310,7 +310,7 @@
            */
       157  
           public String getFileName() {
      -  158  74
               return this.fileName;
      +  158  76
               return this.fileName;
       159  
           }
       160   @@ -387,7 +387,7 @@
            */
       200  
           public String getActualFilePath() {
      -  201  69
               return this.actualFilePath;
      +  201  73
               return this.actualFilePath;
       202  
           }
       203   @@ -404,7 +404,7 @@
            */
       209  
           public File getActualFile() {
      -  210  144
               return new File(this.actualFilePath);
      +  210  142
               return new File(this.actualFilePath);
       211  
           }
       212   @@ -435,7 +435,7 @@
            * The file name to display in reports.
       227  
            */
      -  228  91
           private String displayName = null;
      +  228  94
           private String displayName = null;
       229  
       
       230   @@ -533,8 +533,8 @@
            */
       280  
           public void setMd5sum(String md5sum) {
      -  281  71
               this.md5sum = md5sum;
      -  282  71
           }
      +  281  74
               this.md5sum = md5sum;
      +  282  74
           }
       283  
       
       284   @@ -549,7 +549,7 @@
            */
       289  
           public String getSha1sum() {
      -  290  13
               return this.sha1sum;
      +  290  24
               return this.sha1sum;
       291  
           }
       292   @@ -566,8 +566,8 @@
            */
       298  
           public void setSha1sum(String sha1sum) {
      -  299  109
               this.sha1sum = sha1sum;
      -  300  109
           }
      +  299  112
               this.sha1sum = sha1sum;
      +  300  112
           }
       301  
       
       302   @@ -582,7 +582,7 @@
            */
       307  
           public Set<Identifier> getIdentifiers() {
      -  308  468
               return this.identifiers;
      +  308  491
               return this.identifiers;
       309  
           }
       310   @@ -719,8 +719,8 @@
            */
       391  
           public void addIdentifier(Identifier identifier) {
      -  392  3
               this.identifiers.add(identifier);
      -  393  3
           }
      +  392  4
               this.identifiers.add(identifier);
      +  393  4
           }
       394  
       
       395   @@ -921,7 +921,7 @@
            */
       500  
           public EvidenceCollection getProductEvidence() {
      -  501  212
               return this.productEvidence;
      +  501  213
               return this.productEvidence;
       502  
           }
       503   @@ -938,7 +938,7 @@
            */
       509  
           public EvidenceCollection getVersionEvidence() {
      -  510  110
               return this.versionEvidence;
      +  510  114
               return this.versionEvidence;
       511  
           }
       512   @@ -1051,7 +1051,7 @@
            */
       569  
           public SortedSet<Vulnerability> getVulnerabilities() {
      -  570  14
               return vulnerabilities;
      +  570  15
               return vulnerabilities;
       571  
           }
       572   @@ -1084,22 +1084,22 @@
            */
       587  
           private void determineHashes(File file) {
      -  588  70
               String md5 = null;
      -  589  70
               String sha1 = null;
      +  588  73
               String md5 = null;
      +  589  73
               String sha1 = null;
       590  
               try {
      -  591  70
                   md5 = Checksum.getMD5Checksum(file);
      -  592  70
                   sha1 = Checksum.getSHA1Checksum(file);
      +  591  73
                   md5 = Checksum.getMD5Checksum(file);
      +  592  73
                   sha1 = Checksum.getSHA1Checksum(file);
       593  0
               } catch (IOException ex) {
       594  0
                   LOGGER.warn("Unable to read '{}' to determine hashes.", file.getName());
       595  0
                   LOGGER.debug("", ex);
       596  0
               } catch (NoSuchAlgorithmException ex) {
       597  0
                   LOGGER.warn("Unable to use MD5 of SHA1 checksums.");
       598  0
                   LOGGER.debug("", ex);
      -  599  70
               }
      -  600  70
               this.setMd5sum(md5);
      -  601  70
               this.setSha1sum(sha1);
      -  602  70
           }
      +  599  73
               }
      +  600  73
               this.setMd5sum(md5);
      +  601  73
               this.setSha1sum(sha1);
      +  602  73
           }
       603  
       
       604   @@ -1124,7 +1124,7 @@
            * A collection of related dependencies.
       615  
            */
      -  616  91
           private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
      +  616  94
           private Set<Dependency> relatedDependencies = new TreeSet<Dependency>();
       617  
       
       618   @@ -1154,7 +1154,7 @@
            * A list of projects that reference this dependency.
       631  
            */
      -  632  91
           private Set<String> projectReferences = new HashSet<String>();
      +  632  94
           private Set<String> projectReferences = new HashSet<String>();
       633  
       
       634   @@ -1279,7 +1279,7 @@
            * A list of available versions.
       703  
            */
      -  704  91
           private List<String> availableVersions = new ArrayList<String>();
      +  704  94
           private List<String> availableVersions = new ArrayList<String>();
       705  
       
       706   @@ -1413,24 +1413,24 @@
           @Override
       784  
           public int hashCode() {
      -  785  216
               return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER)
      -  786  108
                       .append(actualFilePath)
      -  787  108
                       .append(filePath)
      -  788  108
                       .append(fileName)
      -  789  108
                       .append(md5sum)
      -  790  108
                       .append(sha1sum)
      -  791  108
                       .append(identifiers)
      -  792  108
                       .append(vendorEvidence)
      -  793  108
                       .append(productEvidence)
      -  794  108
                       .append(versionEvidence)
      -  795  108
                       .append(description)
      -  796  108
                       .append(license)
      -  797  108
                       .append(vulnerabilities)
      +  785  12
               return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER)
      +  786  6
                       .append(actualFilePath)
      +  787  6
                       .append(filePath)
      +  788  6
                       .append(fileName)
      +  789  6
                       .append(md5sum)
      +  790  6
                       .append(sha1sum)
      +  791  6
                       .append(identifiers)
      +  792  6
                       .append(vendorEvidence)
      +  793  6
                       .append(productEvidence)
      +  794  6
                       .append(versionEvidence)
      +  795  6
                       .append(description)
      +  796  6
                       .append(license)
      +  797  6
                       .append(vulnerabilities)
       798  
                       //.append(relatedDependencies)
      -  799  108
                       .append(projectReferences)
      -  800  108
                       .append(availableVersions)
      -  801  108
                       .toHashCode();
      +  799  6
                       .append(projectReferences)
      +  800  6
                       .append(availableVersions)
      +  801  6
                       .toHashCode();
       802  
           }
       803   @@ -1460,6 +1460,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Evidence.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Evidence.html index 4fcf5409b..0b2171e37 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Evidence.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Evidence.html @@ -77,7 +77,7 @@
        * @author Jeremy Long
       30  
        */
      -  31  692
       public class Evidence implements Serializable, Comparable<Evidence> {
      +  31  691
       public class Evidence implements Serializable, Comparable<Evidence> {
       32  
       
       33   @@ -125,11 +125,11 @@  55  
            *
       56   -
            * @param source     the source of the evidence.
      +
            * @param source the source of the evidence.
       57   -
            * @param name       the name of the evidence.
      +
            * @param name the name of the evidence.
       58   -
            * @param value      the value of the evidence.
      +
            * @param value the value of the evidence.
       59  
            * @param confidence the confidence of the evidence.
       60   @@ -250,8 +250,8 @@
            */
       124  
           public String getValue() {
      -  125  406
               used = true;
      -  126  406
               return value;
      +  125  451
               used = true;
      +  126  451
               return value;
       127  
           }
       128   @@ -259,285 +259,303 @@  129  
           /**
       130   -
            * Get the value of value. If setUsed is set to false this call to get will not mark the evidence as used.
      +
            * Get the value of value. If setUsed is set to false this call to get will
       131   -
            *
      +
            * not mark the evidence as used.
       132   -
            * @param setUsed whether or not this call to getValue should cause the used flag to be updated
      +
            *
       133   -
            * @return the value of value
      +
            * @param setUsed whether or not this call to getValue should cause the used
       134   -
            */
      +
            * flag to be updated
       135   +
            * @return the value of value
      +  136   +
            */
      +  137  
           public String getValue(Boolean setUsed) {
      -  136  50
               used = used || setUsed;
      -  137  50
               return value;
      -  138   -
           }
      -  139   -
       
      +  138  49
               used = used || setUsed;
      +  139  49
               return value;
       140   -
           /**
      +
           }
       141   -
            * Set the value of value.
      +
       
       142   -
            *
      +
           /**
       143   -
            * @param value new value of value
      +
            * Set the value of value.
       144   -
            */
      +
            *
       145   +
            * @param value new value of value
      +  146   +
            */
      +  147  
           public void setValue(String value) {
      -  146  0
               this.value = value;
      -  147  0
           }
      -  148   -
       
      -  149   -
           /**
      +  148  0
               this.value = value;
      +  149  0
           }
       150   -
            * A value indicating if the Evidence has been "used" (aka read).
      +
       
       151   -
            */
      +
           /**
       152   -
           private boolean used;
      +
            * A value indicating if the Evidence has been "used" (aka read).
       153   -
       
      +
            */
       154   -
           /**
      +
           private boolean used;
       155   -
            * Get the value of used.
      +
       
       156   -
            *
      +
           /**
       157   -
            * @return the value of used
      +
            * Get the value of used.
       158   -
            */
      +
            *
       159   -
           public boolean isUsed() {
      -  160  340
               return used;
      +
            * @return the value of used
      +  160   +
            */
       161   -
           }
      -  162   -
       
      +
           public boolean isUsed() {
      +  162  390
               return used;
       163   -
           /**
      +
           }
       164   -
            * Set the value of used.
      +
       
       165   -
            *
      +
           /**
       166   -
            * @param used new value of used
      +
            * Set the value of used.
       167   -
            */
      +
            *
       168   +
            * @param used new value of used
      +  169   +
            */
      +  170  
           public void setUsed(boolean used) {
      -  169  0
               this.used = used;
      -  170  0
           }
      -  171   -
       
      -  172   -
           /**
      +  171  0
               this.used = used;
      +  172  0
           }
       173   -
            * The confidence level for the evidence.
      +
       
       174   -
            */
      +
           /**
       175   -
           private Confidence confidence;
      +
            * The confidence level for the evidence.
       176   -
       
      +
            */
       177   -
           /**
      +
           private Confidence confidence;
       178   -
            * Get the value of confidence.
      +
       
       179   -
            *
      +
           /**
       180   -
            * @return the value of confidence
      +
            * Get the value of confidence.
       181   -
            */
      +
            *
       182   -
           public Confidence getConfidence() {
      -  183  240
               return confidence;
      +
            * @return the value of confidence
      +  183   +
            */
       184   -
           }
      -  185   -
       
      +
           public Confidence getConfidence() {
      +  185  256
               return confidence;
       186   -
           /**
      -  187   -
            * Set the value of confidence.
      -  188   -
            *
      -  189   -
            * @param confidence new value of confidence
      -  190   -
            */
      -  191   -
           public void setConfidence(Confidence confidence) {
      -  192  0
               this.confidence = confidence;
      -  193  0
           }
      -  194   -
       
      -  195   -
           /**
      -  196   -
            * Implements the hashCode for Evidence.
      -  197   -
            *
      -  198   -
            * @return hash code.
      -  199   -
            */
      -  200   -
           @Override
      -  201   -
           public int hashCode() {
      -  202  12
               return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER)
      -  203  6
                   .append(StringUtils.lowerCase(name))
      -  204  6
                   .append(StringUtils.lowerCase(source))
      -  205  6
                   .append(StringUtils.lowerCase(value))
      -  206  6
                   .append(confidence)
      -  207  6
                   .toHashCode();
      -  208  
           }
      -  209   +  187  
       
      -  210   +  188  
           /**
      -  211   -
            * Implements equals for Evidence.
      -  212   +  189   +
            * Set the value of confidence.
      +  190  
            *
      -  213   -
            * @param that an object to check the equality of.
      -  214   -
            * @return whether the two objects are equal.
      -  215   +  191   +
            * @param confidence new value of confidence
      +  192  
            */
      -  216   +  193   +
           public void setConfidence(Confidence confidence) {
      +  194  0
               this.confidence = confidence;
      +  195  0
           }
      +  196   +
       
      +  197   +
           /**
      +  198   +
            * Implements the hashCode for Evidence.
      +  199   +
            *
      +  200   +
            * @return hash code.
      +  201   +
            */
      +  202  
           @Override
      +  203   +
           public int hashCode() {
      +  204  12
               return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER)
      +  205  6
                       .append(StringUtils.lowerCase(name))
      +  206  6
                       .append(StringUtils.lowerCase(source))
      +  207  6
                       .append(StringUtils.lowerCase(value))
      +  208  6
                       .append(confidence)
      +  209  6
                       .toHashCode();
      +  210   +
           }
      +  211   +
       
      +  212   +
           /**
      +  213   +
            * Implements equals for Evidence.
      +  214   +
            *
      +  215   +
            * @param that an object to check the equality of.
      +  216   +
            * @return whether the two objects are equal.
       217   -
           public boolean equals(Object that) {
      -  218  10
               if (this == that) {
      -  219  0
                   return true;
      +
            */
      +  218   +
           @SuppressWarnings("deprecation")
      +  219   +
           @Override
       220   -
               }
      -  221  10
               if (!(that instanceof Evidence)) {
      -  222  0
                   return false;
      +
           public boolean equals(Object that) {
      +  221  10
               if (this == that) {
      +  222  0
                   return true;
       223  
               }
      -  224  10
               final Evidence e = (Evidence) that;
      -  225   +  224  10
               if (!(that instanceof Evidence)) {
      +  225  0
                   return false;
      +  226   +
               }
      +  227  10
               final Evidence e = (Evidence) that;
      +  228  
       
      -  226  20
               return StringUtils.equalsIgnoreCase(name, e.name)
      -  227  2
                       && StringUtils.equalsIgnoreCase(source, e.source)
      -  228  2
                       && StringUtils.equalsIgnoreCase(value, e.value)
      -  229  2
                       && ObjectUtils.equals(confidence, e.confidence);
      +  229   +
               //TODO the call to ObjectUtils.equals needs to be replaced when we
       230   -
           }
      -  231   -
       
      -  232   -
           /**
      -  233   -
            * Implementation of the comparable interface.
      -  234   -
            *
      +
               //stop supporting Jenkins 1.6 requirement.
      +  231  20
               return StringUtils.equalsIgnoreCase(name, e.name)
      +  232  2
                       && StringUtils.equalsIgnoreCase(source, e.source)
      +  233  2
                       && StringUtils.equalsIgnoreCase(value, e.value)
      +  234  2
                       && ObjectUtils.equals(confidence, e.confidence);
       235   -
            * @param o the evidence being compared
      +
           }
       236   -
            * @return an integer indicating the ordering of the two objects
      +
       
       237   -
            */
      +
           /**
       238   -
           @Override
      +
            * Implementation of the comparable interface.
       239   -
           public int compareTo(Evidence o) {
      -  240  702
               if (o == null) {
      -  241  0
                   return 1;
      +
            *
      +  240   +
            * @param o the evidence being compared
      +  241   +
            * @return an integer indicating the ordering of the two objects
       242   -
               }
      -  243  702
               if (StringUtils.equalsIgnoreCase(source, o.source)) {
      -  244  451
                   if (StringUtils.equalsIgnoreCase(name, o.name)) {
      -  245  240
                       if (StringUtils.equalsIgnoreCase(value, o.value)) {
      -  246  215
                           if (ObjectUtils.equals(confidence, o.confidence)) {
      -  247  213
                               return 0; //they are equal
      -  248   -
                           } else {
      -  249  2
                               return ObjectUtils.compare(confidence, o.confidence);
      -  250   -
                           }
      -  251   -
                       } else {
      -  252  25
                           return compareToIgnoreCaseWithNullCheck(value, o.value);
      -  253   -
                       }
      -  254   -
                   } else {
      -  255  211
                       return compareToIgnoreCaseWithNullCheck(name, o.name);
      -  256   -
                   }
      -  257   -
               } else {
      -  258  251
                   return compareToIgnoreCaseWithNullCheck(source, o.source);
      -  259   -
               }
      -  260   -
           }
      -  261   -
       
      -  262   -
           /**
      -  263   -
            * Wrapper around {@link java.lang.String#compareToIgnoreCase(java.lang.String) String.compareToIgnoreCase} with an
      -  264   -
            * exhaustive, possibly duplicative, check against nulls.
      -  265   -
            *
      -  266   -
            * @param me    the value to be compared
      -  267   -
            * @param other the other value to be compared
      -  268   -
            * @return true if the values are equal; otherwise false
      -  269  
            */
      -  270   -
           private int compareToIgnoreCaseWithNullCheck(String me, String other) {
      -  271  487
               if (me == null && other == null) {
      -  272  0
                   return 0;
      -  273  487
               } else if (me == null) {
      -  274  0
                   return -1; //the other string is greater then me
      -  275  487
               } else if (other == null) {
      -  276  0
                   return 1; //me is greater then the other string
      -  277   -
               }
      -  278  487
               return me.compareToIgnoreCase(other);
      -  279   -
           }
      -  280   -
       
      -  281   -
           /**
      -  282   -
            * Standard toString() implementation.
      -  283   -
            *
      -  284   -
            * @return the string representation of the object
      -  285   -
            */
      -  286   +  243   +
           @SuppressWarnings("deprecation")
      +  244  
           @Override
      -  287   -
           public String toString() {
      -  288  0
               return "Evidence{" + "name=" + name + ", source=" + source + ", value=" + value + ", confidence=" + confidence + '}';
      -  289   +  245   +
           public int compareTo(Evidence o) {
      +  246  702
               if (o == null) {
      +  247  0
                   return 1;
      +  248   +
               }
      +  249  702
               if (StringUtils.equalsIgnoreCase(source, o.source)) {
      +  250  451
                   if (StringUtils.equalsIgnoreCase(name, o.name)) {
      +  251  240
                       if (StringUtils.equalsIgnoreCase(value, o.value)) {
      +  252   +
                           //TODO the call to ObjectUtils.equals needs to be replaced when we
      +  253   +
                           //stop supporting Jenkins 1.6 requirement.
      +  254  215
                           if (ObjectUtils.equals(confidence, o.confidence)) {
      +  255  213
                               return 0; //they are equal
      +  256   +
                           } else {
      +  257  2
                               return ObjectUtils.compare(confidence, o.confidence);
      +  258   +
                           }
      +  259   +
                       } else {
      +  260  25
                           return compareToIgnoreCaseWithNullCheck(value, o.value);
      +  261   +
                       }
      +  262   +
                   } else {
      +  263  211
                       return compareToIgnoreCaseWithNullCheck(name, o.name);
      +  264   +
                   }
      +  265   +
               } else {
      +  266  251
                   return compareToIgnoreCaseWithNullCheck(source, o.source);
      +  267   +
               }
      +  268  
           }
      +  269   +
       
      +  270   +
           /**
      +  271   +
            * Wrapper around
      +  272   +
            * {@link java.lang.String#compareToIgnoreCase(java.lang.String) String.compareToIgnoreCase}
      +  273   +
            * with an exhaustive, possibly duplicative, check against nulls.
      +  274   +
            *
      +  275   +
            * @param me the value to be compared
      +  276   +
            * @param other the other value to be compared
      +  277   +
            * @return true if the values are equal; otherwise false
      +  278   +
            */
      +  279   +
           private int compareToIgnoreCaseWithNullCheck(String me, String other) {
      +  280  486
               if (me == null && other == null) {
      +  281  0
                   return 0;
      +  282  487
               } else if (me == null) {
      +  283  0
                   return -1; //the other string is greater then me
      +  284  487
               } else if (other == null) {
      +  285  0
                   return 1; //me is greater then the other string
      +  286   +
               }
      +  287  486
               return me.compareToIgnoreCase(other);
      +  288   +
           }
      +  289   +
       
       290   +
           /**
      +  291   +
            * Standard toString() implementation.
      +  292   +
            *
      +  293   +
            * @return the string representation of the object
      +  294   +
            */
      +  295   +
           @Override
      +  296   +
           public String toString() {
      +  297  0
               return "Evidence{" + "name=" + name + ", source=" + source + ", value=" + value + ", confidence=" + confidence + '}';
      +  298   +
           }
      +  299  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.EvidenceCollection.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.EvidenceCollection.html index 53b9e1374..fc98c1f92 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.EvidenceCollection.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.EvidenceCollection.html @@ -125,12 +125,12 @@
            * Used to iterate over highest confidence evidence contained in the collection.
       52  
            */
      -  53  22
           private static final Filter<Evidence> HIGHEST_CONFIDENCE = new Filter<Evidence>() {
      +  53  26
           private static final Filter<Evidence> HIGHEST_CONFIDENCE = new Filter<Evidence>() {
       54  
               @Override
       55  
               public boolean passes(Evidence evidence) {
      -  56  21
                   return evidence.getConfidence() == Confidence.HIGHEST;
      +  56  25
                   return evidence.getConfidence() == Confidence.HIGHEST;
       57  
               }
       58   @@ -141,12 +141,12 @@
            * Used to iterate over high confidence evidence contained in the collection.
       61  
            */
      -  62  61
           private static final Filter<Evidence> HIGH_CONFIDENCE = new Filter<Evidence>() {
      +  62  65
           private static final Filter<Evidence> HIGH_CONFIDENCE = new Filter<Evidence>() {
       63  
               @Override
       64  
               public boolean passes(Evidence evidence) {
      -  65  60
                   return evidence.getConfidence() == Confidence.HIGH;
      +  65  64
                   return evidence.getConfidence() == Confidence.HIGH;
       66  
               }
       67   @@ -157,12 +157,12 @@
            * Used to iterate over medium confidence evidence contained in the collection.
       70  
            */
      -  71  37
           private static final Filter<Evidence> MEDIUM_CONFIDENCE = new Filter<Evidence>() {
      +  71  41
           private static final Filter<Evidence> MEDIUM_CONFIDENCE = new Filter<Evidence>() {
       72  
               @Override
       73  
               public boolean passes(Evidence evidence) {
      -  74  36
                   return evidence.getConfidence() == Confidence.MEDIUM;
      +  74  40
                   return evidence.getConfidence() == Confidence.MEDIUM;
       75  
               }
       76   @@ -173,12 +173,12 @@
            * Used to iterate over low confidence evidence contained in the collection.
       79  
            */
      -  80  40
           private static final Filter<Evidence> LOW_CONFIDENCE = new Filter<Evidence>() {
      +  80  44
           private static final Filter<Evidence> LOW_CONFIDENCE = new Filter<Evidence>() {
       81  
               @Override
       82  
               public boolean passes(Evidence evidence) {
      -  83  39
                   return evidence.getConfidence() == Confidence.LOW;
      +  83  43
                   return evidence.getConfidence() == Confidence.LOW;
       84  
               }
       85   @@ -189,12 +189,12 @@
            * Used to iterate over evidence that has was used (aka read) from the collection.
       88  
            */
      -  89  339
           private static final Filter<Evidence> EVIDENCE_USED = new Filter<Evidence>() {
      +  89  389
           private static final Filter<Evidence> EVIDENCE_USED = new Filter<Evidence>() {
       90  
               @Override
       91  
               public boolean passes(Evidence evidence) {
      -  92  338
                   return evidence.isUsed();
      +  92  388
                   return evidence.isUsed();
       93  
               }
       94   @@ -215,15 +215,15 @@
            */
       102  
           public final Iterable<Evidence> iterator(Confidence confidence) {
      -  103  30
               if (confidence == Confidence.HIGHEST) {
      -  104  5
                   return EvidenceCollection.HIGHEST_CONFIDENCE.filter(this.list);
      -  105  25
               } else if (confidence == Confidence.HIGH) {
      -  106  12
                   return EvidenceCollection.HIGH_CONFIDENCE.filter(this.list);
      -  107  13
               } else if (confidence == Confidence.MEDIUM) {
      -  108  6
                   return EvidenceCollection.MEDIUM_CONFIDENCE.filter(this.list);
      +  103  34
               if (confidence == Confidence.HIGHEST) {
      +  104  6
                   return EvidenceCollection.HIGHEST_CONFIDENCE.filter(this.list);
      +  105  28
               } else if (confidence == Confidence.HIGH) {
      +  106  13
                   return EvidenceCollection.HIGH_CONFIDENCE.filter(this.list);
      +  107  15
               } else if (confidence == Confidence.MEDIUM) {
      +  108  7
                   return EvidenceCollection.MEDIUM_CONFIDENCE.filter(this.list);
       109  
               } else {
      -  110  7
                   return EvidenceCollection.LOW_CONFIDENCE.filter(this.list);
      +  110  8
                   return EvidenceCollection.LOW_CONFIDENCE.filter(this.list);
       111  
               }
       112   @@ -252,10 +252,10 @@
            * Creates a new EvidenceCollection.
       124  
            */
      -  125  285
           public EvidenceCollection() {
      -  126  285
               list = new TreeSet<Evidence>();
      -  127  285
               weightedStrings = new HashSet<String>();
      -  128  285
           }
      +  125  294
           public EvidenceCollection() {
      +  126  294
               list = new TreeSet<Evidence>();
      +  127  294
               weightedStrings = new HashSet<String>();
      +  128  294
           }
       129  
       
       130   @@ -437,7 +437,7 @@
           @Override
       231  
           public Iterator<Evidence> iterator() {
      -  232  67
               return list.iterator();
      +  232  75
               return list.iterator();
       233  
           }
       234   @@ -456,23 +456,23 @@
            */
       241  
           public boolean containsUsedString(String text) {
      -  242  52
               if (text == null) {
      +  242  60
               if (text == null) {
       243  0
                   return false;
       244  
               }
      -  245  52
               final String textToTest = text.toLowerCase();
      +  245  60
               final String textToTest = text.toLowerCase();
       246  
       
      -  247  52
               for (Evidence e : EvidenceCollection.EVIDENCE_USED.filter(this)) {
      +  247  60
               for (Evidence e : EvidenceCollection.EVIDENCE_USED.filter(this)) {
       248  
                   //TODO consider changing the regex to only compare alpha-numeric (i.e. strip everything else)
      -  249  254
                   final String value = urlCorrection(e.getValue().toLowerCase()).replaceAll("[\\s_-]", "");
      -  250  254
                   if (value.contains(textToTest)) {
      -  251  27
                       return true;
      +  249  295
                   final String value = urlCorrection(e.getValue().toLowerCase()).replaceAll("[\\s_-]", "");
      +  250  295
                   if (value.contains(textToTest)) {
      +  251  31
                       return true;
       252  
                   }
      -  253  227
               }
      -  254  25
               return false;
      +  253  264
               }
      +  254  29
               return false;
       255  
           }
       256   @@ -698,22 +698,22 @@
            */
       386  
           private String urlCorrection(String value) {
      -  387  254
               if (value == null || !UrlStringUtils.containsUrl(value)) {
      -  388  235
                   return value;
      +  387  295
               if (value == null || !UrlStringUtils.containsUrl(value)) {
      +  388  273
                   return value;
       389  
               }
      -  390  19
               final StringBuilder sb = new StringBuilder(value.length());
      -  391  19
               final String[] parts = value.split("\\s");
      -  392  38
               for (String part : parts) {
      -  393  19
                   if (UrlStringUtils.isUrl(part)) {
      +  390  22
               final StringBuilder sb = new StringBuilder(value.length());
      +  391  22
               final String[] parts = value.split("\\s");
      +  392  44
               for (String part : parts) {
      +  393  22
                   if (UrlStringUtils.isUrl(part)) {
       394  
                       try {
      -  395  19
                           final List<String> data = UrlStringUtils.extractImportantUrlData(part);
      -  396  19
                           sb.append(' ').append(StringUtils.join(data, ' '));
      +  395  22
                           final List<String> data = UrlStringUtils.extractImportantUrlData(part);
      +  396  22
                           sb.append(' ').append(StringUtils.join(data, ' '));
       397  0
                       } catch (MalformedURLException ex) {
       398  0
                           LOGGER.debug("error parsing {}", part, ex);
       399  0
                           sb.append(' ').append(part);
      -  400  19
                       }
      +  400  22
                       }
       401  
                   } else {
       402  0
                       sb.append(' ').append(part);
      @@ -721,13 +721,13 @@
                   }
       404  
               }
      -  405  19
               return sb.toString().trim();
      +  405  22
               return sb.toString().trim();
       406  
           }
       407  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Identifier.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Identifier.html index b3bb49e1e..c9186ca34 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Identifier.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Identifier.html @@ -67,7 +67,7 @@
        * @author Jeremy Long
       25  
        */
      -  26  33
       public class Identifier implements Serializable, Comparable<Identifier> {
      +  26  36
       public class Identifier implements Serializable, Comparable<Identifier> {
       27  
       
       28   @@ -110,11 +110,11 @@
            * @param url the identifier url.
       48  
            */
      -  49  26
           public Identifier(String type, String value, String url) {
      -  50  26
               this.type = type;
      -  51  26
               this.value = value;
      -  52  26
               this.url = url;
      -  53  26
           }
      +  49  27
           public Identifier(String type, String value, String url) {
      +  50  27
               this.type = type;
      +  51  27
               this.value = value;
      +  52  27
               this.url = url;
      +  53  27
           }
       54  
       
       55   @@ -179,8 +179,8 @@
            */
       87  
           public void setConfidence(Confidence confidence) {
      -  88  6
               this.confidence = confidence;
      -  89  6
           }
      +  88  7
               this.confidence = confidence;
      +  89  7
           }
       90  
       
       91   @@ -205,7 +205,7 @@
            */
       101  
           public String getValue() {
      -  102  216
               return value;
      +  102  308
               return value;
       103  
           }
       104   @@ -287,7 +287,7 @@
            */
       145  
           public String getType() {
      -  146  384
               return type;
      +  146  543
               return type;
       147  
           }
       148   @@ -383,10 +383,10 @@
           @Override
       201  
           public int hashCode() {
      -  202  18
               int hash = 5;
      -  203  18
               hash = 53 * hash + (this.value != null ? this.value.hashCode() : 0);
      -  204  18
               hash = 53 * hash + (this.type != null ? this.type.hashCode() : 0);
      -  205  18
               return hash;
      +  202  4
               int hash = 5;
      +  203  4
               hash = 53 * hash + (this.value != null ? this.value.hashCode() : 0);
      +  204  4
               hash = 53 * hash + (this.type != null ? this.type.hashCode() : 0);
      +  205  4
               return hash;
       206  
           }
       207   @@ -426,17 +426,17 @@
           @Override
       225  
           public int compareTo(Identifier o) {
      -  226  33
               if (o == null) {
      +  226  36
               if (o == null) {
       227  0
                   return -1;
       228  
               }
      -  229  33
               return this.value.compareTo(o.value);
      +  229  36
               return this.value.compareTo(o.value);
       230  
           }
       231  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Reference.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Reference.html index 3860f9e39..b12dd4a29 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Reference.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Reference.html @@ -288,6 +288,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Vulnerability.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Vulnerability.html index 35f0f5924..62357de80 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Vulnerability.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.Vulnerability.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      Vulnerability
      54%
      50/91
      22%
      5/22
      1.324
      Vulnerability
      51%
      47/91
      18%
      4/22
      1.324
       
      @@ -719,9 +719,9 @@
           @Override
       383  
           public int hashCode() {
      -  384  8
               int hash = 5;
      -  385  8
               hash = 41 * hash + (this.name != null ? this.name.hashCode() : 0);
      -  386  8
               return hash;
      +  384  0
               int hash = 5;
      +  385  0
               hash = 41 * hash + (this.name != null ? this.name.hashCode() : 0);
      +  386  0
               return hash;
       387  
           }
       388   @@ -868,6 +868,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerabilityComparator.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerabilityComparator.html index 7b47a02a3..815b77595 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerabilityComparator.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerabilityComparator.html @@ -71,7 +71,7 @@
        * @author Jeremy Long
       27  
        */
      -  28  207
       public class VulnerabilityComparator implements Comparator<Vulnerability>, Serializable {
      +  28  213
       public class VulnerabilityComparator implements Comparator<Vulnerability>, Serializable {
       29  
       
       30   @@ -109,6 +109,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerableSoftware.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerableSoftware.html index c4fe01b82..6138e46b6 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerableSoftware.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.dependency.VulnerableSoftware.html @@ -79,7 +79,7 @@
        * @author Jeremy Long
       31  
        */
      -  32  12318
       public class VulnerableSoftware extends IndexEntry implements Serializable, Comparable<VulnerableSoftware> {
      +  32  12396
       public class VulnerableSoftware extends IndexEntry implements Serializable, Comparable<VulnerableSoftware> {
       33  
       
       34   @@ -113,13 +113,13 @@
           public void setCpe(String cpe) {
       49  
               try {
      -  50  1082
                   parseName(cpe);
      +  50  1103
                   parseName(cpe);
       51  0
               } catch (UnsupportedEncodingException ex) {
       52  0
                   LOGGER.warn("Character encoding is unsupported for CPE '{}'.", cpe);
       53  0
                   LOGGER.debug("", ex);
       54  0
                   setName(cpe);
      -  55  1082
               }
      -  56  1082
           }
      +  55  1103
               }
      +  56  1103
           }
       57  
       
       58   @@ -154,32 +154,32 @@
           @Override
       73  
           public void parseName(String cpeName) throws UnsupportedEncodingException {
      -  74  1599
               this.name = cpeName;
      -  75  1599
               if (cpeName != null && cpeName.length() > 7) {
      -  76  1594
                   final String[] data = cpeName.substring(7).split(":");
      -  77  1594
                   if (data.length >= 1) {
      -  78  1594
                       this.setVendor(urlDecode(data[0]));
      +  74  1677
               this.name = cpeName;
      +  75  1677
               if (cpeName != null && cpeName.length() > 7) {
      +  76  1672
                   final String[] data = cpeName.substring(7).split(":");
      +  77  1672
                   if (data.length >= 1) {
      +  78  1672
                       this.setVendor(urlDecode(data[0]));
       79  
                   }
      -  80  1594
                   if (data.length >= 2) {
      -  81  1593
                       this.setProduct(urlDecode(data[1]));
      +  80  1672
                   if (data.length >= 2) {
      +  81  1671
                       this.setProduct(urlDecode(data[1]));
       82  
                   }
      -  83  1594
                   if (data.length >= 3) {
      -  84  1593
                       version = urlDecode(data[2]);
      +  83  1672
                   if (data.length >= 3) {
      +  84  1671
                       version = urlDecode(data[2]);
       85  
                   }
      -  86  1594
                   if (data.length >= 4) {
      +  86  1672
                   if (data.length >= 4) {
       87  232
                       update = urlDecode(data[3]);
       88  
                   }
      -  89  1594
                   if (data.length >= 5) {
      +  89  1672
                   if (data.length >= 5) {
       90  0
                       edition = urlDecode(data[4]);
       91  
                   }
       92  
               }
      -  93  1599
           }
      +  93  1677
           }
       94  
           /**
       95   @@ -288,9 +288,9 @@
           @Override
       153  
           public int hashCode() {
      -  154  110
               int hash = 7;
      -  155  110
               hash = 83 * hash + (this.name != null ? this.name.hashCode() : 0);
      -  156  110
               return hash;
      +  154  131
               int hash = 7;
      +  155  131
               hash = 83 * hash + (this.name != null ? this.name.hashCode() : 0);
      +  156  131
               return hash;
       157  
           }
       158   @@ -491,7 +491,7 @@
            */
       277  
           public String getVersion() {
      -  278  1861
               return version;
      +  278  2083
               return version;
       279  
           }
       280   @@ -532,7 +532,7 @@
            */
       299  
           public String getUpdate() {
      -  300  1256
               return update;
      +  300  1372
               return update;
       301  
           }
       302   @@ -608,12 +608,12 @@
            */
       340  
           private String urlDecode(String string) {
      -  341  5012
               final String text = string.replace("+", "%2B");
      +  341  5246
               final String text = string.replace("+", "%2B");
       342  
               String result;
       343  
               try {
      -  344  5012
                   result = URLDecoder.decode(text, "UTF-8");
      +  344  5246
                   result = URLDecoder.decode(text, "UTF-8");
       345  0
               } catch (UnsupportedEncodingException ex) {
       346  
                   try {
      @@ -621,8 +621,8 @@  348  0
                   } catch (UnsupportedEncodingException ex1) {
       349  0
                       result = defaultUrlDecode(text);
       350  0
                   }
      -  351  5012
               }
      -  352  5012
               return result;
      +  351  5246
               }
      +  352  5246
               return result;
       353  
           }
       354   @@ -650,6 +650,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ExceptionCollection.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ExceptionCollection.html index 0ad825119..80ae4be63 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ExceptionCollection.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ExceptionCollection.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      ExceptionCollection
      6%
      4/60
      0%
      0/10
      1.333
      ExceptionCollection
      13%
      8/60
      0%
      0/10
      1.333
       
      @@ -72,7 +72,7 @@  27  
        *
       28   -
        * @author Jeremy Lomg
      +
        * @author Jeremy Long
       29  
        */
       30   @@ -124,7 +124,7 @@  56  
            * @param exceptions a list of exceptions
       57   -
            * @param fatal indicates if the exception that occurred is fatal - meaning
      +
            * @param fatal indicates if any of the exceptions that occurred is fatal - meaning
       58  
            * that no analysis was performed.
       59   @@ -148,17 +148,17 @@  70  
            * @param exceptions a list of exceptions
       71   -
            * @param fatal indicates if the exception that occurred is fatal - meaning
      +
            * @param fatal indicates if any of the exceptions that occurred is fatal - meaning
       72  
            * that no analysis was performed.
       73  
            */
       74  
           public ExceptionCollection(String msg, List<Throwable> exceptions, boolean fatal) {
      -  75  0
               super(msg);
      -  76  0
               this.exceptions = exceptions;
      -  77  0
               this.fatal = fatal;
      -  78  0
           }
      +  75  1
               super(msg);
      +  76  1
               this.exceptions = exceptions;
      +  77  1
               this.fatal = fatal;
      +  78  1
           }
       79  
       
       80   @@ -296,7 +296,7 @@
            * attempt at completing the analysis even if exceptions occurred.
       156  
            */
      -  157  1
           private boolean fatal = false;
      +  157  2
           private boolean fatal = false;
       158  
       
       159   @@ -346,7 +346,7 @@
           @Override
       183  
           public void printStackTrace(PrintWriter s) {
      -  184  0
               s.println("Multiple Exceptions Occured");
      +  184  0
               s.println("Multiple Exceptions Occurred");
       185  0
               super.printStackTrace(s);
       186  0
               for (Throwable t : this.exceptions) {
       187  0
                   s.println("Next Exception:");
      @@ -397,7 +397,7 @@  215  0
               final StringBuilder sb = new StringBuilder();
       216  0
               final String msg = super.getMessage();
       217  0
               if (msg == null || msg.isEmpty()) {
      -  218  0
                   sb.append("One or more exceptions occured during analysis:");
      +  218  0
                   sb.append("One or more exceptions occurred during analysis:");
       219  
               } else {
       220  0
                   sb.append(msg);
      @@ -413,6 +413,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.InitializationException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.InitializationException.html index 591fc0d95..dedb620fb 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.InitializationException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.InitializationException.html @@ -137,12 +137,12 @@
            */
       63  
           public InitializationException(String msg, Throwable ex) {
      -  64  5
               super(msg, ex);
      -  65  5
           }
      +  64  7
               super(msg, ex);
      +  65  7
           }
       66  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.NoDataException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.NoDataException.html index a63f5468b..e58a3f11c 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.NoDataException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.NoDataException.html @@ -147,6 +147,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ReportException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ReportException.html index 3ad1eea14..91956e01f 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ReportException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ReportException.html @@ -143,6 +143,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ScanAgentException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ScanAgentException.html index 874b82627..0a6ca0c6d 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ScanAgentException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.exception.ScanAgentException.html @@ -147,6 +147,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.EscapeTool.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.EscapeTool.html index 503571df4..8f6ef2f37 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.EscapeTool.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.EscapeTool.html @@ -170,6 +170,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.ReportGenerator.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.ReportGenerator.html index 03a979a8e..545c99573 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.ReportGenerator.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.ReportGenerator.html @@ -561,6 +561,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.VelocityLoggerRedirect.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.VelocityLoggerRedirect.html index 2dafb8d41..b6ef24305 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.VelocityLoggerRedirect.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.reporting.VelocityLoggerRedirect.html @@ -235,6 +235,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DBUtils.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DBUtils.html index c33ec613b..9b1d2c2f5 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DBUtils.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DBUtils.html @@ -151,16 +151,16 @@
            */
       74  
           public static void closeStatement(Statement statement) {
      -  75  49
               if (statement != null) {
      +  75  51
               if (statement != null) {
       76  
                   try {
      -  77  49
                       statement.close();
      +  77  51
                       statement.close();
       78  0
                   } catch (SQLException ex) {
       79  0
                       LOGGER.trace(statement.toString(), ex);
      -  80  49
                   }
      +  80  51
                   }
       81  
               }
      -  82  49
           }
      +  82  51
           }
       83  
       
       84   @@ -175,20 +175,20 @@
            */
       89  
           public static void closeResultSet(ResultSet rs) {
      -  90  49
               if (rs != null) {
      +  90  51
               if (rs != null) {
       91  
                   try {
      -  92  49
                       rs.close();
      +  92  51
                       rs.close();
       93  0
                   } catch (SQLException ex) {
       94  0
                       LOGGER.trace(rs.toString(), ex);
      -  95  49
                   }
      +  95  51
                   }
       96  
               }
      -  97  49
           }
      +  97  51
           }
       98  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DateUtil.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DateUtil.html index a6f87ad9b..31db3625f 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DateUtil.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DateUtil.html @@ -109,6 +109,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersion.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersion.html index 5319a6375..fbf59b61d 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersion.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersion.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      DependencyVersion
      91%
      82/90
      76%
      49/64
      5.273
      DependencyVersion
      93%
      88/94
      84%
      59/70
      5.636
       
      @@ -74,9 +74,9 @@  28  
        * <p>
       29   -
        * Simple object to track the parts of a version number. The parts are contained in a List such that version 1.2.3 will
      +
        * Simple object to track the parts of a version number. The parts are contained
       30   -
        * be stored as:  <code>versionParts[0] = 1;
      +
        * in a List such that version 1.2.3 will be stored as:  <code>versionParts[0] = 1;
       31  
        * versionParts[1] = 2;
       32   @@ -86,365 +86,383 @@  34  
        * <p>
       35   -
        * Note, the parser contained in this class expects the version numbers to be separated by periods. If a different
      +
        * Note, the parser contained in this class expects the version numbers to be
       36   -
        * separator is used the parser will likely fail.</p>
      +
        * separated by periods. If a different separator is used the parser will likely
       37   -
        *
      +
        * fail.</p>
       38   -
        * @author Jeremy Long
      +
        *
       39   +
        * @author Jeremy Long
      +  40  
        */
      -  40  14
       public class DependencyVersion implements Iterable<String>, Comparable<DependencyVersion> {
      -  41   -
       
      +  41  14
       public class DependencyVersion implements Iterable<String>, Comparable<DependencyVersion> {
       42   -
           /**
      +
       
       43   -
            * Constructor for a empty DependencyVersion.
      +
           /**
       44   +
            * Constructor for a empty DependencyVersion.
      +  45  
            */
      -  45  4
           public DependencyVersion() {
      -  46  4
           }
      -  47   -
       
      +  46  4
           public DependencyVersion() {
      +  47  4
           }
       48   -
           /**
      -  49   -
            * Constructor for a DependencyVersion that will parse a version string.
      -  50   -
            * <b>Note</b>, this should only be used when the version passed in is already known to be a well formatted version
      -  51   -
            * number. Otherwise, DependencyVersionUtil.parseVersion() should be used instead.
      -  52   -
            *
      -  53   -
            * @param version the well formatted version number to parse
      -  54   -
            */
      -  55  931
           public DependencyVersion(String version) {
      -  56  931
               parseVersion(version);
      -  57  931
           }
      -  58  
       
      -  59   +  49  
           /**
      -  60   -
            * Parses a version string into its sub parts: major, minor, revision, build, etc. <b>Note</b>, this should only be
      -  61   -
            * used to parse something that is already known to be a version number.
      -  62   +  50   +
            * Constructor for a DependencyVersion that will parse a version string.
      +  51   +
            * <b>Note</b>, this should only be used when the version passed in is
      +  52   +
            * already known to be a well formatted version number. Otherwise,
      +  53   +
            * DependencyVersionUtil.parseVersion() should be used instead.
      +  54  
            *
      -  63   -
            * @param version the version string to parse
      -  64   +  55   +
            * @param version the well formatted version number to parse
      +  56  
            */
      +  57  1054
           public DependencyVersion(String version) {
      +  58  1054
               parseVersion(version);
      +  59  1054
           }
      +  60   +
       
      +  61   +
           /**
      +  62   +
            * Parses a version string into its sub parts: major, minor, revision,
      +  63   +
            * build, etc. <b>Note</b>, this should only be used to parse something that
      +  64   +
            * is already known to be a version number.
       65   +
            *
      +  66   +
            * @param version the version string to parse
      +  67   +
            */
      +  68  
           public final void parseVersion(String version) {
      -  66  933
               versionParts = new ArrayList<String>();
      -  67  933
               if (version != null) {
      -  68  933
                   final Pattern rx = Pattern.compile("(\\d+[a-z]{1,3}$|[a-z]+\\d+|\\d+|(release|beta|alpha)$)");
      -  69  933
                   final Matcher matcher = rx.matcher(version.toLowerCase());
      -  70  3876
                   while (matcher.find()) {
      -  71  2943
                       versionParts.add(matcher.group());
      -  72   -
                   }
      -  73  933
                   if (versionParts.isEmpty()) {
      -  74  6
                       versionParts.add(version);
      +  69  1056
               versionParts = new ArrayList<String>();
      +  70  1056
               if (version != null) {
      +  71  1056
                   final Pattern rx = Pattern.compile("(\\d+[a-z]{1,3}$|[a-z]+\\d+|\\d+|(release|beta|alpha)$)");
      +  72  1056
                   final Matcher matcher = rx.matcher(version.toLowerCase());
      +  73  4362
                   while (matcher.find()) {
      +  74  3306
                       versionParts.add(matcher.group());
       75  
                   }
      -  76   -
               }
      -  77  933
           }
      +  76  1056
                   if (versionParts.isEmpty()) {
      +  77  7
                       versionParts.add(version);
       78   -
           /**
      +
                   }
       79   -
            * A list of the version parts.
      -  80   -
            */
      -  81   -
           private List<String> versionParts;
      -  82   -
       
      -  83   -
           /**
      -  84   -
            * Get the value of versionParts.
      -  85   -
            *
      -  86   -
            * @return the value of versionParts
      -  87   -
            */
      -  88   -
           public List<String> getVersionParts() {
      -  89  1402
               return versionParts;
      -  90   -
           }
      -  91   -
       
      -  92   -
           /**
      -  93   -
            * Set the value of versionParts.
      -  94   -
            *
      -  95   -
            * @param versionParts new value of versionParts
      -  96   -
            */
      -  97   -
           public void setVersionParts(List<String> versionParts) {
      -  98  3
               this.versionParts = versionParts;
      -  99  3
           }
      -  100   -
       
      -  101   -
           /**
      -  102   -
            * Retrieves an iterator for the version parts.
      -  103   -
            *
      -  104   -
            * @return an iterator for the version parts
      -  105   -
            */
      -  106   -
           @Override
      -  107   -
           public Iterator<String> iterator() {
      -  108  1
               return versionParts.iterator();
      -  109   -
           }
      -  110   -
       
      -  111   -
           /**
      -  112   -
            * Reconstructs the version string from the split version parts.
      -  113   -
            *
      -  114   -
            * @return a string representing the version.
      -  115   -
            */
      -  116   -
           @Override
      -  117   -
           public String toString() {
      -  118  318
               return StringUtils.join(versionParts, '.');
      -  119   -
           }
      -  120   -
       
      -  121   -
           /**
      -  122   -
            * Compares the equality of this object to the one passed in as a parameter.
      -  123   -
            *
      -  124   -
            * @param obj the object to compare equality
      -  125   -
            * @return returns true only if the two objects are equal, otherwise false
      -  126   -
            */
      -  127   -
           @Override
      -  128   -
           public boolean equals(Object obj) {
      -  129  557
               if (obj == null) {
      -  130  0
                   return false;
      -  131  
               }
      -  132  557
               if (getClass() != obj.getClass()) {
      +  80  1056
           }
      +  81   +
           /**
      +  82   +
            * A list of the version parts.
      +  83   +
            */
      +  84   +
           private List<String> versionParts;
      +  85   +
       
      +  86   +
           /**
      +  87   +
            * Get the value of versionParts.
      +  88   +
            *
      +  89   +
            * @return the value of versionParts
      +  90   +
            */
      +  91   +
           public List<String> getVersionParts() {
      +  92  1635
               return versionParts;
      +  93   +
           }
      +  94   +
       
      +  95   +
           /**
      +  96   +
            * Set the value of versionParts.
      +  97   +
            *
      +  98   +
            * @param versionParts new value of versionParts
      +  99   +
            */
      +  100   +
           public void setVersionParts(List<String> versionParts) {
      +  101  3
               this.versionParts = versionParts;
      +  102  3
           }
      +  103   +
       
      +  104   +
           /**
      +  105   +
            * Retrieves an iterator for the version parts.
      +  106   +
            *
      +  107   +
            * @return an iterator for the version parts
      +  108   +
            */
      +  109   +
           @Override
      +  110   +
           public Iterator<String> iterator() {
      +  111  1
               return versionParts.iterator();
      +  112   +
           }
      +  113   +
       
      +  114   +
           /**
      +  115   +
            * Reconstructs the version string from the split version parts.
      +  116   +
            *
      +  117   +
            * @return a string representing the version.
      +  118   +
            */
      +  119   +
           @Override
      +  120   +
           public String toString() {
      +  121  348
               return StringUtils.join(versionParts, '.');
      +  122   +
           }
      +  123   +
       
      +  124   +
           /**
      +  125   +
            * Compares the equality of this object to the one passed in as a parameter.
      +  126   +
            *
      +  127   +
            * @param obj the object to compare equality
      +  128   +
            * @return returns true only if the two objects are equal, otherwise false
      +  129   +
            */
      +  130   +
           @Override
      +  131   +
           public boolean equals(Object obj) {
      +  132  648
               if (obj == null) {
       133  0
                   return false;
       134  
               }
      -  135  557
               final DependencyVersion other = (DependencyVersion) obj;
      -  136  557
               final int max = (this.versionParts.size() < other.versionParts.size())
      -  137  105
                       ? this.versionParts.size() : other.versionParts.size();
      -  138   +  135  648
               if (getClass() != obj.getClass()) {
      +  136  0
                   return false;
      +  137   +
               }
      +  138  648
               final DependencyVersion other = (DependencyVersion) obj;
      +  139  648
               final int minVersionMatchLength = (this.versionParts.size() < other.versionParts.size())
      +  140  105
                       ? this.versionParts.size() : other.versionParts.size();
      +  141  648
               final int maxVersionMatchLength = (this.versionParts.size() > other.versionParts.size())
      +  142  10
                       ? this.versionParts.size() : other.versionParts.size();
      +  143   +
       
      +  144  648
               if (minVersionMatchLength == 1 && maxVersionMatchLength >= 3) {
      +  145  1
                   return false;
      +  146   +
               }
      +  147   +
       
      +  148  
               //TODO steal better version of code from compareTo
      -  139  1225
               for (int i = 0; i < max; i++) {
      -  140  1126
                   final String thisPart = this.versionParts.get(i);
      -  141  1126
                   final String otherPart = other.versionParts.get(i);
      -  142  1126
                   if (!thisPart.equals(otherPart)) {
      -  143  458
                       return false;
      -  144   +  149  1373
               for (int i = 0; i < minVersionMatchLength; i++) {
      +  150  1273
                   final String thisPart = this.versionParts.get(i);
      +  151  1273
                   final String otherPart = other.versionParts.get(i);
      +  152  1273
                   if (!thisPart.equals(otherPart)) {
      +  153  547
                       return false;
      +  154  
                   }
      -  145   +  155  
               }
      -  146  99
               if (this.versionParts.size() > max) {
      -  147  0
                   for (int i = max; i < this.versionParts.size(); i++) {
      -  148  0
                       if (!"0".equals(this.versionParts.get(i))) {
      -  149  0
                           return false;
      -  150   -
                       }
      -  151   -
                   }
      -  152   -
               }
      -  153   -
       
      -  154  99
               if (other.versionParts.size() > max) {
      -  155  77
                   for (int i = max; i < other.versionParts.size(); i++) {
      -  156  77
                       if (!"0".equals(other.versionParts.get(i))) {
      -  157  77
                           return false;
      -  158   -
                       }
      -  159   -
                   }
      +  156  100
               if (this.versionParts.size() > minVersionMatchLength) {
      +  157  2
                   for (int i = minVersionMatchLength; i < this.versionParts.size(); i++) {
      +  158  1
                       if (!"0".equals(this.versionParts.get(i))) {
      +  159  0
                           return false;
       160   -
               }
      +
                       }
       161   -
       
      +
                   }
       162   -
               /*
      +
               }
       163   -
                *  if (this.versionParts != other.versionParts && (this.versionParts == null || !this.versionParts.equals(other.versionParts))) {
      -  164   -
                *      return false;
      -  165   -
                *  }
      -  166   -
                */
      -  167  22
               return true;
      +
       
      +  164  100
               if (other.versionParts.size() > minVersionMatchLength) {
      +  165  77
                   for (int i = minVersionMatchLength; i < other.versionParts.size(); i++) {
      +  166  77
                       if (!"0".equals(other.versionParts.get(i))) {
      +  167  77
                           return false;
       168   -
           }
      +
                       }
       169   -
       
      +
                   }
       170   -
           /**
      +
               }
       171   -
            * Calculates the hashCode for this object.
      +
       
       172   -
            *
      +
               /*
       173   -
            * @return the hashCode
      +
                *  if (this.versionParts != other.versionParts && (this.versionParts == null || !this.versionParts.equals(other.versionParts))) {
       174   -
            */
      +
                *      return false;
       175   -
           @Override
      +
                *  }
       176   -
           public int hashCode() {
      -  177  1
               int hash = 5;
      -  178  1
               hash = 71 * hash + (this.versionParts != null ? this.versionParts.hashCode() : 0);
      -  179  1
               return hash;
      +
                */
      +  177  23
               return true;
      +  178   +
           }
      +  179   +
       
       180   -
           }
      -  181   -
       
      -  182  
           /**
      -  183   -
            * Determines if the three most major major version parts are identical. For instances, if version 1.2.3.4 was
      -  184   -
            * compared to 1.2.3 this function would return true.
      -  185   +  181   +
            * Calculates the hashCode for this object.
      +  182  
            *
      -  186   -
            * @param version the version number to compare
      -  187   -
            * @return true if the first three major parts of the version are identical
      -  188   +  183   +
            * @return the hashCode
      +  184  
            */
      -  189   -
           public boolean matchesAtLeastThreeLevels(DependencyVersion version) {
      -  190  319
               if (version == null) {
      -  191  0
                   return false;
      -  192   -
               }
      -  193  319
               if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) {
      -  194  1
                   return false;
      -  195   -
               }
      -  196   -
       
      -  197  318
               final int max = (this.versionParts.size() < version.versionParts.size())
      -  198  66
                       ? this.versionParts.size() : version.versionParts.size();
      -  199   -
       
      -  200  318
               boolean ret = true;
      -  201  657
               for (int i = 0; i < max; i++) {
      -  202  607
                   final String thisVersion = this.versionParts.get(i);
      -  203  607
                   final String otherVersion = version.getVersionParts().get(i);
      -  204  607
                   if (i >= 3) {
      -  205  2
                       if (thisVersion.compareToIgnoreCase(otherVersion) >= 0) {
      -  206  1
                           ret = false;
      -  207  1
                           break;
      -  208   -
                       }
      -  209  605
                   } else if (!thisVersion.equals(otherVersion)) {
      -  210  267
                       ret = false;
      -  211  267
                       break;
      -  212   -
                   }
      -  213   -
               }
      -  214   -
       
      -  215  318
               return ret;
      -  216   -
           }
      -  217   -
       
      -  218   +  185  
           @Override
      -  219   -
           public int compareTo(DependencyVersion version) {
      -  220  32
               if (version == null) {
      -  221  0
                   return 1;
      -  222   -
               }
      -  223  32
               final List<String> left = this.getVersionParts();
      -  224  32
               final List<String> right = version.getVersionParts();
      -  225  32
               final int max = left.size() < right.size() ? left.size() : right.size();
      -  226   -
       
      -  227  82
               for (int i = 0; i < max; i++) {
      -  228  70
                   final String lStr = left.get(i);
      -  229  70
                   final String rStr = right.get(i);
      -  230  70
                   if (lStr.equals(rStr)) {
      -  231  50
                       continue;
      -  232   -
                   }
      -  233   -
                   try {
      -  234  20
                       final int l = Integer.parseInt(lStr);
      -  235  13
                       final int r = Integer.parseInt(rStr);
      -  236  12
                       if (l < r) {
      -  237  9
                           return -1;
      -  238  3
                       } else if (l > r) {
      -  239  3
                           return 1;
      -  240   -
                       }
      -  241  8
                   } catch (NumberFormatException ex) {
      -  242  8
                       final int comp = left.get(i).compareTo(right.get(i));
      -  243  8
                       if (comp < 0) {
      -  244  6
                           return -1;
      -  245  2
                       } else if (comp > 0) {
      -  246  2
                           return 1;
      -  247   -
                       }
      -  248  0
                   }
      -  249   -
               }
      -  250  12
               if (left.size() < right.size()) {
      -  251  3
                   return -1;
      -  252  9
               } else if (left.size() > right.size()) {
      -  253  3
                   return 1;
      -  254   -
               } else {
      -  255  6
                   return 0;
      -  256   -
               }
      -  257   +  186   +
           public int hashCode() {
      +  187  1
               int hash = 5;
      +  188  1
               hash = 71 * hash + (this.versionParts != null ? this.versionParts.hashCode() : 0);
      +  189  1
               return hash;
      +  190  
           }
      +  191   +
       
      +  192   +
           /**
      +  193   +
            * Determines if the three most major major version parts are identical. For
      +  194   +
            * instances, if version 1.2.3.4 was compared to 1.2.3 this function would
      +  195   +
            * return true.
      +  196   +
            *
      +  197   +
            * @param version the version number to compare
      +  198   +
            * @return true if the first three major parts of the version are identical
      +  199   +
            */
      +  200   +
           public boolean matchesAtLeastThreeLevels(DependencyVersion version) {
      +  201  382
               if (version == null) {
      +  202  0
                   return false;
      +  203   +
               }
      +  204  382
               if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) {
      +  205  1
                   return false;
      +  206   +
               }
      +  207   +
       
      +  208  381
               final int max = (this.versionParts.size() < version.versionParts.size())
      +  209  66
                       ? this.versionParts.size() : version.versionParts.size();
      +  210   +
       
      +  211  381
               boolean ret = true;
      +  212  762
               for (int i = 0; i < max; i++) {
      +  213  712
                   final String thisVersion = this.versionParts.get(i);
      +  214  712
                   final String otherVersion = version.getVersionParts().get(i);
      +  215  712
                   if (i >= 3) {
      +  216  2
                       if (thisVersion.compareToIgnoreCase(otherVersion) >= 0) {
      +  217  1
                           ret = false;
      +  218  1
                           break;
      +  219   +
                       }
      +  220  710
                   } else if (!thisVersion.equals(otherVersion)) {
      +  221  330
                       ret = false;
      +  222  330
                       break;
      +  223   +
                   }
      +  224   +
               }
      +  225   +
       
      +  226  381
               return ret;
      +  227   +
           }
      +  228   +
       
      +  229   +
           @Override
      +  230   +
           public int compareTo(DependencyVersion version) {
      +  231  32
               if (version == null) {
      +  232  0
                   return 1;
      +  233   +
               }
      +  234  32
               final List<String> left = this.getVersionParts();
      +  235  32
               final List<String> right = version.getVersionParts();
      +  236  32
               final int max = left.size() < right.size() ? left.size() : right.size();
      +  237   +
       
      +  238  82
               for (int i = 0; i < max; i++) {
      +  239  70
                   final String lStr = left.get(i);
      +  240  70
                   final String rStr = right.get(i);
      +  241  70
                   if (lStr.equals(rStr)) {
      +  242  50
                       continue;
      +  243   +
                   }
      +  244   +
                   try {
      +  245  20
                       final int l = Integer.parseInt(lStr);
      +  246  13
                       final int r = Integer.parseInt(rStr);
      +  247  12
                       if (l < r) {
      +  248  9
                           return -1;
      +  249  3
                       } else if (l > r) {
      +  250  3
                           return 1;
      +  251   +
                       }
      +  252  8
                   } catch (NumberFormatException ex) {
      +  253  8
                       final int comp = left.get(i).compareTo(right.get(i));
      +  254  8
                       if (comp < 0) {
      +  255  6
                           return -1;
      +  256  2
                       } else if (comp > 0) {
      +  257  2
                           return 1;
       258   +
                       }
      +  259  0
                   }
      +  260   +
               }
      +  261  12
               if (left.size() < right.size()) {
      +  262  3
                   return -1;
      +  263  9
               } else if (left.size() > right.size()) {
      +  264  3
                   return 1;
      +  265   +
               } else {
      +  266  6
                   return 0;
      +  267   +
               }
      +  268   +
           }
      +  269  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersionUtil.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersionUtil.html index b874b3dd6..204370408 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersionUtil.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.DependencyVersionUtil.html @@ -152,13 +152,13 @@
            */
       70  
           public static DependencyVersion parseVersion(String text) {
      -  71  886
               if (text == null) {
      +  71  1006
               if (text == null) {
       72  0
                   return null;
       73  
               }
       74  
               //'-' is a special case used within the CVE entries, just include it as the version.
      -  75  886
               if ("-".equals(text)) {
      +  75  1006
               if ("-".equals(text)) {
       76  1
                   final DependencyVersion dv = new DependencyVersion();
       77  1
                   final List<String> list = new ArrayList<String>();
       78  1
                   list.add(text);
      @@ -166,25 +166,25 @@  80  1
                   return dv;
       81  
               }
      -  82  885
               String version = null;
      -  83  885
               Matcher matcher = RX_VERSION.matcher(text);
      -  84  885
               if (matcher.find()) {
      -  85  876
                   version = matcher.group();
      +  82  1005
               String version = null;
      +  83  1005
               Matcher matcher = RX_VERSION.matcher(text);
      +  84  1005
               if (matcher.find()) {
      +  85  995
                   version = matcher.group();
       86  
               }
       87  
               //throw away the results if there are two things that look like version numbers
      -  88  885
               if (matcher.find()) {
      +  88  1005
               if (matcher.find()) {
       89  2
                   return null;
       90  
               }
      -  91  883
               if (version == null) {
      -  92  9
                   matcher = RX_SINGLE_VERSION.matcher(text);
      -  93  9
                   if (matcher.find()) {
      +  91  1003
               if (version == null) {
      +  92  10
                   matcher = RX_SINGLE_VERSION.matcher(text);
      +  93  10
                   if (matcher.find()) {
       94  2
                       version = matcher.group();
       95  
                   } else {
      -  96  7
                       return null;
      +  96  8
                       return null;
       97  
                   }
       98   @@ -195,11 +195,11 @@
                   }
       102  
               }
      -  103  875
               if (version != null && version.endsWith("-py2") && version.length() > 4) {
      +  103  994
               if (version != null && version.endsWith("-py2") && version.length() > 4) {
       104  1
                   version = version.substring(0, version.length() - 4);
       105  
               }
      -  106  875
               return new DependencyVersion(version);
      +  106  994
               return new DependencyVersion(version);
       107  
           }
       108   @@ -252,6 +252,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.ExtractionUtil.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.ExtractionUtil.html index 0f2dca99d..d5571fffe 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.ExtractionUtil.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.ExtractionUtil.html @@ -449,6 +449,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.FileFilterBuilder.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.FileFilterBuilder.html index 333e0452a..710adc64d 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.FileFilterBuilder.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.FileFilterBuilder.html @@ -270,6 +270,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Filter.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Filter.html index 89c444ba4..f21c1204d 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Filter.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Filter.html @@ -56,21 +56,21 @@
       
       19  
           public Iterator<T> filter(Iterator<T> iterator) {
      -  20  83
               return new FilterIterator(iterator);
      +  20  95
               return new FilterIterator(iterator);
       21  
           }
       22  
       
       23  
           public Iterable<T> filter(final Iterable<T> iterable) {
      -  24  83
               return new Iterable<T>() {
      +  24  95
               return new Iterable<T>() {
       25  
       
       26  
                   @Override
       27  
                   public Iterator<T> iterator() {
      -  28  83
                       return filter(iterable.iterator());
      +  28  95
                       return filter(iterable.iterator());
       29  
                   }
       30   @@ -79,7 +79,7 @@
           }
       32  
       
      -  33  83
           private class FilterIterator implements Iterator<T> {
      +  33  95
           private class FilterIterator implements Iterator<T> {
       34  
       
       35   @@ -88,17 +88,17 @@
               private T next;
       37  
       
      -  38  83
               private FilterIterator(Iterator<T> iterator) {
      -  39  83
                   this.iterator = iterator;
      -  40  83
                   toNext();
      -  41  83
               }
      +  38  95
               private FilterIterator(Iterator<T> iterator) {
      +  39  95
                   this.iterator = iterator;
      +  40  95
                   toNext();
      +  41  95
               }
       42  
       
       43  
               @Override
       44  
               public boolean hasNext() {
      -  45  361
                   return next != null;
      +  45  414
                   return next != null;
       46  
               }
       47   @@ -107,13 +107,13 @@
               @Override
       49  
               public T next() {
      -  50  305
                   if (next == null) {
      +  50  350
                   if (next == null) {
       51  0
                       throw new NoSuchElementException();
       52  
                   }
      -  53  305
                   final T returnValue = next;
      -  54  305
                   toNext();
      -  55  305
                   return returnValue;
      +  53  350
                   final T returnValue = next;
      +  54  350
                   toNext();
      +  55  350
                   return returnValue;
       56  
               }
       57   @@ -129,22 +129,22 @@
       
       63  
               private void toNext() {
      -  64  388
                   next = null;
      -  65  555
                   while (iterator.hasNext()) {
      -  66  497
                       final T item = iterator.next();
      -  67  497
                       if (item != null && passes(item)) {
      -  68  330
                           next = item;
      -  69  330
                           break;
      +  64  445
                   next = null;
      +  65  629
                   while (iterator.hasNext()) {
      +  66  563
                       final T item = iterator.next();
      +  67  563
                       if (item != null && passes(item)) {
      +  68  379
                           next = item;
      +  69  379
                           break;
       70  
                       }
      -  71  167
                   }
      -  72  388
               }
      +  71  184
                   }
      +  72  445
               }
       73  
           }
       74  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Pair.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Pair.html index 0a53b72ef..810677be9 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Pair.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.Pair.html @@ -97,17 +97,17 @@
            * @param right the value for the right pair
       41  
            */
      -  42  52334
           public Pair(L left, R right) {
      -  43  52334
               this.left = left;
      -  44  52334
               this.right = right;
      -  45  52334
           }
      +  42  52774
           public Pair(L left, R right) {
      +  43  52774
               this.left = left;
      +  44  52774
               this.right = right;
      +  45  52774
           }
       46  
           /**
       47  
            * The left element of the pair.
       48  
            */
      -  49  52334
           private L left = null;
      +  49  52774
           private L left = null;
       50  
       
       51   @@ -122,7 +122,7 @@
            */
       56  
           public L getLeft() {
      -  57  104666
               return left;
      +  57  105546
               return left;
       58  
           }
       59   @@ -147,7 +147,7 @@
            * The right element of the pair.
       70  
            */
      -  71  52334
           private R right = null;
      +  71  52774
           private R right = null;
       72  
       
       73   @@ -162,7 +162,7 @@
            */
       78  
           public R getRight() {
      -  79  104666
               return right;
      +  79  105546
               return right;
       80  
           }
       81   @@ -197,10 +197,10 @@
           @Override
       97  
           public int hashCode() {
      -  98  52334
               int hash = 3;
      -  99  52334
               hash = 53 * hash + (this.left != null ? this.left.hashCode() : 0);
      -  100  52334
               hash = 53 * hash + (this.right != null ? this.right.hashCode() : 0);
      -  101  52334
               return hash;
      +  98  52774
               int hash = 3;
      +  99  52774
               hash = 53 * hash + (this.left != null ? this.left.hashCode() : 0);
      +  100  52774
               hash = 53 * hash + (this.right != null ? this.right.hashCode() : 0);
      +  101  52774
               return hash;
       102  
           }
       103   @@ -245,6 +245,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.UrlStringUtils.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.UrlStringUtils.html index f7d8c45d8..17682714a 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.UrlStringUtils.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.utils.UrlStringUtils.html @@ -125,7 +125,7 @@
            */
       56  
           public static boolean containsUrl(String text) {
      -  57  206801
               return CONTAINS_URL_TEST.matcher(text).matches();
      +  57  208244
               return CONTAINS_URL_TEST.matcher(text).matches();
       58  
           }
       59   @@ -144,7 +144,7 @@
            */
       66  
           public static boolean isUrl(String text) {
      -  67  33
               return IS_URL_TEST.matcher(text).matches();
      +  67  36
               return IS_URL_TEST.matcher(text).matches();
       68  
           }
       69   @@ -187,40 +187,40 @@
            */
       89  
           public static List<String> extractImportantUrlData(String text) throws MalformedURLException {
      -  90  25
               final List<String> importantParts = new ArrayList<String>();
      -  91  25
               final URL url = new URL(text);
      -  92  25
               final String[] domain = url.getHost().split("\\.");
      +  90  28
               final List<String> importantParts = new ArrayList<String>();
      +  91  28
               final URL url = new URL(text);
      +  92  28
               final String[] domain = url.getHost().split("\\.");
       93  
               //add the domain except www and the tld.
      -  94  72
               for (int i = 0; i < domain.length - 1; i++) {
      -  95  47
                   final String sub = domain[i];
      -  96  47
                   if (!IGNORE_LIST.contains(sub.toLowerCase())) {
      -  97  44
                       importantParts.add(sub);
      +  94  81
               for (int i = 0; i < domain.length - 1; i++) {
      +  95  53
                   final String sub = domain[i];
      +  96  53
                   if (!IGNORE_LIST.contains(sub.toLowerCase())) {
      +  97  50
                       importantParts.add(sub);
       98  
                   }
       99  
               }
      -  100  25
               final String document = url.getPath();
      -  101  25
               final String[] pathParts = document.split("[\\//]");
      -  102  44
               for (int i = 0; i < pathParts.length - 2; i++) {
      -  103  19
                   if (!pathParts[i].isEmpty()) {
      +  100  28
               final String document = url.getPath();
      +  101  28
               final String[] pathParts = document.split("[\\//]");
      +  102  50
               for (int i = 0; i < pathParts.length - 2; i++) {
      +  103  22
                   if (!pathParts[i].isEmpty()) {
       104  0
                       importantParts.add(pathParts[i]);
       105  
                   }
       106  
               }
      -  107  25
               if (pathParts.length > 0 && !pathParts[pathParts.length - 1].isEmpty()) {
      -  108  22
                   final String fileNameNoExt = pathParts[pathParts.length - 1].replaceAll("\\..*{0,5}$", "");
      -  109  22
                   importantParts.add(fileNameNoExt);
      +  107  28
               if (pathParts.length > 0 && !pathParts[pathParts.length - 1].isEmpty()) {
      +  108  25
                   final String fileNameNoExt = pathParts[pathParts.length - 1].replaceAll("\\..*{0,5}$", "");
      +  109  25
                   importantParts.add(fileNameNoExt);
       110  
               }
      -  111  25
               return importantParts;
      +  111  28
               return importantParts;
       112  
           }
       113  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintErrorHandler.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintErrorHandler.html index 09595f53a..0a40d6bb8 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintErrorHandler.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintErrorHandler.html @@ -196,6 +196,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintHandler.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintHandler.html index 0425eb26e..76be69db8 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintHandler.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintHandler.html @@ -429,6 +429,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintParseException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintParseException.html index 8abd9d521..e2a54d422 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintParseException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintParseException.html @@ -147,6 +147,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintParser.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintParser.html index 5fae50d96..d359949a2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintParser.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintParser.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      HintParser
      56%
      30/53
      33%
      2/6
      11
      HintParser
      57%
      31/54
      33%
      2/6
      11
       
      @@ -220,62 +220,63 @@  109  4
                   schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA);
       110  4
                   final HintHandler handler = new HintHandler();
       111  4
                   final SAXParserFactory factory = SAXParserFactory.newInstance();
      -  112  4
                   factory.setNamespaceAware(true);
      -  113  4
                   factory.setValidating(true);
      -  114  4
                   final SAXParser saxParser = factory.newSAXParser();
      -  115  4
                   saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA);
      -  116  4
                   saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
      -  117  4
                   final XMLReader xmlReader = saxParser.getXMLReader();
      -  118  4
                   xmlReader.setErrorHandler(new HintErrorHandler());
      -  119  4
                   xmlReader.setContentHandler(handler);
      -  120   +  112  4
                   factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +  113  4
                   factory.setNamespaceAware(true);
      +  114  4
                   factory.setValidating(true);
      +  115  4
                   final SAXParser saxParser = factory.newSAXParser();
      +  116  4
                   saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA);
      +  117  4
                   saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
      +  118  4
                   final XMLReader xmlReader = saxParser.getXMLReader();
      +  119  4
                   xmlReader.setErrorHandler(new HintErrorHandler());
      +  120  4
                   xmlReader.setContentHandler(handler);
      +  121  
       
      -  121  4
                   final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      -  122  4
                   final InputSource in = new InputSource(reader);
      -  123   +  122  4
                   final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      +  123  4
                   final InputSource in = new InputSource(reader);
      +  124  
       
      -  124  4
                   xmlReader.parse(in);
      -  125  4
                   final Hints hints = new Hints();
      -  126  4
                   hints.setHintRules(handler.getHintRules());
      -  127  4
                   hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules());
      -  128  8
                   return hints;
      -  129  0
               } catch (ParserConfigurationException ex) {
      -  130  0
                   LOGGER.debug("", ex);
      -  131  0
                   throw new HintParseException(ex);
      -  132  0
               } catch (SAXException ex) {
      -  133  0
                   if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) {
      -  134  0
                       throw ex;
      -  135   +  125  4
                   xmlReader.parse(in);
      +  126  4
                   final Hints hints = new Hints();
      +  127  4
                   hints.setHintRules(handler.getHintRules());
      +  128  4
                   hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules());
      +  129  8
                   return hints;
      +  130  0
               } catch (ParserConfigurationException ex) {
      +  131  0
                   LOGGER.debug("", ex);
      +  132  0
                   throw new HintParseException(ex);
      +  133  0
               } catch (SAXException ex) {
      +  134  0
                   if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) {
      +  135  0
                       throw ex;
      +  136  
                   } else {
      -  136  0
                       LOGGER.debug("", ex);
      -  137  0
                       throw new HintParseException(ex);
      -  138   +  137  0
                       LOGGER.debug("", ex);
      +  138  0
                       throw new HintParseException(ex);
      +  139  
                   }
      -  139  0
               } catch (FileNotFoundException ex) {
      -  140  0
                   LOGGER.debug("", ex);
      -  141  0
                   throw new HintParseException(ex);
      -  142  0
               } catch (IOException ex) {
      -  143  0
                   LOGGER.debug("", ex);
      -  144  0
                   throw new HintParseException(ex);
      -  145   +  140  0
               } catch (FileNotFoundException ex) {
      +  141  0
                   LOGGER.debug("", ex);
      +  142  0
                   throw new HintParseException(ex);
      +  143  0
               } catch (IOException ex) {
      +  144  0
                   LOGGER.debug("", ex);
      +  145  0
                   throw new HintParseException(ex);
      +  146  
               } finally {
      -  146  4
                   if (schemaStream != null) {
      -  147   +  147  4
                   if (schemaStream != null) {
      +  148  
                       try {
      -  148  4
                           schemaStream.close();
      -  149  0
                       } catch (IOException ex) {
      -  150  0
                           LOGGER.debug("Error closing hint file stream", ex);
      -  151  4
                       }
      -  152   -
                   }
      +  149  4
                           schemaStream.close();
      +  150  0
                       } catch (IOException ex) {
      +  151  0
                           LOGGER.debug("Error closing hint file stream", ex);
      +  152  4
                       }
       153   -
               }
      +
                   }
       154   -
           }
      +
               }
       155   +
           }
      +  156  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintRule.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintRule.html index f1806a55d..358dff5a4 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintRule.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.HintRule.html @@ -167,7 +167,7 @@
            */
       79  
           public List<Evidence> getGivenProduct() {
      -  80  49
               return givenProduct;
      +  80  48
               return givenProduct;
       81  
           }
       82   @@ -364,6 +364,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.Hints.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.Hints.html index 70077200b..292fc8b83 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.Hints.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.Hints.html @@ -160,6 +160,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule.html index 19b515e91..ac87f4af6 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule.html @@ -179,6 +179,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.License.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.License.html index 98749cf17..c6cfc821a 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.License.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.License.html @@ -266,6 +266,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.Model.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.Model.html index 9dbc41f35..8c21b6d76 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.Model.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.Model.html @@ -665,7 +665,7 @@  350  
            */
       351   -
           private static class PropertyLookup extends StrLookup {
      +
           private static class PropertyLookup extends StrLookup<String> {
       352  
       
       353   @@ -718,6 +718,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomHandler.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomHandler.html index 50f3f73e1..038eb6ce2 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomHandler.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomHandler.html @@ -356,6 +356,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomParseException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomParseException.html index 336fcf6ab..115503d3c 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomParseException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomParseException.html @@ -147,6 +147,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomParser.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomParser.html index b7a57d228..03e317094 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomParser.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomParser.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      PomParser
      50%
      17/34
      50%
      1/2
      8
      PomParser
      51%
      18/35
      50%
      1/2
      8
       
      @@ -114,103 +114,110 @@  49  
           /**
       50   -
            * Parses the given xml file and returns a Model object containing only the fields dependency-check requires.
      +
            * Parses the given xml file and returns a Model object containing only the
       51   -
            *
      +
            * fields dependency-check requires.
       52   -
            * @param file a pom.xml
      -  53   -
            * @return a Model object containing only the fields dependency-check requires
      -  54   -
            * @throws PomParseException thrown if the xml file cannot be parsed
      -  55   -
            */
      -  56   -
           public Model parse(File file) throws PomParseException {
      -  57  1
               FileInputStream fis = null;
      -  58   -
               try {
      -  59  1
                   fis = new FileInputStream(file);
      -  60  2
                   return parse(fis);
      -  61  0
               } catch (IOException ex) {
      -  62  0
                   LOGGER.debug("", ex);
      -  63  0
                   throw new PomParseException(ex);
      -  64   -
               } finally {
      -  65  1
                   if (fis != null) {
      -  66   -
                       try {
      -  67  1
                           fis.close();
      -  68  0
                       } catch (IOException ex) {
      -  69  0
                           LOGGER.debug("Unable to close stream", ex);
      -  70  1
                       }
      -  71   -
                   }
      -  72   -
               }
      -  73   -
           }
      -  74   -
       
      -  75   -
           /**
      -  76   -
            * Parses the given XML file and returns a Model object containing only the fields dependency-check requires.
      -  77  
            *
      -  78   -
            * @param inputStream an InputStream containing suppression rues
      -  79   -
            * @return a list of suppression rules
      -  80   -
            * @throws PomParseException if the XML cannot be parsed
      -  81   +  53   +
            * @param file a pom.xml
      +  54   +
            * @return a Model object containing only the fields dependency-check
      +  55   +
            * requires
      +  56   +
            * @throws PomParseException thrown if the xml file cannot be parsed
      +  57  
            */
      -  82   -
           public Model parse(InputStream inputStream) throws PomParseException {
      -  83   +  58   +
           public Model parse(File file) throws PomParseException {
      +  59  1
               FileInputStream fis = null;
      +  60  
               try {
      -  84  3
                   final PomHandler handler = new PomHandler();
      -  85  3
                   final SAXParserFactory factory = SAXParserFactory.newInstance();
      -  86   -
       //            factory.setNamespaceAware(true);
      -  87   -
       //            factory.setValidating(true);
      -  88  3
                   final SAXParser saxParser = factory.newSAXParser();
      -  89  3
                   final XMLReader xmlReader = saxParser.getXMLReader();
      -  90  3
                   xmlReader.setContentHandler(handler);
      -  91   +  61  1
                   fis = new FileInputStream(file);
      +  62  2
                   return parse(fis);
      +  63  0
               } catch (IOException ex) {
      +  64  0
                   LOGGER.debug("", ex);
      +  65  0
                   throw new PomParseException(ex);
      +  66   +
               } finally {
      +  67  1
                   if (fis != null) {
      +  68   +
                       try {
      +  69  1
                           fis.close();
      +  70  0
                       } catch (IOException ex) {
      +  71  0
                           LOGGER.debug("Unable to close stream", ex);
      +  72  1
                       }
      +  73   +
                   }
      +  74   +
               }
      +  75   +
           }
      +  76  
       
      -  92  3
                   final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      -  93  3
                   final InputSource in = new InputSource(reader);
      -  94   -
                   //in.setEncoding("UTF-8");
      +  77   +
           /**
      +  78   +
            * Parses the given XML file and returns a Model object containing only the
      +  79   +
            * fields dependency-check requires.
      +  80   +
            *
      +  81   +
            * @param inputStream an InputStream containing suppression rues
      +  82   +
            * @return a list of suppression rules
      +  83   +
            * @throws PomParseException if the XML cannot be parsed
      +  84   +
            */
      +  85   +
           public Model parse(InputStream inputStream) throws PomParseException {
      +  86   +
               try {
      +  87  3
                   final PomHandler handler = new PomHandler();
      +  88  3
                   final SAXParserFactory factory = SAXParserFactory.newInstance();
      +  89   +
       //            factory.setNamespaceAware(true);
      +  90   +
       //            factory.setValidating(true);
      +  91  3
                   factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +  92  3
                   final SAXParser saxParser = factory.newSAXParser();
      +  93  3
                   final XMLReader xmlReader = saxParser.getXMLReader();
      +  94  3
                   xmlReader.setContentHandler(handler);
       95  
       
      -  96  3
                   xmlReader.parse(in);
      -  97   +  96  3
                   final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      +  97  3
                   final InputSource in = new InputSource(reader);
      +  98   +
                   //in.setEncoding("UTF-8");
      +  99  
       
      -  98  3
                   return handler.getModel();
      -  99  0
               } catch (ParserConfigurationException ex) {
      -  100  0
                   LOGGER.debug("", ex);
      -  101  0
                   throw new PomParseException(ex);
      -  102  0
               } catch (SAXException ex) {
      -  103  0
                   LOGGER.debug("", ex);
      -  104  0
                   throw new PomParseException(ex);
      -  105  0
               } catch (FileNotFoundException ex) {
      -  106  0
                   LOGGER.debug("", ex);
      -  107  0
                   throw new PomParseException(ex);
      -  108  0
               } catch (IOException ex) {
      -  109  0
                   LOGGER.debug("", ex);
      -  110  0
                   throw new PomParseException(ex);
      -  111   +  100  3
                   xmlReader.parse(in);
      +  101   +
       
      +  102  3
                   return handler.getModel();
      +  103  0
               } catch (ParserConfigurationException ex) {
      +  104  0
                   LOGGER.debug("", ex);
      +  105  0
                   throw new PomParseException(ex);
      +  106  0
               } catch (SAXException ex) {
      +  107  0
                   LOGGER.debug("", ex);
      +  108  0
                   throw new PomParseException(ex);
      +  109  0
               } catch (FileNotFoundException ex) {
      +  110  0
                   LOGGER.debug("", ex);
      +  111  0
                   throw new PomParseException(ex);
      +  112  0
               } catch (IOException ex) {
      +  113  0
                   LOGGER.debug("", ex);
      +  114  0
                   throw new PomParseException(ex);
      +  115  
               }
      -  112   +  116  
           }
      -  113   +  117  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomUtils.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomUtils.html index 06d6f9a10..340c3a9f8 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomUtils.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.pom.PomUtils.html @@ -227,6 +227,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.PropertyType.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.PropertyType.html index 55e086301..1f3920a66 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.PropertyType.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.PropertyType.html @@ -71,7 +71,7 @@
        * @author Jeremy Long
       27  
        */
      -  28  1034
       public class PropertyType {
      +  28  1111
       public class PropertyType {
       29  
       
       30   @@ -100,7 +100,7 @@
            */
       42  
           public String getValue() {
      -  43  119
               return value;
      +  43  179
               return value;
       44  
           }
       45   @@ -117,15 +117,15 @@
            */
       51  
           public void setValue(String value) {
      -  52  1043
               this.value = value;
      -  53  1043
           }
      +  52  1120
               this.value = value;
      +  53  1120
           }
       54  
           /**
       55  
            * Whether or not the expression is a regex.
       56  
            */
      -  57  1034
           private boolean regex = false;
      +  57  1111
           private boolean regex = false;
       58  
       
       59   @@ -142,7 +142,7 @@
            */
       65  
           public boolean isRegex() {
      -  66  69
               return regex;
      +  66  99
               return regex;
       67  
           }
       68   @@ -161,15 +161,15 @@
            */
       75  
           public void setRegex(boolean value) {
      -  76  1027
               this.regex = value;
      -  77  1027
           }
      +  76  1104
               this.regex = value;
      +  77  1104
           }
       78  
           /**
       79  
            * Indicates case sensitivity.
       80  
            */
      -  81  1034
           private boolean caseSensitive = false;
      +  81  1111
           private boolean caseSensitive = false;
       82  
       
       83   @@ -186,7 +186,7 @@
            */
       89  
           public boolean isCaseSensitive() {
      -  90  59
               return caseSensitive;
      +  90  89
               return caseSensitive;
       91  
           }
       92   @@ -205,8 +205,8 @@
            */
       99  
           public void setCaseSensitive(boolean value) {
      -  100  1028
               this.caseSensitive = value;
      -  101  1028
           }
      +  100  1105
               this.caseSensitive = value;
      +  101  1105
           }
       102  
           //</editor-fold>
       103   @@ -225,11 +225,11 @@
            */
       110  
           public boolean matches(String text) {
      -  111  168
               if (text == null) {
      +  111  198
               if (text == null) {
       112  0
                   return false;
       113  
               }
      -  114  168
               if (this.regex) {
      +  114  198
               if (this.regex) {
       115  
                   Pattern rx;
       116  100
                   if (this.caseSensitive) {
      @@ -242,11 +242,11 @@  121  100
                   return rx.matcher(text).matches();
       122  
               } else {
      -  123  68
                   if (this.caseSensitive) {
      +  123  98
                   if (this.caseSensitive) {
       124  2
                       return value.equals(text);
       125  
                   } else {
      -  126  66
                       return value.equalsIgnoreCase(text);
      +  126  96
                       return value.equalsIgnoreCase(text);
       127  
                   }
       128   @@ -345,6 +345,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionErrorHandler.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionErrorHandler.html index 3b60ad0ce..06713fafe 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionErrorHandler.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionErrorHandler.html @@ -194,6 +194,6 @@
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionHandler.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionHandler.html index 53333e149..753bb2ea7 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionHandler.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionHandler.html @@ -216,13 +216,13 @@
           @Override
       101  
           public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
      -  102  1865
               currentAttributes = attributes;
      -  103  1865
               currentText = new StringBuilder();
      -  104  1865
               if (SUPPRESS.equals(qName)) {
      -  105  419
                   rule = new SuppressionRule();
      -  106  419
                   final String base = currentAttributes.getValue("base");
      -  107  419
                   if (base != null) {
      -  108  419
                       rule.setBase(Boolean.parseBoolean(base));
      +  102  1984
               currentAttributes = attributes;
      +  103  1984
               currentText = new StringBuilder();
      +  104  1984
               if (SUPPRESS.equals(qName)) {
      +  105  440
                   rule = new SuppressionRule();
      +  106  440
                   final String base = currentAttributes.getValue("base");
      +  107  440
                   if (base != null) {
      +  108  440
                       rule.setBase(Boolean.parseBoolean(base));
       109  
                   } else {
       110  0
                       rule.setBase(false);
      @@ -230,7 +230,7 @@
                   }
       112  
               }
      -  113  1865
           }
      +  113  1984
           }
       114  
       
       115   @@ -253,30 +253,30 @@
           @Override
       124  
           public void endElement(String uri, String localName, String qName) throws SAXException {
      -  125  1865
               if (SUPPRESS.equals(qName)) {
      -  126  419
                   suppressionRules.add(rule);
      -  127  419
                   rule = null;
      -  128  1446
               } else if (FILE_PATH.equals(qName)) {
      +  125  1984
               if (SUPPRESS.equals(qName)) {
      +  126  440
                   suppressionRules.add(rule);
      +  127  440
                   rule = null;
      +  128  1544
               } else if (FILE_PATH.equals(qName)) {
       129  75
                   final PropertyType pt = processPropertyType();
       130  75
                   rule.setFilePath(pt);
       131  75
               } else if (SHA1.equals(qName)) {
       132  4
                   rule.setSha1(currentText.toString());
      -  133  1367
               } else if (GAV.equals(qName)) {
      -  134  336
                   final PropertyType pt = processPropertyType();
      -  135  336
                   rule.setGav(pt);
      -  136  336
               } else if (CPE.equals(qName)) {
      -  137  589
                   final PropertyType pt = processPropertyType();
      -  138  589
                   rule.addCpe(pt);
      -  139  589
               } else if (CWE.equals(qName)) {
      +  133  1465
               } else if (GAV.equals(qName)) {
      +  134  357
                   final PropertyType pt = processPropertyType();
      +  135  357
                   rule.setGav(pt);
      +  136  357
               } else if (CPE.equals(qName)) {
      +  137  645
                   final PropertyType pt = processPropertyType();
      +  138  645
                   rule.addCpe(pt);
      +  139  645
               } else if (CWE.equals(qName)) {
       140  0
                   rule.addCwe(currentText.toString());
      -  141  442
               } else if (CVE.equals(qName)) {
      +  141  463
               } else if (CVE.equals(qName)) {
       142  8
                   rule.addCve(currentText.toString());
      -  143  434
               } else if (CVSS_BELOW.equals(qName)) {
      +  143  455
               } else if (CVSS_BELOW.equals(qName)) {
       144  4
                   final float cvss = Float.parseFloat(currentText.toString());
       145  4
                   rule.addCvssBelow(cvss);
       146  
               }
      -  147  1865
           }
      +  147  1984
           }
       148  
       
       149   @@ -299,8 +299,8 @@
           @Override
       158  
           public void characters(char[] ch, int start, int length) throws SAXException {
      -  159  4222
               currentText.append(ch, start, length);
      -  160  4222
           }
      +  159  4460
               currentText.append(ch, start, length);
      +  160  4460
           }
       161  
       
       162   @@ -317,28 +317,28 @@
            */
       168  
           private PropertyType processPropertyType() {
      -  169  1000
               final PropertyType pt = new PropertyType();
      -  170  1000
               pt.setValue(currentText.toString());
      -  171  1000
               if (currentAttributes != null && currentAttributes.getLength() > 0) {
      -  172  1000
                   final String regex = currentAttributes.getValue("regex");
      -  173  1000
                   if (regex != null) {
      -  174  1000
                       pt.setRegex(Boolean.parseBoolean(regex));
      +  169  1077
               final PropertyType pt = new PropertyType();
      +  170  1077
               pt.setValue(currentText.toString());
      +  171  1077
               if (currentAttributes != null && currentAttributes.getLength() > 0) {
      +  172  1077
                   final String regex = currentAttributes.getValue("regex");
      +  173  1077
                   if (regex != null) {
      +  174  1077
                       pt.setRegex(Boolean.parseBoolean(regex));
       175  
                   }
      -  176  1000
                   final String caseSensitive = currentAttributes.getValue("caseSensitive");
      -  177  1000
                   if (caseSensitive != null) {
      -  178  1000
                       pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
      +  176  1077
                   final String caseSensitive = currentAttributes.getValue("caseSensitive");
      +  177  1077
                   if (caseSensitive != null) {
      +  178  1077
                       pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
       179  
                   }
       180  
               }
      -  181  1000
               return pt;
      +  181  1077
               return pt;
       182  
           }
       183  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionParseException.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionParseException.html index 785eb63ab..07c94057a 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionParseException.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionParseException.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      SuppressionParseException
      50%
      4/8
      N/A
      1
      SuppressionParseException
      25%
      2/8
      N/A
      1
       
      @@ -107,8 +107,8 @@
            */
       46  
           public SuppressionParseException(String msg) {
      -  47  0
               super(msg);
      -  48  0
           }
      +  47  1
               super(msg);
      +  48  1
           }
       49  
       
       50   @@ -123,8 +123,8 @@
            */
       55  
           public SuppressionParseException(Throwable ex) {
      -  56  1
               super(ex);
      -  57  1
           }
      +  56  0
               super(ex);
      +  57  0
           }
       58  
       
       59   @@ -141,12 +141,12 @@
            */
       65  
           public SuppressionParseException(String msg, Throwable ex) {
      -  66  1
               super(msg, ex);
      -  67  1
           }
      +  66  0
               super(msg, ex);
      +  67  0
           }
       68  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionParser.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionParser.html index 873ff2965..322ac2901 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionParser.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionParser.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      SuppressionParser
      64%
      59/92
      50%
      5/10
      12.667
      SuppressionParser
      61%
      57/93
      50%
      5/10
      12.667
       
      @@ -177,14 +177,14 @@
            */
       81  
           public List<SuppressionRule> parseSuppressionRules(File file) throws SuppressionParseException {
      -  82  4
               FileInputStream fis = null;
      +  82  3
               FileInputStream fis = null;
       83  
               try {
      -  84  4
                   fis = new FileInputStream(file);
      +  84  3
                   fis = new FileInputStream(file);
       85  3
                   return parseSuppressionRules(fis);
      -  86  1
               } catch (IOException ex) {
      -  87  1
                   LOGGER.debug("", ex);
      -  88  1
                   throw new SuppressionParseException(ex);
      +  86  0
               } catch (IOException ex) {
      +  87  0
                   LOGGER.debug("", ex);
      +  88  0
                   throw new SuppressionParseException(ex);
       89  3
               } catch (SAXException ex) {
       90  
                   try {
      @@ -204,13 +204,13 @@  102  6
                   return parseOldSuppressionRules(fis);
       103  
               } finally {
      -  104  4
                   if (fis != null) {
      +  104  3
                   if (fis != null) {
       105  
                       try {
       106  3
                           fis.close();
       107  0
                       } catch (IOException ex) {
       108  0
                           LOGGER.debug("Unable to close stream", ex);
      -  109  4
                       }
      +  109  3
                       }
       110  
                   }
       111   @@ -247,132 +247,133 @@  128  10
                   final SAXParserFactory factory = SAXParserFactory.newInstance();
       129  10
                   factory.setNamespaceAware(true);
       130  10
                   factory.setValidating(true);
      -  131  10
                   final SAXParser saxParser = factory.newSAXParser();
      -  132  10
                   saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
      -  133  10
                   saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
      -  134  10
                   final XMLReader xmlReader = saxParser.getXMLReader();
      -  135  10
                   xmlReader.setErrorHandler(new SuppressionErrorHandler());
      -  136  10
                   xmlReader.setContentHandler(handler);
      -  137   +  131  10
                   factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +  132  10
                   final SAXParser saxParser = factory.newSAXParser();
      +  133  10
                   saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
      +  134  10
                   saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
      +  135  10
                   final XMLReader xmlReader = saxParser.getXMLReader();
      +  136  10
                   xmlReader.setErrorHandler(new SuppressionErrorHandler());
      +  137  10
                   xmlReader.setContentHandler(handler);
      +  138  
       
      -  138  10
                   final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      -  139  10
                   final InputSource in = new InputSource(reader);
      -  140   -
                   //in.setEncoding("UTF-8");
      +  139  10
                   final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      +  140  10
                   final InputSource in = new InputSource(reader);
       141   +
                   //in.setEncoding("UTF-8");
      +  142  
       
      -  142  10
                   xmlReader.parse(in);
      -  143   +  143  10
                   xmlReader.parse(in);
      +  144  
       
      -  144  14
                   return handler.getSuppressionRules();
      -  145  0
               } catch (ParserConfigurationException ex) {
      -  146  0
                   LOGGER.debug("", ex);
      -  147  0
                   throw new SuppressionParseException(ex);
      -  148  3
               } catch (SAXException ex) {
      -  149  3
                   if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) {
      -  150  3
                       throw ex;
      -  151   +  145  14
                   return handler.getSuppressionRules();
      +  146  0
               } catch (ParserConfigurationException ex) {
      +  147  0
                   LOGGER.debug("", ex);
      +  148  0
                   throw new SuppressionParseException(ex);
      +  149  3
               } catch (SAXException ex) {
      +  150  3
                   if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) {
      +  151  3
                       throw ex;
      +  152  
                   } else {
      -  152  0
                       LOGGER.debug("", ex);
      -  153  0
                       throw new SuppressionParseException(ex);
      -  154   +  153  0
                       LOGGER.debug("", ex);
      +  154  0
                       throw new SuppressionParseException(ex);
      +  155  
                   }
      -  155  0
               } catch (FileNotFoundException ex) {
      -  156  0
                   LOGGER.debug("", ex);
      -  157  0
                   throw new SuppressionParseException(ex);
      -  158  0
               } catch (IOException ex) {
      -  159  0
                   LOGGER.debug("", ex);
      -  160  0
                   throw new SuppressionParseException(ex);
      -  161   +  156  0
               } catch (FileNotFoundException ex) {
      +  157  0
                   LOGGER.debug("", ex);
      +  158  0
                   throw new SuppressionParseException(ex);
      +  159  0
               } catch (IOException ex) {
      +  160  0
                   LOGGER.debug("", ex);
      +  161  0
                   throw new SuppressionParseException(ex);
      +  162  
               } finally {
      -  162  10
                   if (schemaStream != null) {
      -  163   +  163  10
                   if (schemaStream != null) {
      +  164  
                       try {
      -  164  10
                           schemaStream.close();
      -  165  0
                       } catch (IOException ex) {
      -  166  0
                           LOGGER.debug("Error closing suppression file stream", ex);
      -  167  13
                       }
      -  168   -
                   }
      +  165  10
                           schemaStream.close();
      +  166  0
                       } catch (IOException ex) {
      +  167  0
                           LOGGER.debug("Error closing suppression file stream", ex);
      +  168  13
                       }
       169   -
               }
      -  170   -
           }
      -  171   -
       
      -  172   -
           /**
      -  173   -
            * Parses the given XML stream and returns a list of the suppression rules
      -  174   -
            * contained.
      -  175   -
            *
      -  176   -
            * @param inputStream an InputStream containing suppression rues
      -  177   -
            * @return a list of suppression rules
      -  178   -
            * @throws SuppressionParseException if the XML cannot be parsed
      -  179   -
            */
      -  180   -
           private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException {
      -  181  3
               InputStream schemaStream = null;
      -  182   -
               try {
      -  183  3
                   schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA);
      -  184  3
                   final SuppressionHandler handler = new SuppressionHandler();
      -  185  3
                   final SAXParserFactory factory = SAXParserFactory.newInstance();
      -  186  3
                   factory.setNamespaceAware(true);
      -  187  3
                   factory.setValidating(true);
      -  188  3
                   final SAXParser saxParser = factory.newSAXParser();
      -  189  3
                   saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
      -  190  3
                   saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
      -  191  3
                   final XMLReader xmlReader = saxParser.getXMLReader();
      -  192  3
                   xmlReader.setErrorHandler(new SuppressionErrorHandler());
      -  193  3
                   xmlReader.setContentHandler(handler);
      -  194   -
       
      -  195  3
                   final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      -  196  3
                   final InputSource in = new InputSource(reader);
      -  197   -
       
      -  198  3
                   xmlReader.parse(in);
      -  199   -
       
      -  200  6
                   return handler.getSuppressionRules();
      -  201  0
               } catch (ParserConfigurationException ex) {
      -  202  0
                   LOGGER.debug("", ex);
      -  203  0
                   throw new SuppressionParseException(ex);
      -  204  0
               } catch (SAXException ex) {
      -  205  0
                   LOGGER.debug("", ex);
      -  206  0
                   throw new SuppressionParseException(ex);
      -  207  0
               } catch (FileNotFoundException ex) {
      -  208  0
                   LOGGER.debug("", ex);
      -  209  0
                   throw new SuppressionParseException(ex);
      -  210  0
               } catch (IOException ex) {
      -  211  0
                   LOGGER.debug("", ex);
      -  212  0
                   throw new SuppressionParseException(ex);
      -  213   -
               } finally {
      -  214  3
                   if (schemaStream != null) {
      -  215   -
                       try {
      -  216  3
                           schemaStream.close();
      -  217  0
                       } catch (IOException ex) {
      -  218  0
                           LOGGER.debug("Error closing old suppression file stream", ex);
      -  219  3
                       }
      -  220  
                   }
      -  221   +  170  
               }
      -  222   +  171  
           }
      +  172   +
       
      +  173   +
           /**
      +  174   +
            * Parses the given XML stream and returns a list of the suppression rules
      +  175   +
            * contained.
      +  176   +
            *
      +  177   +
            * @param inputStream an InputStream containing suppression rues
      +  178   +
            * @return a list of suppression rules
      +  179   +
            * @throws SuppressionParseException if the XML cannot be parsed
      +  180   +
            */
      +  181   +
           private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException {
      +  182  3
               InputStream schemaStream = null;
      +  183   +
               try {
      +  184  3
                   schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA);
      +  185  3
                   final SuppressionHandler handler = new SuppressionHandler();
      +  186  3
                   final SAXParserFactory factory = SAXParserFactory.newInstance();
      +  187  3
                   factory.setNamespaceAware(true);
      +  188  3
                   factory.setValidating(true);
      +  189  3
                   final SAXParser saxParser = factory.newSAXParser();
      +  190  3
                   saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
      +  191  3
                   saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
      +  192  3
                   final XMLReader xmlReader = saxParser.getXMLReader();
      +  193  3
                   xmlReader.setErrorHandler(new SuppressionErrorHandler());
      +  194  3
                   xmlReader.setContentHandler(handler);
      +  195   +
       
      +  196  3
                   final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      +  197  3
                   final InputSource in = new InputSource(reader);
      +  198   +
       
      +  199  3
                   xmlReader.parse(in);
      +  200   +
       
      +  201  6
                   return handler.getSuppressionRules();
      +  202  0
               } catch (ParserConfigurationException ex) {
      +  203  0
                   LOGGER.debug("", ex);
      +  204  0
                   throw new SuppressionParseException(ex);
      +  205  0
               } catch (SAXException ex) {
      +  206  0
                   LOGGER.debug("", ex);
      +  207  0
                   throw new SuppressionParseException(ex);
      +  208  0
               } catch (FileNotFoundException ex) {
      +  209  0
                   LOGGER.debug("", ex);
      +  210  0
                   throw new SuppressionParseException(ex);
      +  211  0
               } catch (IOException ex) {
      +  212  0
                   LOGGER.debug("", ex);
      +  213  0
                   throw new SuppressionParseException(ex);
      +  214   +
               } finally {
      +  215  3
                   if (schemaStream != null) {
      +  216   +
                       try {
      +  217  3
                           schemaStream.close();
      +  218  0
                       } catch (IOException ex) {
      +  219  0
                           LOGGER.debug("Error closing old suppression file stream", ex);
      +  220  3
                       }
      +  221   +
                   }
      +  222   +
               }
       223   +
           }
      +  224  
       }
      - + diff --git a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionRule.html b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionRule.html index 2691ebfdf..7fce52a86 100644 --- a/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionRule.html +++ b/dependency-check-core/cobertura/org.owasp.dependencycheck.xml.suppression.SuppressionRule.html @@ -77,7 +77,7 @@
        * @author Jeremy Long
       30  
        */
      -  31  434
       public class SuppressionRule {
      +  31  455
       public class SuppressionRule {
       32  
       
       33   @@ -168,7 +168,7 @@
            * A list of CPEs to suppression
       79  
            */
      -  80  434
           private List<PropertyType> cpe = new ArrayList<PropertyType>();
      +  80  455
           private List<PropertyType> cpe = new ArrayList<PropertyType>();
       81  
       
       82   @@ -216,8 +216,8 @@
            */
       105  
           public void addCpe(PropertyType cpe) {
      -  106  596
               this.cpe.add(cpe);
      -  107  596
           }
      +  106  652
               this.cpe.add(cpe);
      +  107  652
           }
       108  
       
       109   @@ -241,7 +241,7 @@
            * The list of cvssBelow scores.
       119  
            */
      -  120  434
           private List<Float> cvssBelow = new ArrayList<Float>();
      +  120  455
           private List<Float> cvssBelow = new ArrayList<Float>();
       121  
       
       122   @@ -314,7 +314,7 @@
            * The list of cwe entries to suppress.
       159  
            */
      -  160  434
           private List<String> cwe = new ArrayList<String>();
      +  160  455
           private List<String> cwe = new ArrayList<String>();
       161  
       
       162   @@ -387,7 +387,7 @@
            * The list of cve entries to suppress.
       199  
            */
      -  200  434
           private List<String> cve = new ArrayList<String>();
      +  200  455
           private List<String> cve = new ArrayList<String>();
       201  
       
       202   @@ -460,7 +460,7 @@
            * A Maven GAV to suppression.
       239  
            */
      -  240  434
           private PropertyType gav = null;
      +  240  455
           private PropertyType gav = null;
       241  
       
       242   @@ -492,8 +492,8 @@
            */
       256  
           public void setGav(PropertyType gav) {
      -  257  337
               this.gav = gav;
      -  258  337
           }
      +  257  358
               this.gav = gav;
      +  258  358
           }
       259  
       
       260   @@ -554,8 +554,8 @@
            */
       289  
           public void setBase(boolean base) {
      -  290  421
               this.base = base;
      -  291  421
           }
      +  290  442
               this.base = base;
      +  291  442
           }
       292  
       
       293   @@ -572,27 +572,27 @@
            */
       299  
           public void process(Dependency dependency) {
      -  300  466
               if (filePath != null && !filePath.matches(dependency.getFilePath())) {
      +  300  490
               if (filePath != null && !filePath.matches(dependency.getFilePath())) {
       301  48
                   return;
       302  
               }
      -  303  418
               if (sha1 != null && !sha1.equalsIgnoreCase(dependency.getSha1sum())) {
      +  303  442
               if (sha1 != null && !sha1.equalsIgnoreCase(dependency.getSha1sum())) {
       304  1
                   return;
       305  
               }
      -  306  417
               if (gav != null) {
      -  307  385
                   final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
      -  308  385
                   boolean gavFound = false;
      -  309  677
                   while (itr.hasNext()) {
      -  310  293
                       final Identifier i = itr.next();
      -  311  293
                       if (identifierMatches("maven", this.gav, i)) {
      +  306  441
               if (gav != null) {
      +  307  409
                   final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
      +  308  409
                   boolean gavFound = false;
      +  309  821
                   while (itr.hasNext()) {
      +  310  413
                       final Identifier i = itr.next();
      +  311  413
                       if (identifierMatches("maven", this.gav, i)) {
       312  1
                           gavFound = true;
       313  1
                           break;
       314  
                       }
      -  315  292
                   }
      -  316  385
                   if (!gavFound) {
      -  317  384
                       return;
      +  315  412
                   }
      +  316  409
                   if (!gavFound) {
      +  317  408
                       return;
       318  
                   }
       319   @@ -601,10 +601,10 @@
       
       321  33
               if (this.hasCpe()) {
       322  28
                   final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
      -  323  74
                   while (itr.hasNext()) {
      -  324  46
                       final Identifier i = itr.next();
      -  325  46
                       for (PropertyType c : this.cpe) {
      -  326  60
                           if (identifierMatches("cpe", c, i)) {
      +  323  86
                   while (itr.hasNext()) {
      +  324  58
                       final Identifier i = itr.next();
      +  325  58
                       for (PropertyType c : this.cpe) {
      +  326  90
                           if (identifierMatches("cpe", c, i)) {
       327  7
                               if (!isBase()) {
       328  4
                                   dependency.addSuppressedIdentifier(i);
       329   @@ -613,8 +613,8 @@  331  7
                               break;
       332  
                           }
      -  333  53
                       }
      -  334  46
                   }
      +  333  83
                       }
      +  334  58
                   }
       335  
               }
       336  33
               if (hasCve() || hasCwe() || hasCvssBelow()) {
      @@ -682,7 +682,7 @@
            */
       383  
           boolean cpeHasNoVersion(PropertyType c) {
      -  384  64
               return !c.isRegex() && countCharacter(c.getValue(), ':') <= 3;
      +  384  94
               return !c.isRegex() && countCharacter(c.getValue(), ':') <= 3;
       385  
           }
       386   @@ -703,14 +703,14 @@
            */
       394  
           int countCharacter(String str, char c) {
      -  395  62
               int count = 0;
      -  396  62
               int pos = str.indexOf(c) + 1;
      -  397  254
               while (pos > 0) {
      -  398  192
                   count += 1;
      -  399  192
                   pos = str.indexOf(c, pos) + 1;
      +  395  92
               int count = 0;
      +  396  92
               int pos = str.indexOf(c) + 1;
      +  397  374
               while (pos > 0) {
      +  398  282
                   count += 1;
      +  399  282
                   pos = str.indexOf(c, pos) + 1;
       400  
               }
      -  401  62
               return count;
      +  401  92
               return count;
       402  
           }
       403   @@ -733,24 +733,24 @@
            */
       412  
           boolean identifierMatches(String identifierType, PropertyType suppressionEntry, Identifier identifier) {
      -  413  362
               if (identifierType.equals(identifier.getType())) {
      -  414  67
                   if (suppressionEntry.matches(identifier.getValue())) {
      +  413  512
               if (identifierType.equals(identifier.getType())) {
      +  414  97
                   if (suppressionEntry.matches(identifier.getValue())) {
       415  5
                       return true;
      -  416  62
                   } else if ("cpe".equals(identifierType) && cpeHasNoVersion(suppressionEntry)) {
      -  417  55
                       if (suppressionEntry.isCaseSensitive()) {
      +  416  92
                   } else if ("cpe".equals(identifierType) && cpeHasNoVersion(suppressionEntry)) {
      +  417  85
                       if (suppressionEntry.isCaseSensitive()) {
       418  0
                           return identifier.getValue().startsWith(suppressionEntry.getValue());
       419  
                       } else {
      -  420  55
                           final String id = identifier.getValue().toLowerCase();
      -  421  55
                           final String check = suppressionEntry.getValue().toLowerCase();
      -  422  55
                           return id.startsWith(check);
      +  420  85
                           final String id = identifier.getValue().toLowerCase();
      +  421  85
                           final String check = suppressionEntry.getValue().toLowerCase();
      +  422  85
                           return id.startsWith(check);
       423  
                       }
       424  
                   }
       425  
               }
      -  426  302
               return false;
      +  426  422
               return false;
       427  
           }
       428   @@ -823,6 +823,6 @@
       }
      - + diff --git a/dependency-check-core/cpd.html b/dependency-check-core/cpd.html index 01479e4e7..344244625 100644 --- a/dependency-check-core/cpd.html +++ b/dependency-check-core/cpd.html @@ -1,13 +1,13 @@ - + dependency-check-core – CPD Results @@ -52,7 +52,7 @@ @@ -247,7 +247,7 @@ Line org\owasp\dependencycheck\data\update\CpeUpdater.java -161 +169 org\owasp\dependencycheck\data\update\nvd\DownloadTask.java 271 @@ -336,46 +336,11 @@ File Line -org\owasp\dependencycheck\xml\suppression\SuppressionParser.java -126 - -org\owasp\dependencycheck\xml\suppression\SuppressionParser.java -183 - -
      -
                  schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
      -            final SuppressionHandler handler = new SuppressionHandler();
      -            final SAXParserFactory factory = SAXParserFactory.newInstance();
      -            factory.setNamespaceAware(true);
      -            factory.setValidating(true);
      -            final SAXParser saxParser = factory.newSAXParser();
      -            saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
      -            saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
      -            final XMLReader xmlReader = saxParser.getXMLReader();
      -            xmlReader.setErrorHandler(new SuppressionErrorHandler());
      -            xmlReader.setContentHandler(handler);
      -
      -            final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      -            final InputSource in = new InputSource(reader);
      -            //in.setEncoding("UTF-8");
      -
      -            xmlReader.parse(in);
      -
      -            return handler.getSuppressionRules();
      -        } catch (ParserConfigurationException ex) {
      -            LOGGER.debug("", ex);
      -            throw new SuppressionParseException(ex);
      -        } catch (SAXException ex) {
      - - - - - - + - +
      FileLine
      org\owasp\dependencycheck\analyzer\ArchiveAnalyzer.java182
      180
      org\owasp\dependencycheck\analyzer\PythonDistributionAnalyzer.java247
      248
          public void initializeFileTypeAnalyzer() throws InitializationException {
      @@ -406,7 +371,86 @@
            * files
            */
           @Override
      -    public void close() throws Exception {
      + public void close() throws Exception { + + + + + + + + + + +
      FileLine
      org\owasp\dependencycheck\xml\suppression\SuppressionParser.java131
      org\owasp\dependencycheck\xml\suppression\SuppressionParser.java188
      +
      +
                  factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
      +            final SAXParser saxParser = factory.newSAXParser();
      +            saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
      +            saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
      +            final XMLReader xmlReader = saxParser.getXMLReader();
      +            xmlReader.setErrorHandler(new SuppressionErrorHandler());
      +            xmlReader.setContentHandler(handler);
      +
      +            final Reader reader = new InputStreamReader(inputStream, "UTF-8");
      +            final InputSource in = new InputSource(reader);
      +            //in.setEncoding("UTF-8");
      +
      +            xmlReader.parse(in);
      +
      +            return handler.getSuppressionRules();
      +        } catch (ParserConfigurationException ex) {
      +            LOGGER.debug("", ex);
      +            throw new SuppressionParseException(ex);
      +        } catch (SAXException ex) {
      + + + + + + + + + + +
      FileLine
      org\owasp\dependencycheck\analyzer\JarAnalyzer.java917
      org\owasp\dependencycheck\analyzer\PythonDistributionAnalyzer.java263
      +
      +
                      setEnabled(false);
      +                throw new InitializationException(msg);
      +            }
      +        } catch (IOException ex) {
      +            setEnabled(false);
      +            throw new InitializationException("Unable to create a temporary file", ex);
      +        }
      +    }
      +
      +    /**
      +     * Deletes any files extracted from the JAR during analysis.
      +     */
      +    @Override
      +    public void close() {
      +        if (tempFileLocation != null && tempFileLocation.exists()) {
      +            LOGGER.debug("Attempting to delete temporary files");
      +            final boolean success = FileUtils.delete(tempFileLocation);
      +            if (!success && tempFileLocation.exists()) {
      +                final String[] l = tempFileLocation.list();
      +                if (l != null && l.length > 0) {
      +                    LOGGER.warn("Failed to delete some temporary files, see the log for more details");
      +                }
      +            }
      +        }
      +    }
      +
      +    /**
      +     * Determines if the key value pair from the manifest is for an "import"
      +     * type entry for package names.
      +     *
      +     * @param key the key from the manifest
      +     * @param value the value from the manifest
      +     * @return true or false depending on if it is believed the entry is an
      +     * "import" entry
      +     */
      +    private boolean isImportPackage(String key, String value) {
      diff --git a/dependency-check-core/dependency-analysis.html b/dependency-check-core/dependency-analysis.html index 62f2ec4f1..285011a84 100644 --- a/dependency-check-core/dependency-analysis.html +++ b/dependency-check-core/dependency-analysis.html @@ -1,13 +1,13 @@ - + dependency-check-core – Dependencies Report @@ -52,7 +52,7 @@ @@ -268,7 +268,7 @@ org.owasp dependency-check-utils -1.4.3 +1.4.4 compile jar @@ -364,7 +364,7 @@ com.sun.mail mailapi -1.5.5 +1.5.6 compile jar diff --git a/dependency-check-core/dependency-updates-report.html b/dependency-check-core/dependency-updates-report.html index 86d3b269d..e0d78f4ab 100644 --- a/dependency-check-core/dependency-updates-report.html +++ b/dependency-check-core/dependency-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-core – Dependency Updates Report @@ -52,7 +52,7 @@ @@ -243,7 +243,7 @@ # of dependencies using the latest version available -24 +25 # of dependencies where the next version available is smaller than an incremental version update @@ -251,7 +251,7 @@ # of dependencies where the next version available is an incremental version update -8 +7 # of dependencies where the next version available is a minor version update @@ -324,15 +324,15 @@ 1.4.177 - + com.sun.mail mailapi -1.5.5 +1.5.6 jar -1.5.6 + @@ -528,16 +528,16 @@ - + org.apache.maven.plugin-tools maven-plugin-annotations -3.4 +3.5 jar -3.5 + @@ -612,7 +612,7 @@ 1.25 - + org.jsoup jsoup 1.9.2 @@ -621,7 +621,7 @@ jar - +1.10.1 @@ -846,7 +846,7 @@ org.owasp dependency-check-utils -1.4.3 +1.4.4 compile jar @@ -1054,7 +1054,7 @@ jar Newer versions -1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192 Latest Minor +1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192
      1.4.193 Latest Minor

      com.hazelcast:hazelcast

      @@ -1081,13 +1081,13 @@ -
      jar
      Newer versions2.5.1 Next Incremental
      2.6 Next Minor
      2.6.1
      2.6.2
      2.6.3
      2.6.4
      2.6.5
      2.6.6
      2.6.7
      2.6.8
      2.6.9
      3.0-RC1
      3.0-RC2 Latest Minor
      3.0 Next Major
      3.0.1
      3.0.2
      3.0.3
      3.1
      3.1.1
      3.1.2
      3.1.3
      3.1.4
      3.1.5
      3.1.6
      3.1.7
      3.1.8
      3.2-RC1
      3.2-RC2
      3.2
      3.2.1
      3.2.2
      3.2.3
      3.2.4
      3.2.5
      3.2.6
      3.3-RC1
      3.3-RC2
      3.3-RC3
      3.3
      3.3-EA
      3.3-EA2
      3.3.1
      3.3.2
      3.3.3
      3.3.4
      3.3.5
      3.4
      3.4-EA
      3.4.1
      3.4.2
      3.4.5
      3.4.6
      3.4.7
      3.4.8
      3.5-EA
      3.5.1
      3.5.2
      3.5.3
      3.5.4
      3.5.5
      3.6-RC1
      3.6
      3.6-EA
      3.6-EA2
      3.6-EA3
      3.6.1
      3.6.2
      3.6.3
      3.6.4
      3.6.5
      3.7
      3.7-EA
      3.7.1 Latest Major
      +2.5.1 Next Incremental
      2.6 Next Minor
      2.6.1
      2.6.2
      2.6.3
      2.6.4
      2.6.5
      2.6.6
      2.6.7
      2.6.8
      2.6.9
      3.0-RC1
      3.0-RC2 Latest Minor
      3.0 Next Major
      3.0.1
      3.0.2
      3.0.3
      3.1
      3.1.1
      3.1.2
      3.1.3
      3.1.4
      3.1.5
      3.1.6
      3.1.7
      3.1.8
      3.2-RC1
      3.2-RC2
      3.2
      3.2.1
      3.2.2
      3.2.3
      3.2.4
      3.2.5
      3.2.6
      3.3-RC1
      3.3-RC2
      3.3-RC3
      3.3
      3.3-EA
      3.3-EA2
      3.3.1
      3.3.2
      3.3.3
      3.3.4
      3.3.5
      3.4
      3.4-EA
      3.4.1
      3.4.2
      3.4.5
      3.4.6
      3.4.7
      3.4.8
      3.5-EA
      3.5.1
      3.5.2
      3.5.3
      3.5.4
      3.5.5
      3.6-RC1
      3.6
      3.6-EA
      3.6-EA2
      3.6-EA3
      3.6.1
      3.6.2
      3.6.3
      3.6.4
      3.6.5
      3.6.6
      3.7
      3.7-EA
      3.7.1
      3.7.2 Latest Major

      com.sun.mail:mailapi

      - + @@ -1096,7 +1096,7 @@ - + @@ -1105,10 +1105,7 @@ - - - -
      Status There is at least one newer incremental version available. Incremental updates are typically passive.
       No newer versions available.
      Group Id com.sun.mail
      mailapi
      Current Version1.5.5
      1.5.6
      Scope
      Typejar
      Newer versions1.5.6 Next Incremental
      +jar

      com.thoughtworks.xstream:xstream

      @@ -1336,7 +1333,7 @@ -
      jar
      Newer versions1.5 Next Minor
      1.5.1
      1.5.2
      1.5.3
      1.5.4
      1.5.5
      1.5.6
      1.6.0
      1.6.1
      1.6.2
      1.6.3
      1.6.4
      1.7.0
      1.7.1
      1.7.2
      1.7.3 Latest Minor
      +1.5 Next Minor
      1.5.1
      1.5.2
      1.5.3
      1.5.4
      1.5.5
      1.5.6
      1.6.0
      1.6.1
      1.6.2
      1.6.3
      1.6.4
      1.7.0
      1.7.1
      1.7.2
      1.7.3
      1.7.4 Latest Minor

      org.apache.axis2:axis2-spring

      @@ -1363,7 +1360,7 @@ -
      jar
      Newer versions1.5 Next Minor
      1.5.1
      1.5.2
      1.5.3
      1.5.4
      1.5.5
      1.5.6
      1.6.0
      1.6.1
      1.6.2
      1.6.3
      1.6.4
      1.7.0
      1.7.1
      1.7.2
      1.7.3 Latest Minor
      +1.5 Next Minor
      1.5.1
      1.5.2
      1.5.3
      1.5.4
      1.5.5
      1.5.6
      1.6.0
      1.6.1
      1.6.2
      1.6.3
      1.6.4
      1.7.0
      1.7.1
      1.7.2
      1.7.3
      1.7.4 Latest Minor

      org.apache.commons:commons-compress

      @@ -1414,7 +1411,7 @@ -
      jar
      Newer versions3.4 Next Minor
      +3.4 Next Minor
      3.5 Latest Minor

      org.apache.geronimo.daytrader:daytrader-ear

      @@ -1465,7 +1462,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-core

      @@ -1492,7 +1489,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-queryparser

      @@ -1519,7 +1516,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-test-framework

      @@ -1546,7 +1543,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.maven:maven-core

      @@ -1648,7 +1645,7 @@
      - + @@ -1657,7 +1654,7 @@ - + @@ -1666,10 +1663,7 @@ - - - -
      Status There is at least one newer minor version available. Minor updates are sometimes passive.
       No newer versions available.
      Group Id org.apache.maven.plugin-tools
      maven-plugin-annotations
      Current Version3.4
      3.5
      Scope
      Typejar
      Newer versions3.5 Next Minor
      +jar

      org.apache.maven.reporting:maven-reporting-api

      @@ -1801,7 +1795,7 @@ -
      jar
      Newer versions2.1.6 Next Incremental
      2.1.8
      2.1.8.1 Latest Incremental
      2.2.1 Next Minor
      2.2.1.1
      2.2.3
      2.2.3.1
      2.3.1
      2.3.1.1
      2.3.1.2
      2.3.3
      2.3.4
      2.3.4.1
      2.3.7
      2.3.8
      2.3.12
      2.3.14
      2.3.14.1
      2.3.14.2
      2.3.14.3
      2.3.15
      2.3.15.1
      2.3.15.2
      2.3.15.3
      2.3.16
      2.3.16.1
      2.3.16.2
      2.3.16.3
      2.3.20
      2.3.20.1
      2.3.20.3
      2.3.24
      2.3.24.1
      2.3.24.3
      2.3.28
      2.3.28.1
      2.3.29
      2.3.30
      2.5-BETA1
      2.5-BETA2
      2.5-BETA3
      2.5
      2.5.1
      2.5.2 Latest Minor
      +2.1.6 Next Incremental
      2.1.8
      2.1.8.1 Latest Incremental
      2.2.1 Next Minor
      2.2.1.1
      2.2.3
      2.2.3.1
      2.3.1
      2.3.1.1
      2.3.1.2
      2.3.3
      2.3.4
      2.3.4.1
      2.3.7
      2.3.8
      2.3.12
      2.3.14
      2.3.14.1
      2.3.14.2
      2.3.14.3
      2.3.15
      2.3.15.1
      2.3.15.2
      2.3.15.3
      2.3.16
      2.3.16.1
      2.3.16.2
      2.3.16.3
      2.3.20
      2.3.20.1
      2.3.20.3
      2.3.24
      2.3.24.1
      2.3.24.3
      2.3.28
      2.3.28.1
      2.3.29
      2.3.30
      2.3.31
      2.5-BETA1
      2.5-BETA2
      2.5-BETA3
      2.5
      2.5.1
      2.5.2
      2.5.5 Latest Minor

      org.apache.velocity:velocity

      @@ -1954,13 +1948,13 @@ -
      jar
      Newer versions1.25 Next Minor
      1.26
      1.27 Latest Minor
      +1.25 Next Minor
      1.26
      1.27
      1.28
      1.29 Latest Minor

      org.jsoup:jsoup

      - + @@ -1978,7 +1972,10 @@ -
      Status No newer versions available.
       There is at least one newer minor version available. Minor updates are sometimes passive.
      Group Id org.jsoup
      Typejar
      +jar + +Newer versions +1.10.1 Next Minor

      org.mortbay.jetty:jetty

      @@ -2020,7 +2017,7 @@ - + @@ -2128,7 +2125,7 @@ -
      dependency-check-utils
      Current Version1.4.3
      1.4.4
      Scope compile
      jar
      Newer versions2.5.6 Next Incremental
      2.5.6.SEC01
      2.5.6.SEC02
      2.5.6.SEC03 Latest Incremental
      3.0.0.RELEASE Next Major
      3.0.1.RELEASE
      3.0.2.RELEASE
      3.0.3.RELEASE
      3.0.4.RELEASE
      3.0.5.RELEASE
      3.0.6.RELEASE
      3.0.7.RELEASE
      3.1.0.RELEASE
      3.1.1.RELEASE
      3.1.2.RELEASE
      3.2.0.RELEASE
      3.2.1.RELEASE
      3.2.2.RELEASE
      3.2.3.RELEASE
      3.2.4.RELEASE
      3.2.5.RELEASE
      3.2.6.RELEASE
      3.2.7.RELEASE
      3.2.8.RELEASE
      3.2.9.RELEASE
      3.2.10.RELEASE
      3.2.11.RELEASE
      3.2.12.RELEASE
      3.2.13.RELEASE
      3.2.14.RELEASE
      3.2.15.RELEASE
      3.2.16.RELEASE
      3.2.17.RELEASE
      4.0.0.RELEASE
      4.0.1.RELEASE
      4.0.2.RELEASE
      4.0.3.RELEASE
      4.0.4.RELEASE
      4.0.5.RELEASE
      4.0.6.RELEASE
      4.0.7.RELEASE
      4.0.8.RELEASE
      4.0.9.RELEASE
      4.1.0.RELEASE
      4.1.1.RELEASE
      4.1.2.RELEASE
      4.1.3.RELEASE
      4.1.4.RELEASE
      4.1.5.RELEASE
      4.1.6.RELEASE
      4.1.7.RELEASE
      4.1.8.RELEASE
      4.1.9.RELEASE
      4.2.0.RELEASE
      4.2.1.RELEASE
      4.2.2.RELEASE
      4.2.3.RELEASE
      4.2.4.RELEASE
      4.2.5.RELEASE
      4.2.6.RELEASE
      4.2.7.RELEASE
      4.3.0.RELEASE
      4.3.1.RELEASE
      4.3.2.RELEASE Latest Major
      +2.5.6 Next Incremental
      2.5.6.SEC01
      2.5.6.SEC02
      2.5.6.SEC03 Latest Incremental
      3.0.0.RELEASE Next Major
      3.0.1.RELEASE
      3.0.2.RELEASE
      3.0.3.RELEASE
      3.0.4.RELEASE
      3.0.5.RELEASE
      3.0.6.RELEASE
      3.0.7.RELEASE
      3.1.0.RELEASE
      3.1.1.RELEASE
      3.1.2.RELEASE
      3.2.0.RELEASE
      3.2.1.RELEASE
      3.2.2.RELEASE
      3.2.3.RELEASE
      3.2.4.RELEASE
      3.2.5.RELEASE
      3.2.6.RELEASE
      3.2.7.RELEASE
      3.2.8.RELEASE
      3.2.9.RELEASE
      3.2.10.RELEASE
      3.2.11.RELEASE
      3.2.12.RELEASE
      3.2.13.RELEASE
      3.2.14.RELEASE
      3.2.15.RELEASE
      3.2.16.RELEASE
      3.2.17.RELEASE
      4.0.0.RELEASE
      4.0.1.RELEASE
      4.0.2.RELEASE
      4.0.3.RELEASE
      4.0.4.RELEASE
      4.0.5.RELEASE
      4.0.6.RELEASE
      4.0.7.RELEASE
      4.0.8.RELEASE
      4.0.9.RELEASE
      4.1.0.RELEASE
      4.1.1.RELEASE
      4.1.2.RELEASE
      4.1.3.RELEASE
      4.1.4.RELEASE
      4.1.5.RELEASE
      4.1.6.RELEASE
      4.1.7.RELEASE
      4.1.8.RELEASE
      4.1.9.RELEASE
      4.2.0.RELEASE
      4.2.1.RELEASE
      4.2.2.RELEASE
      4.2.3.RELEASE
      4.2.4.RELEASE
      4.2.5.RELEASE
      4.2.6.RELEASE
      4.2.7.RELEASE
      4.2.8.RELEASE
      4.3.0.RELEASE
      4.3.1.RELEASE
      4.3.2.RELEASE
      4.3.3.RELEASE Latest Major

      org.springframework.retry:spring-retry

      @@ -2155,7 +2152,7 @@ -
      jar
      Newer versions1.1.1.RELEASE Next Incremental
      1.1.2.RELEASE
      1.1.3.RELEASE Latest Incremental
      +1.1.1.RELEASE Next Incremental
      1.1.2.RELEASE
      1.1.3.RELEASE
      1.1.4.RELEASE Latest Incremental

      org.springframework.security:spring-security-web

      diff --git a/dependency-check-core/failsafe-report.html b/dependency-check-core/failsafe-report.html index 9a86b2d1b..3544a91f3 100644 --- a/dependency-check-core/failsafe-report.html +++ b/dependency-check-core/failsafe-report.html @@ -1,13 +1,13 @@ - + dependency-check-core – Surefire Report @@ -52,7 +52,7 @@ @@ -272,7 +272,7 @@ function toggleDisplay(elementId) { -
      0 0 100%130.044

      +181.425

      Note: failures are anticipated and checked for with assertions while errors are unanticipated.


      Package List

      @@ -293,7 +293,7 @@ function toggleDisplay(elementId) { 0 0 100% -4.471 +3.375 org.owasp.dependencycheck.reporting 2 @@ -301,7 +301,7 @@ function toggleDisplay(elementId) { 0 0 100% -7.617 +9.681 org.owasp.dependencycheck.data.nvdcve 10 @@ -309,7 +309,7 @@ function toggleDisplay(elementId) { 0 0 100% -6.318 +6.494 org.owasp.dependencycheck 1 @@ -317,7 +317,7 @@ function toggleDisplay(elementId) { 0 0 100% -44.53 +42.813 org.owasp.dependencycheck.analyzer 22 @@ -325,7 +325,7 @@ function toggleDisplay(elementId) { 0 0 100% -67.108
      +119.062

      Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.

      org.owasp.dependencycheck.data.update

      @@ -347,7 +347,7 @@ function toggleDisplay(elementId) { 0 0 100% -0 +0.004 NvdCveUpdaterIntegrationTest @@ -356,7 +356,7 @@ function toggleDisplay(elementId) { 0 0 100% -4.471
      +3.371

      org.owasp.dependencycheck.reporting

      @@ -377,7 +377,7 @@ function toggleDisplay(elementId) { -
      0 0 100%7.617
      +9.681

      org.owasp.dependencycheck.data.nvdcve

      @@ -398,7 +398,7 @@ function toggleDisplay(elementId) { - + @@ -407,7 +407,7 @@ function toggleDisplay(elementId) { -
      0 0 100%3.134
      3.282
      DatabasePropertiesIntegrationTest0 0 100%3.184
      +3.212

      org.owasp.dependencycheck

      @@ -428,7 +428,7 @@ function toggleDisplay(elementId) { -
      0 0 100%44.53
      +42.813

      org.owasp.dependencycheck.analyzer

      @@ -449,7 +449,7 @@ function toggleDisplay(elementId) { - + @@ -458,7 +458,7 @@ function toggleDisplay(elementId) { - + @@ -467,7 +467,7 @@ function toggleDisplay(elementId) { - + @@ -476,7 +476,7 @@ function toggleDisplay(elementId) { -
      0 0 100%21.696
      26.302
      CPEAnalyzerIntegrationTest0 0 100%42.85
      89.138
      DependencyBundlingAnalyzerIntegrationTest0 0 100%0.015
      0.002
      VulnerabilitySuppressionAnalyzerIntegrationTest0 0 100%2.547

      +3.62

      Test Cases

      [Summary] [Package List] [Test Cases]

      @@ -486,35 +486,35 @@ function toggleDisplay(elementId) { testAnalyzeExecutableJar -1.086 +1.981 testAnalyzeTar -1.411 +2.049 testAnalyzeTgz -5.4 +5.776 testAnalyzeTarBz2 -3.692 +4.424 testAnalyze -0.847 +1.059 testGetAnalysisPhase -0 +0.001 testGetName -0 +0.001 testAnalyze_badZip -0.523 +0.527 testInitialize @@ -522,11 +522,11 @@ function toggleDisplay(elementId) { testAnalyzeTbz2 -3.182 +3.658 testAnalyzeTarGz -2.9 +5.724 testSupportsExtension @@ -534,30 +534,30 @@ function toggleDisplay(elementId) { testSupportsExtensions -0
      +0.002

      CPEAnalyzerIntegrationTest

      - + - + - + - + -
      testSearchCPE1.486
      2.132
      testDetermineCPE1.055
      2.447
      testDetermineIdentifiers1.115
      1.287
      testDetermineCPE_full39.175
      83.263
      testBuildSearch0.001
      +0

      DependencyBundlingAnalyzerIntegrationTest

      @@ -571,7 +571,7 @@ function toggleDisplay(elementId) { - + @@ -590,42 +590,42 @@ function toggleDisplay(elementId) { - + - + - + -
      testAnalyze2.547
      3.617
      testGetAnalysisPhase
      testGetCPEs0.503
      0.507
      testGetVulnerabilities0.634
      0.789
      testGetMatchingSoftware0.508
      0.505
      testgetVulnerability0.523
      +0.514

      DatabasePropertiesIntegrationTest

      - + - + - + - + -
      testSave1.041
      1.188
      testGetProperty_String_String0.53
      0.504
      testGetProperties0.533
      0.505
      testGetProperty_String0.535
      0.507
      testIsEmpty0.529
      +0.506

      CpeUpdaterIntegrationTest

      @@ -639,29 +639,29 @@ function toggleDisplay(elementId) { - + -
      testUpdatesNeeded1.081
      1.009
      testUpdate3.39
      +2.359

      EngineIntegrationTest

      -
      testEngine44.529
      +42.791

      ReportGeneratorIntegrationTest

      - + -
      testGenerateXMLReport7.612
      9.661
      testGenerateReport0.001

      +0.007
      diff --git a/dependency-check-core/findbugs.html b/dependency-check-core/findbugs.html index 134dea97b..b1ef7ecba 100644 --- a/dependency-check-core/findbugs.html +++ b/dependency-check-core/findbugs.html @@ -1,13 +1,13 @@ - + dependency-check-core – FindBugs Bug Detector Report @@ -52,7 +52,7 @@ @@ -251,7 +251,7 @@ Errors Missing Classes -149 +150 2 0 0 diff --git a/dependency-check-core/index.html b/dependency-check-core/index.html index 7ddecad75..3096df9a7 100644 --- a/dependency-check-core/index.html +++ b/dependency-check-core/index.html @@ -1,13 +1,13 @@ - + dependency-check-core – About @@ -52,7 +52,7 @@ diff --git a/dependency-check-core/integration.html b/dependency-check-core/integration.html index d9a17a61f..3d948d386 100644 --- a/dependency-check-core/integration.html +++ b/dependency-check-core/integration.html @@ -1,13 +1,13 @@ - + dependency-check-core – CI Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-core/issue-tracking.html b/dependency-check-core/issue-tracking.html index 24e06d49c..ba814eb0d 100644 --- a/dependency-check-core/issue-tracking.html +++ b/dependency-check-core/issue-tracking.html @@ -1,13 +1,13 @@ - + dependency-check-core – Issue Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-core/license.html b/dependency-check-core/license.html index e49e58886..b6995115d 100644 --- a/dependency-check-core/license.html +++ b/dependency-check-core/license.html @@ -1,13 +1,13 @@ - + dependency-check-core – Project Licenses @@ -52,7 +52,7 @@ diff --git a/dependency-check-core/mail-lists.html b/dependency-check-core/mail-lists.html index bb38d2003..c61ea7581 100644 --- a/dependency-check-core/mail-lists.html +++ b/dependency-check-core/mail-lists.html @@ -1,13 +1,13 @@ - + dependency-check-core – Project Mailing Lists @@ -52,7 +52,7 @@ diff --git a/dependency-check-core/plugin-updates-report.html b/dependency-check-core/plugin-updates-report.html index b45361237..197bd0a85 100644 --- a/dependency-check-core/plugin-updates-report.html +++ b/dependency-check-core/plugin-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-core – Plugin Updates Report @@ -52,7 +52,7 @@ @@ -411,7 +411,7 @@ org.apache.maven.plugins maven-resources-plugin -3.0.0 +3.0.1 @@ -692,7 +692,7 @@ maven-resources-plugin Current Version -3.0.0 +3.0.1

      Plugin org.apache.maven.plugins:maven-site-plugin

      diff --git a/dependency-check-core/pmd.html b/dependency-check-core/pmd.html index fd2a87fac..7bcc4e7cd 100644 --- a/dependency-check-core/pmd.html +++ b/dependency-check-core/pmd.html @@ -1,13 +1,13 @@ - + dependency-check-core – PMD Results @@ -52,7 +52,7 @@ @@ -249,16 +249,16 @@ - + - + - + -
      Line
      These nested if statements could be combined437446
      479488
      These nested if statements could be combined438445
      480487
      These nested if statements could be combined439444
      481486
      These nested if statements could be combined440443
      +482485

      org/owasp/dependencycheck/analyzer/CPEAnalyzer.java

      @@ -267,13 +267,13 @@ - + - + -
      Line
      These nested if statements could be combined582587
      583588
      These nested if statements could be combined583586
      584587
      These nested if statements could be combined591594
      +592595

      org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java

      @@ -282,10 +282,10 @@ - + -
      Line
      Useless parentheses.400401
      421422
      Useless parentheses.402403
      +423424

      org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java

      @@ -306,7 +306,7 @@ -
      Line
      Useless parentheses.388
      +387

      org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java

      @@ -324,7 +324,7 @@ -
      Line
      These nested if statements could be combined302305
      +305308

      org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java

      @@ -362,116 +362,131 @@
      Useless parentheses. 156
      -

      org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java

      +

      org/owasp/dependencycheck/data/nexus/NexusSearch.java

      + + + + +
      Violation Line
      Avoid unused imports such as 'org.owasp.dependencycheck.utils.InvalidSettingException'29
      Avoid unused imports such as 'org.owasp.dependencycheck.utils.Settings'30
      +
      +

      org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java

      + + + + +
      ViolationLine
      Avoid empty if statements 344346

      org/owasp/dependencycheck/data/nvdcve/CveDB.java

      - + - + - +
      Violation Line
      These nested if statements could be combined 648650
      These nested if statements could be combined 760762

      org/owasp/dependencycheck/data/nvdcve/DriverShim.java

      - + - +
      Violation Line
      Useless parentheses. 193

      org/owasp/dependencycheck/data/update/NvdCveUpdater.java

      - + - +
      Violation Line
      Useless parentheses. 173

      org/owasp/dependencycheck/data/update/nvd/DownloadTask.java

      - + - +
      Violation Line
      Useless parentheses. 242

      org/owasp/dependencycheck/dependency/Identifier.java

      - + - + - +
      Violation Line
      Useless parentheses. 191
      Useless parentheses. 194

      org/owasp/dependencycheck/dependency/Reference.java

      - + - - - - + + + +
      Violation Line
      Useless parentheses.116
      Useless parentheses.119
      116
      Useless parentheses.119
      Useless parentheses. 122

      org/owasp/dependencycheck/dependency/Vulnerability.java

      - + - +
      Violation Line
      Useless parentheses. 376

      org/owasp/dependencycheck/dependency/VulnerableSoftware.java

      - + - - - - + + + +
      Violation Line
      Useless parentheses.141
      Useless parentheses.180
      141
      Useless parentheses.180
      Useless parentheses. 185

      org/owasp/dependencycheck/utils/DependencyVersion.java

      - + - - - -
      Violation Line
      Useless parentheses.136
      Useless parentheses.197
      +139 + +Useless parentheses. +141 + +Useless parentheses. +208

      org/owasp/dependencycheck/xml/hints/HintHandler.java

      diff --git a/dependency-check-core/project-info.html b/dependency-check-core/project-info.html index 91ef98c22..37c935da3 100644 --- a/dependency-check-core/project-info.html +++ b/dependency-check-core/project-info.html @@ -1,13 +1,13 @@ - + dependency-check-core – Project Information @@ -52,7 +52,7 @@ diff --git a/dependency-check-core/project-reports.html b/dependency-check-core/project-reports.html index 1266ea2bf..19d48a654 100644 --- a/dependency-check-core/project-reports.html +++ b/dependency-check-core/project-reports.html @@ -1,13 +1,13 @@ - + dependency-check-core – Generated Reports @@ -52,7 +52,7 @@ diff --git a/dependency-check-core/project-summary.html b/dependency-check-core/project-summary.html index 1415e07e7..034498f5f 100644 --- a/dependency-check-core/project-summary.html +++ b/dependency-check-core/project-summary.html @@ -1,13 +1,13 @@ - + dependency-check-core – Project Summary @@ -52,7 +52,7 @@ @@ -230,7 +230,7 @@ - + diff --git a/dependency-check-core/source-repository.html b/dependency-check-core/source-repository.html index ae9c0b050..05a50b50d 100644 --- a/dependency-check-core/source-repository.html +++ b/dependency-check-core/source-repository.html @@ -1,13 +1,13 @@ - + dependency-check-core – Source Code Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-core/surefire-report.html b/dependency-check-core/surefire-report.html index a28daba0c..0dc28370e 100644 --- a/dependency-check-core/surefire-report.html +++ b/dependency-check-core/surefire-report.html @@ -1,13 +1,13 @@ - + dependency-check-core – Surefire Report @@ -52,7 +52,7 @@ @@ -267,12 +267,12 @@ function toggleDisplay(elementId) { - + - -
      dependency-check-core
      Version1.4.3
      1.4.4
      Type jar
      Success Rate Time
      251260 0 0 1394.821%18.21

      +95% +21.784

      Note: failures are anticipated and checked for with assertions while errors are unanticipated.


      Package List

      @@ -293,7 +293,7 @@ function toggleDisplay(elementId) { 0 0 100% -2.604 +2.374 org.owasp.dependencycheck.dependency 34 @@ -301,7 +301,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.005 +0.013 org.owasp.dependencycheck.data.nexus 4 @@ -309,7 +309,7 @@ function toggleDisplay(elementId) { 0 4 0% -0 +0.001 org.owasp.dependencycheck.data.composer 4 @@ -317,7 +317,7 @@ function toggleDisplay(elementId) { 0 0 100% -0 +0.001 org.owasp.dependencycheck.data.nuget 3 @@ -341,15 +341,15 @@ function toggleDisplay(elementId) { 0 0 100% -0.008 +0.04 org.owasp.dependencycheck.analyzer -86 +88 0 0 9 -89.535% -12.868 +89.773% +14.659 org.owasp.dependencycheck.data.cpe 1 @@ -365,7 +365,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.943 +0.623 org.owasp.dependencycheck.data.cwe 1 @@ -373,7 +373,7 @@ function toggleDisplay(elementId) { 0 0 100% -0 +0.015 org.owasp.dependencycheck.data.update.nvd 15 @@ -381,7 +381,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.923 +1.641 org.owasp.dependencycheck.xml.pom 23 @@ -389,7 +389,7 @@ function toggleDisplay(elementId) { 0 0 100% -0 +0.002 org.owasp.dependencycheck.data.nvdcve 7 @@ -397,23 +397,31 @@ function toggleDisplay(elementId) { 0 0 100% -0.563 +0.768 +org.owasp.dependencycheck +7 +0 +0 +0 +100% +1.396 + org.owasp.dependencycheck.xml.suppression 36 0 0 0 100% -0.016 - +0.006 + org.owasp.dependencycheck.data.central 5 0 0 0 100% -0.279
      +0.244

      Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.

      org.owasp.dependencycheck.data.update

      @@ -435,7 +443,7 @@ function toggleDisplay(elementId) { 0 0 100% -2.39 +2.062 EngineVersionCheckTest @@ -444,7 +452,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.214
      +0.312

      org.owasp.dependencycheck.dependency

      @@ -465,7 +473,7 @@ function toggleDisplay(elementId) { - + @@ -474,7 +482,7 @@ function toggleDisplay(elementId) { - + @@ -492,7 +500,7 @@ function toggleDisplay(elementId) { -
      0 0 100%0
      0.003
      EvidenceTest0 0 100%0
      0.002
      VulnerabilityTest0 0 100%0.005
      +0.008

      org.owasp.dependencycheck.data.nexus

      @@ -513,7 +521,7 @@ function toggleDisplay(elementId) { -
      0 4 0%0
      +0.001

      org.owasp.dependencycheck.data.composer

      @@ -534,7 +542,7 @@ function toggleDisplay(elementId) { -
      0 0 100%0
      +0.001

      org.owasp.dependencycheck.data.nuget

      @@ -606,7 +614,7 @@ function toggleDisplay(elementId) { - + @@ -615,7 +623,7 @@ function toggleDisplay(elementId) { - + @@ -633,7 +641,7 @@ function toggleDisplay(elementId) { -
      0 0 100%0
      0.032
      DependencyVersionTest0 0 100%0.006
      0.003
      DependencyVersionUtilTest0 0 100%0
      +0.003

      org.owasp.dependencycheck.analyzer

      @@ -654,7 +662,7 @@ function toggleDisplay(elementId) { - + @@ -663,7 +671,7 @@ function toggleDisplay(elementId) { - + @@ -672,7 +680,7 @@ function toggleDisplay(elementId) { - + @@ -681,7 +689,7 @@ function toggleDisplay(elementId) { - + @@ -690,7 +698,7 @@ function toggleDisplay(elementId) { - + @@ -699,25 +707,25 @@ function toggleDisplay(elementId) { - + - + - + - + - + @@ -726,7 +734,7 @@ function toggleDisplay(elementId) { - + @@ -735,7 +743,7 @@ function toggleDisplay(elementId) { - + @@ -744,7 +752,7 @@ function toggleDisplay(elementId) { - + @@ -753,7 +761,7 @@ function toggleDisplay(elementId) { - + @@ -762,7 +770,7 @@ function toggleDisplay(elementId) { - + @@ -771,7 +779,7 @@ function toggleDisplay(elementId) { - + @@ -780,7 +788,7 @@ function toggleDisplay(elementId) { - + @@ -789,7 +797,7 @@ function toggleDisplay(elementId) { - + @@ -798,7 +806,7 @@ function toggleDisplay(elementId) { - + @@ -816,7 +824,7 @@ function toggleDisplay(elementId) { - + @@ -825,7 +833,7 @@ function toggleDisplay(elementId) { - + @@ -834,7 +842,7 @@ function toggleDisplay(elementId) { - + @@ -843,7 +851,7 @@ function toggleDisplay(elementId) { -
      0 0 100%0.691
      0.014
      AbstractSuppressionAnalyzerTest0 0 100%0.475
      0.653
      AnalyzerServiceTest0 0 100%0.085
      0.095
      ArchiveAnalyzerTest0 1 0%0.015
      0.004
      AssemblyAnalyzerTest0 5 0%0.59
      0.698
      AutoconfAnalyzerTest0 0 100%0.085
      0.153
      CMakeAnalyzerTest56 0 0 0 100%0.807
      1.03
      ComposerLockAnalyzerTest34 0 0 0 100%0.1
      0.195
      DependencyBundlingAnalyzerTest0 0 100%0
      0.088
      FalsePositiveAnalyzerTest0 0 100%0
      0.003
      FileNameAnalyzerTest0 0 100%0
      0.001
      HintAnalyzerTest0 0 100%4.868
      5.602
      JarAnalyzerTest0 0 100%0.134
      0.363
      NodePackageAnalyzerTest0 0 100%0.002
      0
      NuspecAnalyzerTest0 0 100%0
      0.004
      OpenSSLAnalyzerTest0 0 100%0.001
      0.002
      PythonDistributionAnalyzerTest0 0 100%0.025
      0.044
      PythonPackageAnalyzerTest0 3 50%4.987
      5.7
      RubyBundlerAnalyzerTest0 0 100%0
      0.003
      RubyGemspecAnalyzerTest0 0 100%0
      0.001
      SwiftAnalyzersTest0 0 100%0
      +0.003

      org.owasp.dependencycheck.data.cpe

      @@ -894,7 +902,7 @@ function toggleDisplay(elementId) { - + @@ -903,7 +911,7 @@ function toggleDisplay(elementId) { - + @@ -912,7 +920,7 @@ function toggleDisplay(elementId) { -
      0 0 100%0
      0.002
      TokenPairConcatenatingFilterTest0 0 100%0.17
      0.259
      UrlTokenizingFilterTest0 0 100%0.773
      +0.362

      org.owasp.dependencycheck.data.cwe

      @@ -933,7 +941,7 @@ function toggleDisplay(elementId) { -
      0 0 100%0
      +0.015

      org.owasp.dependencycheck.data.update.nvd

      @@ -954,7 +962,7 @@ function toggleDisplay(elementId) { - + @@ -963,7 +971,7 @@ function toggleDisplay(elementId) { - + @@ -981,7 +989,7 @@ function toggleDisplay(elementId) { - + @@ -1011,7 +1019,7 @@ function toggleDisplay(elementId) { - + @@ -1041,7 +1049,7 @@ function toggleDisplay(elementId) { - + @@ -1050,7 +1058,37 @@ function toggleDisplay(elementId) { -
      0 0 100%0.823
      1.433
      NvdCveInfoTest0 0 100%0.016
      0.001
      NvdCve_1_2_HandlerTest0 0 100%0.084
      0.207
      UpdateableNvdCveTest0 0 100%0
      0.002
      PomUtilsTest0 0 100%0.5
      0.479
      DriverLoaderTest0 0 100%0.063
      +0.289 +
      +

      org.owasp.dependencycheck

      + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      ClassTestsErrors FailuresSkippedSuccess RateTime
      AnalysisTaskTest5000100%1.183
      EngineTest2000100%0.213

      org.owasp.dependencycheck.xml.suppression

      @@ -1089,7 +1127,7 @@ function toggleDisplay(elementId) { - + @@ -1098,7 +1136,7 @@ function toggleDisplay(elementId) { -
      0 0 100%0
      0.006
      SuppressionRuleTest0 0 100%0.016
      +0

      org.owasp.dependencycheck.data.central

      @@ -1119,28 +1157,51 @@ function toggleDisplay(elementId) { -
      0 0 100%0.279

      +0.244

      Test Cases

      [Summary] [Package List] [Test Cases]

      +

      AnalysisTaskTest

      + + + + + + + + + + + + + + + + + + + + +
      shouldAnalyzeReturnsFalseIfTheFileTypeAnalyzerDoesNotAcceptTheDependency0.615
      taskDoesNothingIfItShouldNotAnalyze0.06
      shouldAnalyzeReturnsTrueForNonFileTypeAnalyzers0.007
      shouldAnalyzeReturnsTrueIfTheFileTypeAnalyzersAcceptsTheDependency0.026
      taskAnalyzes0.042
      +

      AbstractFileTypeAnalyzerTest

      -
      testNewHashSet0.017
      +0.005

      AbstractSuppressionAnalyzerTest

      - + - + @@ -1155,11 +1216,11 @@ function toggleDisplay(elementId) { - + -
      testFailureToLocateSuppressionFileAnywhere0.241
      0.255
      testGetRulesFromSuppressionFileFromURL0.193
      0.355
      testGetRulesFromSuppressionFileInClasspath
      testGetAnalyzers0.069
      0.086
      testGetExperimentalAnalyzers0.016
      +0.006

      ArchiveAnalyzerTest

      @@ -1226,27 +1287,27 @@ function toggleDisplay(elementId) { - + - + - + - + - + -
      testAnalyzeReadableConfigureScript0.031
      0.06
      testGetName0
      0.001
      testSupportsFileExtension0
      0.001
      testAnalyzeConfigureScript0.038
      0.069
      testAnalyzeConfigureAC10.016
      0.011
      testAnalyzeConfigureAC20
      +0.011

      CMakeAnalyzerTest

      @@ -1257,19 +1318,23 @@ function toggleDisplay(elementId) { - + - + - - + + + + + + -
      testAnalyzeCMakeListsOpenCV0
      0.011
      testGetName0
      0.002
      testAnalyzeCMakeListsOpenCV3rdParty0.807
      analyzerIsDisabledInCaseOfMissingMessageDigest0.1
      testAnalyzeCMakeListsOpenCV3rdParty0.915
      testAccept0
      +0.001

      ComposerLockAnalyzerTest

      @@ -1279,10 +1344,14 @@ function toggleDisplay(elementId) { - - + + + + + +
      0
      testAnalyzePackageJson0.1
      analyzerIsDisabledInCaseOfMissingMessageDigest0.05
      testAnalyzePackageJson0.141
      testSupportsFiles 0
      @@ -1291,15 +1360,15 @@ function toggleDisplay(elementId) { testAnalyze -0 +0.085 testGetAnalysisPhase -0 +0.001 testGetName -0 +0.001 testFirstPathIsShortest @@ -1307,7 +1376,7 @@ function toggleDisplay(elementId) { testIsCore -0
      +0.001

      FalsePositiveAnalyzerTest

      @@ -1352,7 +1421,7 @@ function toggleDisplay(elementId) { - + @@ -1367,7 +1436,7 @@ function toggleDisplay(elementId) { - + @@ -1379,7 +1448,7 @@ function toggleDisplay(elementId) { -
      testAnalyze4.868
      5.597
      testGetAnalysisPhase
      testAnalyze0.101
      0.297
      testGetName
      testParseManifest0.032
      +0.065

      NodePackageAnalyzerTest

      @@ -1416,7 +1485,7 @@ function toggleDisplay(elementId) { - + @@ -1443,7 +1512,7 @@ function toggleDisplay(elementId) { - + @@ -1451,7 +1520,7 @@ function toggleDisplay(elementId) { - + @@ -1459,7 +1528,7 @@ function toggleDisplay(elementId) { - + @@ -1485,11 +1554,11 @@ function toggleDisplay(elementId) { - + - + - + @@ -1592,15 +1661,15 @@ function toggleDisplay(elementId) { - + - + -
      testGetName0
      0.001
      testVersionConstantExamples
      testAnalyzeEggArchive0.001
      0
      testAnalyzeEggArchiveNamedZip
      testAnalyzeWheel0.012
      0.02
      testAnalyzeEggInfoFolder
      testAnalyzeSitePackage0.004
      0.009
      testSupportsFiles
      testMissingBundleAudit0.53
      0.599
      testGetName0
      0.003
      testAnalysis @@ -1584,7 +1653,7 @@ function toggleDisplay(elementId) {
      testMultipleReturns0.163
      0.148
      testNullSha1
      testMalformedSha10
      0.001
      testValidSha10.069
      0.055
      testMissingSha10.047
      +0.038

      ComposerLockParserTest

      @@ -1611,7 +1680,7 @@ function toggleDisplay(elementId) { - + @@ -1666,26 +1735,26 @@ function toggleDisplay(elementId) { - + -
      testValidComposerLock0
      0.001
      testNotComposer
      testExamples0.054
      0.052
      testClear0
      +0.007

      UrlTokenizingFilterTest

      - - + + - - + + -
      testEmptyTerm0.007
      testExamples0.05
      testExamples0.026
      testEmptyTerm0.005
      testRandomStrings0.578
      +0.291

      NexusSearchTest

      @@ -1731,11 +1800,11 @@ function toggleDisplay(elementId) { - + - + @@ -1746,7 +1815,7 @@ function toggleDisplay(elementId) { -
      testGoodDocument0
      0.001
      testMissingDocument0.001
      0
      testNotNuspec
      testInitialize0.493
      +0.479

      DriverLoaderTest

      @@ -1769,11 +1838,11 @@ function toggleDisplay(elementId) { - + -
      testLoad_String_String0.031
      0.034
      testLoad_String_String_multiple_paths0.032
      +0.252

      BaseUpdaterTest

      @@ -1784,37 +1853,37 @@ function toggleDisplay(elementId) { - + - + -
      testOpenDataStores1
      1.031
      testGetProperties0.882
      0.498
      testCloseDataStores0.506
      +0.528

      EngineVersionCheckTest

      - + -
      testShouldUpdate0.183
      0.265
      testGetCurrentReleaseVersion0.031
      +0.043

      DownloadTaskTest

      - + -
      testIsXML0
      0.013
      testCall0.808
      +1.413

      NvdCveInfoTest

      @@ -1851,11 +1920,11 @@ function toggleDisplay(elementId) { - + -
      testParserWithPreviousVersion0
      0.017
      testParse0.084
      +0.189

      UpdateableNvdCveTest

      @@ -2028,12 +2097,23 @@ function toggleDisplay(elementId) {
      testParseCPE 0
      +

      EngineTest

      + + + + + + + + +
      exceptionDuringAnalysisTaskExecutionIsFatal0.206
      testScanFile0.007
      +

      DateUtilTest

      -
      testWithinDateRange0
      +0.001

      DependencyVersionTest

      @@ -2290,7 +2370,7 @@ function toggleDisplay(elementId) { - + diff --git a/dependency-check-core/taglist.html b/dependency-check-core/taglist.html index 3b52e0c2a..8fb4025f7 100644 --- a/dependency-check-core/taglist.html +++ b/dependency-check-core/taglist.html @@ -1,13 +1,13 @@ - + dependency-check-core – Tag List report @@ -52,7 +52,7 @@ @@ -246,55 +246,49 @@ - +
      testAddCvssBelow0.016
      0
      testFilePath Tag strings used by tag class
      Todo Work2627 todo, FIXME

      Each tag is detailed below:

      Todo Work

      -

      Number of occurrences found in the code: 26

      +

      Number of occurrences found in the code: 27

      - + - - + + - + - + - + - + - + - - - - - - - + @@ -315,10 +309,10 @@ - + - + @@ -351,32 +345,41 @@ - + + + + + + + + + + - + - + - - - + + + - + - + - + - +
      org.owasp.dependencycheck.analyzer.ArchiveAnalyzer Line
      - can we get more evidence from the parent? EAR contains module name, etc. analyze the dependency (i.e. extract files) if it is a supported type.252
      265
      org.owasp.dependencycheck.analyzer.AssemblyAnalyzer Line
      this creaes an "unreported" error - if someone doesn't look at the command output this could easily be missed (especially in an Ant or Mmaven build.236
      this creates an "unreported" error - if someone doesn't look at the command output this could easily be missed (especially in an Ant or Maven build.235
      org.owasp.dependencycheck.analyzer.CMakeAnalyzer Line
      - refactor so we do not assign to the parameter (checkstyle)220
      212
      org.owasp.dependencycheck.analyzer.CPEAnalyzer Line
      test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit199
      200
      - does this nullify some of the fuzzy matching that happens in the lucene search? for instance CPE some-component and in the evidence we have SomeComponent.450
      451
      - likely need to change the split... not sure if this will work for CPE with special chars468
      469
      the following algorithm incorrectly identifies things as a lower version if there lower confidence evidence when the current (highest) version number is newer then anything in the NVD.553
      554
      the following isn't quite right is it? need to think about this guessing game a bit more.579
      org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzerTestLine
      review the generated test code and remove the default call to fail. fail("The test case is a prototype.");62
      580
      org.owasp.dependencycheck.analyzer.FalsePositiveAnalyzer Line
      Line
      remove weighting619
      618
      change this to a regex?726
      725
      org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer Line
      Line
      - move this to a util class as it is duplicative of (copy of) code in the DownloadTask157
      165
      org.owasp.dependencycheck.dependency.EvidenceLine
      the call to ObjectUtils.equals needs to be replaced when we stop supporting Jenkins 1.6 requirement.229
      the call to ObjectUtils.equals needs to be replaced when we stop supporting Jenkins 1.6 requirement.252
      org.owasp.dependencycheck.dependency.EvidenceCollection Line
      consider changing the regex to only compare alpha-numeric (i.e. strip everything else) 248
      org.owasp.dependencycheck.utils.DependencyVersion Line
      steal better version of code from compareTo138
      steal better version of code from compareTo148
      org.owasp.dependencycheck.utils.DependencyVersionTest Line
      (code review): should this be here/do something? assertEquals("0", parts.get(2)); 54
      org.owasp.dependencycheck.xml.pom.PomHandler Line
      add error logging 167
      add error logging 174
      diff --git a/dependency-check-core/team-list.html b/dependency-check-core/team-list.html index 39169c35e..edb1d9e16 100644 --- a/dependency-check-core/team-list.html +++ b/dependency-check-core/team-list.html @@ -1,13 +1,13 @@ - + dependency-check-core – Project Team @@ -52,7 +52,7 @@ diff --git a/dependency-check-core/xref-test/allclasses-frame.html b/dependency-check-core/xref-test/allclasses-frame.html index 016e88106..50aa84178 100644 --- a/dependency-check-core/xref-test/allclasses-frame.html +++ b/dependency-check-core/xref-test/allclasses-frame.html @@ -19,6 +19,9 @@
    6. AbstractSuppressionAnalyzerTest +
    7. +
    8. + AnalysisTaskTest
    9. AnalyzerServiceTest @@ -106,6 +109,9 @@
    10. EngineIntegrationTest +
    11. +
    12. + EngineTest
    13. EngineVersionCheckTest diff --git a/dependency-check-core/xref-test/index.html b/dependency-check-core/xref-test/index.html index 415806e7b..56d800cfe 100644 --- a/dependency-check-core/xref-test/index.html +++ b/dependency-check-core/xref-test/index.html @@ -4,7 +4,7 @@ - Dependency-Check Core 1.4.3 Reference + Dependency-Check Core 1.4.4 Reference diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/AnalysisTaskTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/AnalysisTaskTest.html new file mode 100644 index 000000000..58d468f58 --- /dev/null +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/AnalysisTaskTest.html @@ -0,0 +1,113 @@ + + + +AnalysisTaskTest xref + + + +
      +1   package org.owasp.dependencycheck;
      +2   
      +3   import mockit.Expectations;
      +4   import mockit.Mocked;
      +5   import mockit.Verifications;
      +6   import org.junit.Test;
      +7   import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
      +8   import org.owasp.dependencycheck.analyzer.HintAnalyzer;
      +9   import org.owasp.dependencycheck.dependency.Dependency;
      +10  
      +11  import java.io.File;
      +12  
      +13  import static org.junit.Assert.assertFalse;
      +14  import static org.junit.Assert.assertTrue;
      +15  
      +16  public class AnalysisTaskTest {
      +17  
      +18      @Mocked
      +19      FileTypeAnalyzer fileTypeAnalyzer;
      +20  
      +21      @Mocked
      +22      Dependency dependency;
      +23  
      +24      @Mocked
      +25      Engine engine;
      +26  
      +27  
      +28      @Test
      +29      public void shouldAnalyzeReturnsTrueForNonFileTypeAnalyzers() {
      +30          AnalysisTask instance = new AnalysisTask(new HintAnalyzer(), null, null, null);
      +31          boolean shouldAnalyze = instance.shouldAnalyze();
      +32          assertTrue(shouldAnalyze);
      +33      }
      +34  
      +35      @Test
      +36      public void shouldAnalyzeReturnsTrueIfTheFileTypeAnalyzersAcceptsTheDependency() {
      +37          final File dependencyFile = new File("");
      +38          new Expectations() {{
      +39              dependency.getActualFile();
      +40              result = dependencyFile;
      +41  
      +42              fileTypeAnalyzer.accept(dependencyFile);
      +43              result = true;
      +44          }};
      +45  
      +46          AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, null, null);
      +47  
      +48          boolean shouldAnalyze = analysisTask.shouldAnalyze();
      +49          assertTrue(shouldAnalyze);
      +50      }
      +51  
      +52      @Test
      +53      public void shouldAnalyzeReturnsFalseIfTheFileTypeAnalyzerDoesNotAcceptTheDependency() {
      +54          final File dependencyFile = new File("");
      +55          new Expectations() {{
      +56              dependency.getActualFile();
      +57              result = dependencyFile;
      +58  
      +59              fileTypeAnalyzer.accept(dependencyFile);
      +60              result = false;
      +61          }};
      +62  
      +63          AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, null, null);
      +64  
      +65          boolean shouldAnalyze = analysisTask.shouldAnalyze();
      +66          assertFalse(shouldAnalyze);
      +67      }
      +68  
      +69      @Test
      +70      public void taskAnalyzes() throws Exception {
      +71          final AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, engine, null);
      +72          new Expectations(analysisTask) {{
      +73              analysisTask.shouldAnalyze();
      +74              result = true;
      +75          }};
      +76  
      +77          analysisTask.call();
      +78  
      +79          new Verifications() {{
      +80              fileTypeAnalyzer.analyze(dependency, engine);
      +81              times = 1;
      +82          }};
      +83      }
      +84  
      +85      @Test
      +86      public void taskDoesNothingIfItShouldNotAnalyze() throws Exception {
      +87          final AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, engine, null);
      +88          new Expectations(analysisTask) {{
      +89              analysisTask.shouldAnalyze();
      +90              result = false;
      +91          }};
      +92  
      +93          analysisTask.call();
      +94  
      +95          new Verifications() {{
      +96              fileTypeAnalyzer.analyze(dependency, engine);
      +97              times = 0;
      +98          }};
      +99      }
      +100 }
      +
      +
      + + + diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/EngineTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/EngineTest.html new file mode 100644 index 000000000..a67ab2d66 --- /dev/null +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/EngineTest.html @@ -0,0 +1,109 @@ + + + +EngineTest xref + + + +
      +1   /*
      +2    * This file is part of dependency-check-core.
      +3    *
      +4    * Licensed under the Apache License, Version 2.0 (the "License");
      +5    * you may not use this file except in compliance with the License.
      +6    * You may obtain a copy of the License at
      +7    *
      +8    *     http://www.apache.org/licenses/LICENSE-2.0
      +9    *
      +10   * Unless required by applicable law or agreed to in writing, software
      +11   * distributed under the License is distributed on an "AS IS" BASIS,
      +12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      +13   * See the License for the specific language governing permissions and
      +14   * limitations under the License.
      +15   *
      +16   * Copyright (c) 2016 Jeremy Long. All Rights Reserved.
      +17   */
      +18  package org.owasp.dependencycheck;
      +19  
      +20  import mockit.Expectations;
      +21  import mockit.Mocked;
      +22  import org.junit.Test;
      +23  import org.owasp.dependencycheck.analyzer.Analyzer;
      +24  import org.owasp.dependencycheck.analyzer.JarAnalyzer;
      +25  import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
      +26  import org.owasp.dependencycheck.dependency.Dependency;
      +27  import org.owasp.dependencycheck.exception.ExceptionCollection;
      +28  
      +29  import java.io.File;
      +30  import java.util.ArrayList;
      +31  import java.util.List;
      +32  import java.util.concurrent.ExecutorService;
      +33  import java.util.concurrent.Executors;
      +34  
      +35  import static org.junit.Assert.assertEquals;
      +36  import static org.junit.Assert.assertTrue;
      +37  
      +38  /**
      +39   * @author Jeremy Long
      +40   */
      +41  public class EngineTest extends BaseDBTestCase {
      +42  
      +43      @Mocked
      +44      Analyzer analyzer;
      +45  
      +46      @Mocked
      +47      AnalysisTask analysisTask;
      +48  
      +49  
      +50      /**
      +51       * Test of scanFile method, of class Engine.
      +52       */
      +53      @Test
      +54      public void testScanFile() throws DatabaseException {
      +55          Engine instance = new Engine();
      +56          instance.addFileTypeAnalyzer(new JarAnalyzer());
      +57          File file = BaseTest.getResourceAsFile(this, "dwr.jar");
      +58          Dependency dwr = instance.scanFile(file);
      +59          file = BaseTest.getResourceAsFile(this, "org.mortbay.jmx.jar");
      +60          instance.scanFile(file);
      +61          assertEquals(2, instance.getDependencies().size());
      +62  
      +63          file = BaseTest.getResourceAsFile(this, "dwr.jar");
      +64          Dependency secondDwr = instance.scanFile(file);
      +65  
      +66          assertEquals(2, instance.getDependencies().size());
      +67          assertTrue(dwr == secondDwr);
      +68      }
      +69  
      +70      @Test(expected = ExceptionCollection.class)
      +71      public void exceptionDuringAnalysisTaskExecutionIsFatal() throws DatabaseException, ExceptionCollection {
      +72          final ExecutorService executorService = Executors.newFixedThreadPool(3);
      +73          final Engine instance = new Engine();
      +74          final List<Throwable> exceptions = new ArrayList<Throwable>();
      +75  
      +76          new Expectations() {{
      +77              analysisTask.call();
      +78              result = new IllegalStateException("Analysis task execution threw an exception");
      +79          }};
      +80  
      +81          final List<AnalysisTask> failingAnalysisTask = new ArrayList<AnalysisTask>();
      +82          failingAnalysisTask.add(analysisTask);
      +83  
      +84          new Expectations(instance) {{
      +85              instance.getExecutorService(analyzer);
      +86              result = executorService;
      +87  
      +88              instance.getAnalysisTasks(analyzer, exceptions);
      +89              result = failingAnalysisTask;
      +90          }};
      +91  
      +92          instance.executeAnalysisTasks(analyzer, exceptions);
      +93  
      +94          assertTrue(executorService.isShutdown());
      +95      }
      +96  }
      +
      +
      + + + diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.html index 4af403b82..bf341b8b9 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.html @@ -25,140 +25,165 @@ 17 */ 18 package org.owasp.dependencycheck.analyzer; 19 -20 import org.junit.After; -21 import org.junit.Before; -22 import org.junit.Test; -23 import org.owasp.dependencycheck.BaseTest; -24 import org.owasp.dependencycheck.Engine; -25 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -26 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -27 import org.owasp.dependencycheck.dependency.Dependency; -28 -29 import java.io.File; -30 import java.util.List; -31 import java.util.regex.Pattern; +20 import mockit.Mock; +21 import mockit.MockUp; +22 import org.junit.After; +23 import org.junit.Before; +24 import org.junit.Test; +25 import org.owasp.dependencycheck.BaseDBTestCase; +26 import org.owasp.dependencycheck.BaseTest; +27 import org.owasp.dependencycheck.Engine; +28 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +29 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +30 import org.owasp.dependencycheck.dependency.Dependency; +31 import org.owasp.dependencycheck.exception.InitializationException; 32 -33 import static org.hamcrest.CoreMatchers.equalTo; -34 import static org.hamcrest.CoreMatchers.is; -35 import static org.junit.Assert.*; -36 import org.owasp.dependencycheck.BaseDBTestCase; -37 -38 /** -39 * Unit tests for CmakeAnalyzer. -40 * -41 * @author Dale Visser -42 */ -43 public class CMakeAnalyzerTest extends BaseDBTestCase { -44 -45 /** -46 * The package analyzer to test. -47 */ -48 CMakeAnalyzer analyzer; -49 -50 /** -51 * Setup the CmakeAnalyzer. -52 * -53 * @throws Exception if there is a problem -54 */ -55 @Override -56 @Before -57 public void setUp() throws Exception { -58 super.setUp(); -59 analyzer = new CMakeAnalyzer(); -60 analyzer.setFilesMatched(true); -61 analyzer.initialize(); -62 } -63 -64 /** -65 * Cleanup any resources used. -66 * -67 * @throws Exception if there is a problem -68 */ -69 @After -70 public void tearDown() throws Exception { -71 analyzer.close(); -72 analyzer = null; -73 } -74 -75 /** -76 * Test of getName method, of class PythonPackageAnalyzer. -77 */ -78 @Test -79 public void testGetName() { -80 assertThat(analyzer.getName(), is(equalTo("CMake Analyzer"))); +33 import java.io.File; +34 import java.security.MessageDigest; +35 import java.security.NoSuchAlgorithmException; +36 import java.util.List; +37 import java.util.regex.Pattern; +38 +39 import static org.hamcrest.CoreMatchers.equalTo; +40 import static org.hamcrest.CoreMatchers.is; +41 import static org.junit.Assert.assertEquals; +42 import static org.junit.Assert.assertFalse; +43 import static org.junit.Assert.assertThat; +44 import static org.junit.Assert.assertTrue; +45 +46 /** +47 * Unit tests for CmakeAnalyzer. +48 * +49 * @author Dale Visser +50 */ +51 public class CMakeAnalyzerTest extends BaseDBTestCase { +52 +53 /** +54 * The package analyzer to test. +55 */ +56 CMakeAnalyzer analyzer; +57 +58 /** +59 * Setup the CmakeAnalyzer. +60 * +61 * @throws Exception if there is a problem +62 */ +63 @Override +64 @Before +65 public void setUp() throws Exception { +66 super.setUp(); +67 analyzer = new CMakeAnalyzer(); +68 analyzer.setFilesMatched(true); +69 analyzer.initialize(); +70 } +71 +72 /** +73 * Cleanup any resources used. +74 * +75 * @throws Exception if there is a problem +76 */ +77 @After +78 public void tearDown() throws Exception { +79 analyzer.close(); +80 analyzer = null; 81 } 82 83 /** -84 * Test of supportsExtension method, of class PythonPackageAnalyzer. +84 * Test of getName method, of class PythonPackageAnalyzer. 85 */ 86 @Test -87 public void testAccept() { -88 assertTrue("Should support \"CMakeLists.txt\" name.", -89 analyzer.accept(new File("CMakeLists.txt"))); -90 assertTrue("Should support \"cmake\" extension.", -91 analyzer.accept(new File("test.cmake"))); -92 } -93 -94 /** -95 * Test whether expected evidence is gathered from OpenCV's CMakeLists.txt. -96 * -97 * @throws AnalysisException is thrown when an exception occurs. -98 */ -99 @Test -100 public void testAnalyzeCMakeListsOpenCV() throws AnalysisException { -101 final Dependency result = new Dependency(BaseTest.getResourceAsFile( -102 this, "cmake/opencv/CMakeLists.txt")); -103 analyzer.analyze(result, null); -104 final String product = "OpenCV"; -105 assertProductEvidence(result, product); -106 } -107 -108 /** -109 * Test whether expected evidence is gathered from OpenCV's CMakeLists.txt. -110 * -111 * @throws AnalysisException is thrown when an exception occurs. -112 */ -113 @Test -114 public void testAnalyzeCMakeListsZlib() throws AnalysisException { -115 final Dependency result = new Dependency(BaseTest.getResourceAsFile( -116 this, "cmake/zlib/CMakeLists.txt")); -117 analyzer.analyze(result, null); -118 final String product = "zlib"; -119 assertProductEvidence(result, product); -120 } -121 -122 private void assertProductEvidence(Dependency result, String product) { -123 assertTrue("Expected product evidence to contain \"" + product + "\".", -124 result.getProductEvidence().toString().contains(product)); -125 } -126 -127 /** -128 * Test whether expected version evidence is gathered from OpenCV's third party cmake files. -129 * -130 * @throws AnalysisException is thrown when an exception occurs. -131 */ -132 @Test -133 public void testAnalyzeCMakeListsOpenCV3rdParty() throws AnalysisException, DatabaseException { -134 final Dependency result = new Dependency(BaseTest.getResourceAsFile( -135 this, "cmake/opencv/3rdparty/ffmpeg/ffmpeg_version.cmake")); -136 final Engine engine = new Engine(); -137 analyzer.analyze(result, engine); -138 assertProductEvidence(result, "libavcodec"); -139 assertVersionEvidence(result, "55.18.102"); -140 assertFalse("ALIASOF_ prefix shouldn't be present.", -141 Pattern.compile("\\bALIASOF_\\w+").matcher(result.getProductEvidence().toString()).find()); -142 final List<Dependency> dependencies = engine.getDependencies(); -143 assertEquals("Number of additional dependencies should be 4.", 4, dependencies.size()); -144 final Dependency last = dependencies.get(3); -145 assertProductEvidence(last, "libavresample"); -146 assertVersionEvidence(last, "1.0.1"); -147 } -148 -149 private void assertVersionEvidence(Dependency result, String version) { -150 assertTrue("Expected version evidence to contain \"" + version + "\".", -151 result.getVersionEvidence().toString().contains(version)); -152 } -153 } +87 public void testGetName() { +88 assertThat(analyzer.getName(), is(equalTo("CMake Analyzer"))); +89 } +90 +91 /** +92 * Test of supportsExtension method, of class PythonPackageAnalyzer. +93 */ +94 @Test +95 public void testAccept() { +96 assertTrue("Should support \"CMakeLists.txt\" name.", +97 analyzer.accept(new File("CMakeLists.txt"))); +98 assertTrue("Should support \"cmake\" extension.", +99 analyzer.accept(new File("test.cmake"))); +100 } +101 +102 /** +103 * Test whether expected evidence is gathered from OpenCV's CMakeLists.txt. +104 * +105 * @throws AnalysisException is thrown when an exception occurs. +106 */ +107 @Test +108 public void testAnalyzeCMakeListsOpenCV() throws AnalysisException { +109 final Dependency result = new Dependency(BaseTest.getResourceAsFile( +110 this, "cmake/opencv/CMakeLists.txt")); +111 analyzer.analyze(result, null); +112 final String product = "OpenCV"; +113 assertProductEvidence(result, product); +114 } +115 +116 /** +117 * Test whether expected evidence is gathered from OpenCV's CMakeLists.txt. +118 * +119 * @throws AnalysisException is thrown when an exception occurs. +120 */ +121 @Test +122 public void testAnalyzeCMakeListsZlib() throws AnalysisException { +123 final Dependency result = new Dependency(BaseTest.getResourceAsFile( +124 this, "cmake/zlib/CMakeLists.txt")); +125 analyzer.analyze(result, null); +126 final String product = "zlib"; +127 assertProductEvidence(result, product); +128 } +129 +130 private void assertProductEvidence(Dependency result, String product) { +131 assertTrue("Expected product evidence to contain \"" + product + "\".", +132 result.getProductEvidence().toString().contains(product)); +133 } +134 +135 /** +136 * Test whether expected version evidence is gathered from OpenCV's third party cmake files. +137 * +138 * @throws AnalysisException is thrown when an exception occurs. +139 */ +140 @Test +141 public void testAnalyzeCMakeListsOpenCV3rdParty() throws AnalysisException, DatabaseException { +142 final Dependency result = new Dependency(BaseTest.getResourceAsFile( +143 this, "cmake/opencv/3rdparty/ffmpeg/ffmpeg_version.cmake")); +144 final Engine engine = new Engine(); +145 analyzer.analyze(result, engine); +146 assertProductEvidence(result, "libavcodec"); +147 assertVersionEvidence(result, "55.18.102"); +148 assertFalse("ALIASOF_ prefix shouldn't be present.", +149 Pattern.compile("\\bALIASOF_\\w+").matcher(result.getProductEvidence().toString()).find()); +150 final List<Dependency> dependencies = engine.getDependencies(); +151 assertEquals("Number of additional dependencies should be 4.", 4, dependencies.size()); +152 final Dependency last = dependencies.get(3); +153 assertProductEvidence(last, "libavresample"); +154 assertVersionEvidence(last, "1.0.1"); +155 } +156 +157 private void assertVersionEvidence(Dependency result, String version) { +158 assertTrue("Expected version evidence to contain \"" + version + "\".", +159 result.getVersionEvidence().toString().contains(version)); +160 } +161 +162 @Test(expected = InitializationException.class) +163 public void analyzerIsDisabledInCaseOfMissingMessageDigest() throws InitializationException { +164 new MockUp<MessageDigest>() { +165 @Mock +166 MessageDigest getInstance(String ignore) throws NoSuchAlgorithmException { +167 throw new NoSuchAlgorithmException(); +168 } +169 }; +170 +171 analyzer = new CMakeAnalyzer(); +172 analyzer.setFilesMatched(true); +173 assertTrue(analyzer.isEnabled()); +174 analyzer.initialize(); +175 +176 assertFalse(analyzer.isEnabled()); +177 } +178 }
      diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.html index 12b21a093..c00d1117d 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.html @@ -25,86 +25,110 @@ 17 */ 18 package org.owasp.dependencycheck.analyzer; 19 -20 import org.junit.After; -21 import org.junit.Before; -22 import org.junit.Test; -23 import org.owasp.dependencycheck.BaseTest; -24 import org.owasp.dependencycheck.Engine; -25 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -26 import org.owasp.dependencycheck.dependency.Dependency; -27 -28 import java.io.File; -29 -30 import static org.junit.Assert.assertEquals; -31 import static org.junit.Assert.assertTrue; -32 import org.owasp.dependencycheck.BaseDBTestCase; -33 -34 /** -35 * Unit tests for NodePackageAnalyzer. -36 * -37 * @author Dale Visser -38 */ -39 public class ComposerLockAnalyzerTest extends BaseDBTestCase { -40 -41 /** -42 * The analyzer to test. -43 */ -44 ComposerLockAnalyzer analyzer; -45 -46 /** -47 * Correctly setup the analyzer for testing. -48 * -49 * @throws Exception thrown if there is a problem -50 */ -51 @Override -52 @Before -53 public void setUp() throws Exception { -54 super.setUp(); -55 analyzer = new ComposerLockAnalyzer(); -56 analyzer.setFilesMatched(true); -57 analyzer.initialize(); -58 } -59 -60 /** -61 * Cleanup the analyzer's temp files, etc. -62 * -63 * @throws Exception thrown if there is a problem -64 */ -65 @After -66 public void tearDown() throws Exception { -67 analyzer.close(); -68 analyzer = null; -69 } -70 -71 /** -72 * Test of getName method, of class ComposerLockAnalyzer. -73 */ -74 @Test -75 public void testGetName() { -76 assertEquals("Composer.lock analyzer", analyzer.getName()); -77 } -78 -79 /** -80 * Test of supportsExtension method, of class ComposerLockAnalyzer. -81 */ -82 @Test -83 public void testSupportsFiles() { -84 assertTrue(analyzer.accept(new File("composer.lock"))); -85 } -86 -87 /** -88 * Test of inspect method, of class PythonDistributionAnalyzer. -89 * -90 * @throws AnalysisException is thrown when an exception occurs. -91 */ -92 @Test -93 public void testAnalyzePackageJson() throws Exception { -94 final Engine engine = new Engine(); -95 final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, -96 "composer.lock")); -97 analyzer.analyze(result, engine); -98 } -99 } +20 import mockit.Mock; +21 import mockit.MockUp; +22 import org.junit.After; +23 import org.junit.Before; +24 import org.junit.Test; +25 import org.owasp.dependencycheck.BaseDBTestCase; +26 import org.owasp.dependencycheck.BaseTest; +27 import org.owasp.dependencycheck.Engine; +28 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +29 import org.owasp.dependencycheck.dependency.Dependency; +30 import org.owasp.dependencycheck.exception.InitializationException; +31 +32 import java.io.File; +33 import java.security.MessageDigest; +34 import java.security.NoSuchAlgorithmException; +35 +36 import static org.junit.Assert.assertEquals; +37 import static org.junit.Assert.assertFalse; +38 import static org.junit.Assert.assertTrue; +39 +40 /** +41 * Unit tests for NodePackageAnalyzer. +42 * +43 * @author Dale Visser +44 */ +45 public class ComposerLockAnalyzerTest extends BaseDBTestCase { +46 +47 /** +48 * The analyzer to test. +49 */ +50 ComposerLockAnalyzer analyzer; +51 +52 /** +53 * Correctly setup the analyzer for testing. +54 * +55 * @throws Exception thrown if there is a problem +56 */ +57 @Override +58 @Before +59 public void setUp() throws Exception { +60 super.setUp(); +61 analyzer = new ComposerLockAnalyzer(); +62 analyzer.setFilesMatched(true); +63 analyzer.initialize(); +64 } +65 +66 /** +67 * Cleanup the analyzer's temp files, etc. +68 * +69 * @throws Exception thrown if there is a problem +70 */ +71 @After +72 public void tearDown() throws Exception { +73 analyzer.close(); +74 analyzer = null; +75 } +76 +77 /** +78 * Test of getName method, of class ComposerLockAnalyzer. +79 */ +80 @Test +81 public void testGetName() { +82 assertEquals("Composer.lock analyzer", analyzer.getName()); +83 } +84 +85 /** +86 * Test of supportsExtension method, of class ComposerLockAnalyzer. +87 */ +88 @Test +89 public void testSupportsFiles() { +90 assertTrue(analyzer.accept(new File("composer.lock"))); +91 } +92 +93 /** +94 * Test of inspect method, of class PythonDistributionAnalyzer. +95 * +96 * @throws AnalysisException is thrown when an exception occurs. +97 */ +98 @Test +99 public void testAnalyzePackageJson() throws Exception { +100 final Engine engine = new Engine(); +101 final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, +102 "composer.lock")); +103 analyzer.analyze(result, engine); +104 } +105 +106 +107 @Test(expected = InitializationException.class) +108 public void analyzerIsDisabledInCaseOfMissingMessageDigest() throws InitializationException { +109 new MockUp<MessageDigest>() { +110 @Mock +111 MessageDigest getInstance(String ignore) throws NoSuchAlgorithmException { +112 throw new NoSuchAlgorithmException(); +113 } +114 }; +115 +116 analyzer = new ComposerLockAnalyzer(); +117 analyzer.setFilesMatched(true); +118 assertTrue(analyzer.isEnabled()); +119 analyzer.initialize(); +120 +121 assertFalse(analyzer.isEnabled()); +122 } +123 }
      diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.html index 8e352a382..6e75d0e96 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.html @@ -25,112 +25,130 @@ 17 */ 18 package org.owasp.dependencycheck.analyzer; 19 -20 import static org.junit.Assert.assertEquals; -21 import org.junit.Test; -22 import org.owasp.dependencycheck.BaseTest; -23 import org.owasp.dependencycheck.dependency.Dependency; -24 -25 /** -26 * -27 * @author Jeremy Long -28 */ -29 public class DependencyBundlingAnalyzerTest extends BaseTest { +20 import mockit.Mocked; +21 import mockit.Verifications; +22 import org.junit.Test; +23 import org.owasp.dependencycheck.BaseTest; +24 import org.owasp.dependencycheck.Engine; +25 import org.owasp.dependencycheck.dependency.Dependency; +26 +27 import static org.junit.Assert.assertEquals; +28 import static org.junit.Assert.assertFalse; +29 import static org.junit.Assert.assertTrue; 30 -31 /** -32 * Test of getName method, of class DependencyBundlingAnalyzer. -33 */ -34 @Test -35 public void testGetName() { -36 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); -37 String expResult = "Dependency Bundling Analyzer"; -38 String result = instance.getName(); -39 assertEquals(expResult, result); -40 } -41 -42 /** -43 * Test of getAnalysisPhase method, of class DependencyBundlingAnalyzer. -44 */ -45 @Test -46 public void testGetAnalysisPhase() { -47 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); -48 AnalysisPhase expResult = AnalysisPhase.PRE_FINDING_ANALYSIS; -49 AnalysisPhase result = instance.getAnalysisPhase(); -50 assertEquals(expResult, result); -51 } -52 -53 /** -54 * Test of analyze method, of class DependencyBundlingAnalyzer. -55 */ -56 @Test -57 public void testAnalyze() throws Exception { -58 // Dependency ignore = null; -59 // Engine engine = null; -60 // DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); -61 // instance.analyze(ignore, engine); -62 // // TODO review the generated test code and remove the default call to fail. -63 // fail("The test case is a prototype."); -64 } -65 -66 /** -67 * Test of isCore method, of class DependencyBundlingAnalyzer. -68 */ -69 @Test -70 public void testIsCore() { -71 Dependency left = new Dependency(); -72 Dependency right = new Dependency(); -73 -74 left.setFileName("axis2-kernel-1.4.1.jar"); -75 right.setFileName("axis2-adb-1.4.1.jar"); -76 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); -77 boolean expResult = true; -78 boolean result = instance.isCore(left, right); -79 assertEquals(expResult, result); -80 -81 left.setFileName("struts-1.2.7.jar"); -82 right.setFileName("file.tar.gz\\file.tar\\struts.jar"); -83 -84 expResult = true; -85 result = instance.isCore(left, right); -86 assertEquals(expResult, result); -87 } -88 +31 /** +32 * @author Jeremy Long +33 */ +34 public class DependencyBundlingAnalyzerTest extends BaseTest { +35 +36 @Mocked +37 Engine engineMock; +38 +39 /** +40 * Test of getName method, of class DependencyBundlingAnalyzer. +41 */ +42 @Test +43 public void testGetName() { +44 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); +45 String expResult = "Dependency Bundling Analyzer"; +46 String result = instance.getName(); +47 assertEquals(expResult, result); +48 } +49 +50 /** +51 * Test of getAnalysisPhase method, of class DependencyBundlingAnalyzer. +52 */ +53 @Test +54 public void testGetAnalysisPhase() { +55 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); +56 AnalysisPhase expResult = AnalysisPhase.PRE_FINDING_ANALYSIS; +57 AnalysisPhase result = instance.getAnalysisPhase(); +58 assertEquals(expResult, result); +59 } +60 +61 /** +62 * Test of analyze method, of class DependencyBundlingAnalyzer. +63 * The actually passed dependency does not matter. The analyzer only runs once. +64 */ +65 @Test +66 public void testAnalyze() throws Exception { +67 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); +68 +69 // the actual dependency does not matter +70 assertFalse(instance.getAnalyzed()); +71 instance.analyze(null, engineMock); +72 +73 // the second runs basically does nothing +74 assertTrue(instance.getAnalyzed()); +75 instance.analyze(null, engineMock); +76 instance.analyze(null, engineMock); +77 instance.analyze(null, engineMock); +78 assertTrue(instance.getAnalyzed()); +79 +80 new Verifications() {{ +81 engineMock.getDependencies(); +82 times = 2; +83 }}; +84 } +85 +86 /** +87 * Test of isCore method, of class DependencyBundlingAnalyzer. +88 */ 89 @Test -90 public void testFirstPathIsShortest() { -91 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); -92 -93 String left = "./a/c.jar"; -94 String right = "./d/e/f.jar"; -95 boolean expResult = true; -96 boolean result = instance.firstPathIsShortest(left, right); -97 assertEquals(expResult, result); -98 -99 left = "./a/b/c.jar"; -100 right = "./d/e/f.jar"; -101 expResult = true; -102 result = instance.firstPathIsShortest(left, right); -103 assertEquals(expResult, result); -104 -105 left = "./d/b/c.jar"; -106 right = "./a/e/f.jar"; -107 expResult = false; -108 result = instance.firstPathIsShortest(left, right); -109 assertEquals(expResult, result); -110 -111 left = "./a/b/c.jar"; -112 right = "./d/f.jar"; -113 expResult = false; -114 result = instance.firstPathIsShortest(left, right); -115 assertEquals(expResult, result); -116 -117 left = "./a/b/c.jar"; -118 right = "./a/b/c.jar"; -119 expResult = true; -120 result = instance.firstPathIsShortest(left, right); -121 assertEquals(expResult, result); -122 -123 } +90 public void testIsCore() { +91 Dependency left = new Dependency(); +92 Dependency right = new Dependency(); +93 +94 left.setFileName("axis2-kernel-1.4.1.jar"); +95 right.setFileName("axis2-adb-1.4.1.jar"); +96 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); +97 boolean expResult = true; +98 boolean result = instance.isCore(left, right); +99 assertEquals(expResult, result); +100 +101 left.setFileName("struts-1.2.7.jar"); +102 right.setFileName("file.tar.gz\\file.tar\\struts.jar"); +103 +104 expResult = true; +105 result = instance.isCore(left, right); +106 assertEquals(expResult, result); +107 } +108 +109 @Test +110 public void testFirstPathIsShortest() { +111 DependencyBundlingAnalyzer instance = new DependencyBundlingAnalyzer(); +112 +113 String left = "./a/c.jar"; +114 String right = "./d/e/f.jar"; +115 boolean expResult = true; +116 boolean result = instance.firstPathIsShortest(left, right); +117 assertEquals(expResult, result); +118 +119 left = "./a/b/c.jar"; +120 right = "./d/e/f.jar"; +121 expResult = true; +122 result = instance.firstPathIsShortest(left, right); +123 assertEquals(expResult, result); 124 -125 } +125 left = "./d/b/c.jar"; +126 right = "./a/e/f.jar"; +127 expResult = false; +128 result = instance.firstPathIsShortest(left, right); +129 assertEquals(expResult, result); +130 +131 left = "./a/b/c.jar"; +132 right = "./d/f.jar"; +133 expResult = false; +134 result = instance.firstPathIsShortest(left, right); +135 assertEquals(expResult, result); +136 +137 left = "./a/b/c.jar"; +138 right = "./a/b/c.jar"; +139 expResult = true; +140 result = instance.firstPathIsShortest(left, right); +141 assertEquals(expResult, result); +142 } +143 }
      diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/package-frame.html index 9a3476fc4..a27be64fd 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.analyzer diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/package-summary.html index 71e087843..f626bf635 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/analyzer/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.analyzer diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/central/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/central/package-frame.html index fed1488d5..baad6c22d 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/central/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/central/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.central diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/central/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/central/package-summary.html index 53d4a8081..ddf4d4229 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/central/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/central/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.central diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/composer/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/composer/package-frame.html index ac762f573..7ff899204 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/composer/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/composer/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.composer diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/composer/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/composer/package-summary.html index 647d277b8..16445aba7 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/composer/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/composer/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.composer diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cpe/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cpe/package-frame.html index 60b71a47b..e1a354563 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cpe/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cpe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.cpe diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cpe/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cpe/package-summary.html index 50a570359..1edab1600 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cpe/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cpe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.cpe diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cwe/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cwe/package-frame.html index 2d6a6718b..88435bcca 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cwe/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cwe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.cwe diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cwe/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cwe/package-summary.html index 29407e190..96c1521c7 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cwe/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/cwe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.cwe diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/lucene/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/lucene/package-frame.html index 344e73d10..1aa2cb9f2 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/lucene/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/lucene/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.lucene diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/lucene/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/lucene/package-summary.html index 8a992b644..f195686c4 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/lucene/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/lucene/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.lucene diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/NexusSearchTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/NexusSearchTest.html index 9b55a6a22..ba2d93169 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/NexusSearchTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/NexusSearchTest.html @@ -34,59 +34,60 @@ 26 import org.junit.Ignore; 27 import org.junit.Test; 28 import org.owasp.dependencycheck.BaseTest; -29 import org.owasp.dependencycheck.utils.Settings; -30 import org.slf4j.Logger; -31 import org.slf4j.LoggerFactory; -32 -33 public class NexusSearchTest extends BaseTest { -34 -35 private static final Logger LOGGER = LoggerFactory.getLogger(NexusSearchTest.class); -36 private NexusSearch searcher; -37 -38 @Before -39 public void setUp() throws Exception { -40 String nexusUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL); -41 LOGGER.debug(nexusUrl); -42 searcher = new NexusSearch(new URL(nexusUrl)); -43 Assume.assumeTrue(searcher.preflightRequest()); -44 } -45 -46 @Test(expected = IllegalArgumentException.class) -47 @Ignore -48 public void testNullSha1() throws Exception { -49 searcher.searchSha1(null); -50 } -51 -52 @Test(expected = IllegalArgumentException.class) -53 @Ignore -54 public void testMalformedSha1() throws Exception { -55 searcher.searchSha1("invalid"); -56 } -57 -58 // This test does generate network traffic and communicates with a host -59 // you may not be able to reach. Remove the @Ignore annotation if you want to -60 // test it anyway -61 @Test -62 @Ignore -63 public void testValidSha1() throws Exception { -64 MavenArtifact ma = searcher.searchSha1("9977a8d04e75609cf01badc4eb6a9c7198c4c5ea"); -65 assertEquals("Incorrect group", "org.apache.maven.plugins", ma.getGroupId()); -66 assertEquals("Incorrect artifact", "maven-compiler-plugin", ma.getArtifactId()); -67 assertEquals("Incorrect version", "3.1", ma.getVersion()); -68 assertNotNull("URL Should not be null", ma.getArtifactUrl()); -69 } -70 -71 // This test does generate network traffic and communicates with a host -72 // you may not be able to reach. Remove the @Ignore annotation if you want to -73 // test it anyway -74 @Test(expected = FileNotFoundException.class) -75 @Ignore -76 public void testMissingSha1() throws Exception { -77 searcher.searchSha1("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); -78 } -79 } -80 -81 // vim: cc=120:sw=4:ts=4:sts=4 +29 import org.owasp.dependencycheck.analyzer.NexusAnalyzer; +30 import org.owasp.dependencycheck.utils.Settings; +31 import org.slf4j.Logger; +32 import org.slf4j.LoggerFactory; +33 +34 public class NexusSearchTest extends BaseTest { +35 +36 private static final Logger LOGGER = LoggerFactory.getLogger(NexusSearchTest.class); +37 private NexusSearch searcher; +38 +39 @Before +40 public void setUp() throws Exception { +41 String nexusUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL); +42 LOGGER.debug(nexusUrl); +43 searcher = new NexusSearch(new URL(nexusUrl), NexusAnalyzer.useProxy()); +44 Assume.assumeTrue(searcher.preflightRequest()); +45 } +46 +47 @Test(expected = IllegalArgumentException.class) +48 @Ignore +49 public void testNullSha1() throws Exception { +50 searcher.searchSha1(null); +51 } +52 +53 @Test(expected = IllegalArgumentException.class) +54 @Ignore +55 public void testMalformedSha1() throws Exception { +56 searcher.searchSha1("invalid"); +57 } +58 +59 // This test does generate network traffic and communicates with a host +60 // you may not be able to reach. Remove the @Ignore annotation if you want to +61 // test it anyway +62 @Test +63 @Ignore +64 public void testValidSha1() throws Exception { +65 MavenArtifact ma = searcher.searchSha1("9977a8d04e75609cf01badc4eb6a9c7198c4c5ea"); +66 assertEquals("Incorrect group", "org.apache.maven.plugins", ma.getGroupId()); +67 assertEquals("Incorrect artifact", "maven-compiler-plugin", ma.getArtifactId()); +68 assertEquals("Incorrect version", "3.1", ma.getVersion()); +69 assertNotNull("URL Should not be null", ma.getArtifactUrl()); +70 } +71 +72 // This test does generate network traffic and communicates with a host +73 // you may not be able to reach. Remove the @Ignore annotation if you want to +74 // test it anyway +75 @Test(expected = FileNotFoundException.class) +76 @Ignore +77 public void testMissingSha1() throws Exception { +78 searcher.searchSha1("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); +79 } +80 } +81 +82 // vim: cc=120:sw=4:ts=4:sts=4
      diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/package-frame.html index 02f59cec6..81254591a 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nexus diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/package-summary.html index 9e4b312ba..07417682b 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nexus/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nexus diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nuget/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nuget/package-frame.html index 66257befa..6c186de8f 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nuget/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nuget/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nuget/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nuget/package-summary.html index 3fbfb5760..b15117a64 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nuget/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nuget/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nvdcve/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nvdcve/package-frame.html index 328555170..b7afc298b 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nvdcve/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nvdcve/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nvdcve diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nvdcve/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nvdcve/package-summary.html index b8790d31b..7557c5edf 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nvdcve/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/nvdcve/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nvdcve diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/nvd/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/nvd/package-frame.html index ee732556a..074491bde 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/nvd/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/nvd/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update.nvd diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/nvd/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/nvd/package-summary.html index dd3307e96..71237a35d 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/nvd/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/nvd/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update.nvd diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/package-frame.html index 070bd9485..271ce4a27 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/package-summary.html index 5c26f559e..2c998f73b 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/data/update/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/dependency/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/dependency/package-frame.html index bca7a96ca..63daa89a4 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/dependency/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/dependency/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.dependency diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/dependency/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/dependency/package-summary.html index 0f8dbd4b1..ba3c86a23 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/dependency/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/dependency/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.dependency diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/package-frame.html index f09f21625..0e84aea60 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck @@ -16,6 +16,9 @@ diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/package-summary.html index 7ee87d3e7..0ba315af5 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck @@ -36,6 +36,11 @@ + + AnalysisTaskTest + + + BaseDBTestCase @@ -49,6 +54,11 @@ EngineIntegrationTest + + + + EngineTest + diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/reporting/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/reporting/package-frame.html index bfe2a7523..4308ea1b5 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/reporting/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/reporting/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.reporting diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/reporting/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/reporting/package-summary.html index 5c3817787..790eb9c48 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/reporting/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/reporting/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.reporting diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/DependencyVersionTest.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/DependencyVersionTest.html index 931321b6a..1d6311bf6 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/DependencyVersionTest.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/DependencyVersionTest.html @@ -104,108 +104,121 @@ 96 expResult = true; 97 result = instance.equals(obj); 98 assertEquals(expResult, result); -99 } -100 -101 /** -102 * Test of hashCode method, of class DependencyVersion. -103 */ -104 @Test -105 public void testHashCode() { -106 DependencyVersion instance = new DependencyVersion("3.2.1"); -107 int expResult = 80756; -108 int result = instance.hashCode(); +99 +100 instance = new DependencyVersion("2.0.0"); +101 obj = new DependencyVersion("2"); +102 expResult = false; +103 result = instance.equals(obj); +104 assertEquals(expResult, result); +105 +106 obj = new DependencyVersion("2.0"); +107 expResult = true; +108 result = instance.equals(obj); 109 assertEquals(expResult, result); -110 } -111 -112 /** -113 * Test of matchesAtLeastThreeLevels method, of class DependencyVersion. -114 */ -115 @Test -116 public void testMatchesAtLeastThreeLevels() { -117 -118 DependencyVersion instance = new DependencyVersion("2.3.16.3"); -119 DependencyVersion version = new DependencyVersion("2.3.16.4"); -120 //true tests -121 assertEquals(true, instance.matchesAtLeastThreeLevels(version)); -122 version = new DependencyVersion("2.3"); -123 assertEquals(true, instance.matchesAtLeastThreeLevels(version)); -124 //false tests -125 version = new DependencyVersion("2.3.16.1"); -126 assertEquals(false, instance.matchesAtLeastThreeLevels(version)); -127 version = new DependencyVersion("2"); -128 assertEquals(false, instance.matchesAtLeastThreeLevels(version)); -129 } +110 +111 +112 } +113 +114 /** +115 * Test of hashCode method, of class DependencyVersion. +116 */ +117 @Test +118 public void testHashCode() { +119 DependencyVersion instance = new DependencyVersion("3.2.1"); +120 int expResult = 80756; +121 int result = instance.hashCode(); +122 assertEquals(expResult, result); +123 } +124 +125 /** +126 * Test of matchesAtLeastThreeLevels method, of class DependencyVersion. +127 */ +128 @Test +129 public void testMatchesAtLeastThreeLevels() { 130 -131 /** -132 * Test of compareTo method, of class DependencyVersion. -133 */ -134 @Test -135 public void testCompareTo() { -136 DependencyVersion instance = new DependencyVersion("1.2.3"); -137 DependencyVersion version = new DependencyVersion("1.2.3"); -138 assertEquals(0, instance.compareTo(version)); -139 version = new DependencyVersion("1.1"); -140 assertEquals(1, instance.compareTo(version)); -141 version = new DependencyVersion("1.2"); -142 assertEquals(1, instance.compareTo(version)); -143 version = new DependencyVersion("1.3"); -144 assertEquals(-1, instance.compareTo(version)); -145 version = new DependencyVersion("1.2.3.1"); -146 assertEquals(-1, instance.compareTo(version)); -147 -148 instance = new DependencyVersion("1.0.1n"); -149 version = new DependencyVersion("1.0.1m"); -150 assertEquals(1, instance.compareTo(version)); -151 version = new DependencyVersion("1.0.1n"); -152 assertEquals(0, instance.compareTo(version)); -153 version = new DependencyVersion("1.0.1o"); -154 assertEquals(-1, instance.compareTo(version)); -155 -156 DependencyVersion[] dv = new DependencyVersion[7]; -157 dv[0] = new DependencyVersion("2.1.3"); -158 dv[1] = new DependencyVersion("2.1.3.r2"); -159 dv[2] = new DependencyVersion("2.1.3.r1"); -160 dv[3] = new DependencyVersion("1.2.3.1"); -161 dv[4] = new DependencyVersion("1.2.3"); -162 dv[5] = new DependencyVersion("2"); -163 dv[6] = new DependencyVersion("-"); -164 -165 DependencyVersion[] expected = new DependencyVersion[7]; -166 expected[0] = new DependencyVersion("-"); -167 expected[1] = new DependencyVersion("1.2.3"); -168 expected[2] = new DependencyVersion("1.2.3.1"); -169 expected[3] = new DependencyVersion("2"); -170 expected[4] = new DependencyVersion("2.1.3"); -171 expected[5] = new DependencyVersion("2.1.3.r1"); -172 expected[6] = new DependencyVersion("2.1.3.r2"); -173 java.util.Arrays.sort(dv); -174 -175 assertArrayEquals(expected, dv); -176 } +131 DependencyVersion instance = new DependencyVersion("2.3.16.3"); +132 DependencyVersion version = new DependencyVersion("2.3.16.4"); +133 //true tests +134 assertEquals(true, instance.matchesAtLeastThreeLevels(version)); +135 version = new DependencyVersion("2.3"); +136 assertEquals(true, instance.matchesAtLeastThreeLevels(version)); +137 //false tests +138 version = new DependencyVersion("2.3.16.1"); +139 assertEquals(false, instance.matchesAtLeastThreeLevels(version)); +140 version = new DependencyVersion("2"); +141 assertEquals(false, instance.matchesAtLeastThreeLevels(version)); +142 } +143 +144 /** +145 * Test of compareTo method, of class DependencyVersion. +146 */ +147 @Test +148 public void testCompareTo() { +149 DependencyVersion instance = new DependencyVersion("1.2.3"); +150 DependencyVersion version = new DependencyVersion("1.2.3"); +151 assertEquals(0, instance.compareTo(version)); +152 version = new DependencyVersion("1.1"); +153 assertEquals(1, instance.compareTo(version)); +154 version = new DependencyVersion("1.2"); +155 assertEquals(1, instance.compareTo(version)); +156 version = new DependencyVersion("1.3"); +157 assertEquals(-1, instance.compareTo(version)); +158 version = new DependencyVersion("1.2.3.1"); +159 assertEquals(-1, instance.compareTo(version)); +160 +161 instance = new DependencyVersion("1.0.1n"); +162 version = new DependencyVersion("1.0.1m"); +163 assertEquals(1, instance.compareTo(version)); +164 version = new DependencyVersion("1.0.1n"); +165 assertEquals(0, instance.compareTo(version)); +166 version = new DependencyVersion("1.0.1o"); +167 assertEquals(-1, instance.compareTo(version)); +168 +169 DependencyVersion[] dv = new DependencyVersion[7]; +170 dv[0] = new DependencyVersion("2.1.3"); +171 dv[1] = new DependencyVersion("2.1.3.r2"); +172 dv[2] = new DependencyVersion("2.1.3.r1"); +173 dv[3] = new DependencyVersion("1.2.3.1"); +174 dv[4] = new DependencyVersion("1.2.3"); +175 dv[5] = new DependencyVersion("2"); +176 dv[6] = new DependencyVersion("-"); 177 -178 /** -179 * Test of getVersionParts method, of class DependencyVersion. -180 */ -181 @Test -182 public void testGetVersionParts() { -183 DependencyVersion instance = new DependencyVersion(); -184 List<String> versionParts = Arrays.asList("1", "1", "1"); -185 instance.setVersionParts(versionParts); -186 List<String> expResult = Arrays.asList("1", "1", "1"); -187 List<String> result = instance.getVersionParts(); -188 assertEquals(expResult, result); +178 DependencyVersion[] expected = new DependencyVersion[7]; +179 expected[0] = new DependencyVersion("-"); +180 expected[1] = new DependencyVersion("1.2.3"); +181 expected[2] = new DependencyVersion("1.2.3.1"); +182 expected[3] = new DependencyVersion("2"); +183 expected[4] = new DependencyVersion("2.1.3"); +184 expected[5] = new DependencyVersion("2.1.3.r1"); +185 expected[6] = new DependencyVersion("2.1.3.r2"); +186 java.util.Arrays.sort(dv); +187 +188 assertArrayEquals(expected, dv); 189 } 190 191 /** -192 * Test of setVersionParts method, of class DependencyVersion. +192 * Test of getVersionParts method, of class DependencyVersion. 193 */ 194 @Test -195 public void testSetVersionParts() { -196 List<String> versionParts = Arrays.asList("1", "1", "1"); -197 DependencyVersion instance = new DependencyVersion(); +195 public void testGetVersionParts() { +196 DependencyVersion instance = new DependencyVersion(); +197 List<String> versionParts = Arrays.asList("1", "1", "1"); 198 instance.setVersionParts(versionParts); -199 } -200 } +199 List<String> expResult = Arrays.asList("1", "1", "1"); +200 List<String> result = instance.getVersionParts(); +201 assertEquals(expResult, result); +202 } +203 +204 /** +205 * Test of setVersionParts method, of class DependencyVersion. +206 */ +207 @Test +208 public void testSetVersionParts() { +209 List<String> versionParts = Arrays.asList("1", "1", "1"); +210 DependencyVersion instance = new DependencyVersion(); +211 instance.setVersionParts(versionParts); +212 } +213 }
      diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/package-frame.html index 5ad5102dc..4bda0fd5c 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/package-summary.html index 8884a7097..95d23cac1 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/utils/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/package-frame.html index 0cdebc918..2fbb0a5b5 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/package-summary.html index e818d33bf..7b1d0ef0f 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/hints/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/pom/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/pom/package-frame.html index 7965e7f28..c0cccad1e 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/pom/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/pom/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/pom/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/pom/package-summary.html index 018ec9d8c..e0539a955 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/pom/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/pom/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/suppression/package-frame.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/suppression/package-frame.html index 5ef0c33b5..5c27ef4af 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/suppression/package-frame.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/suppression/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.suppression diff --git a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/suppression/package-summary.html b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/suppression/package-summary.html index fcf079aee..0a1e6dcd1 100644 --- a/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/suppression/package-summary.html +++ b/dependency-check-core/xref-test/org/owasp/dependencycheck/xml/suppression/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.suppression diff --git a/dependency-check-core/xref-test/overview-frame.html b/dependency-check-core/xref-test/overview-frame.html index 65b25635e..dffc7814b 100644 --- a/dependency-check-core/xref-test/overview-frame.html +++ b/dependency-check-core/xref-test/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference + Dependency-Check Core 1.4.4 Reference diff --git a/dependency-check-core/xref-test/overview-summary.html b/dependency-check-core/xref-test/overview-summary.html index e688ce64b..d62286606 100644 --- a/dependency-check-core/xref-test/overview-summary.html +++ b/dependency-check-core/xref-test/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference + Dependency-Check Core 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Core 1.4.3 Reference

      +

      Dependency-Check Core 1.4.4 Reference

      diff --git a/dependency-check-core/xref/allclasses-frame.html b/dependency-check-core/xref/allclasses-frame.html index 013dbcdc5..22ce42385 100644 --- a/dependency-check-core/xref/allclasses-frame.html +++ b/dependency-check-core/xref/allclasses-frame.html @@ -31,6 +31,9 @@
    14. AnalysisPhase +
    15. +
    16. + AnalysisTask
    17. Analyzer diff --git a/dependency-check-core/xref/index.html b/dependency-check-core/xref/index.html index 415806e7b..56d800cfe 100644 --- a/dependency-check-core/xref/index.html +++ b/dependency-check-core/xref/index.html @@ -4,7 +4,7 @@ - Dependency-Check Core 1.4.3 Reference + Dependency-Check Core 1.4.4 Reference diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/AnalysisTask.html b/dependency-check-core/xref/org/owasp/dependencycheck/AnalysisTask.html new file mode 100644 index 000000000..266b3f14a --- /dev/null +++ b/dependency-check-core/xref/org/owasp/dependencycheck/AnalysisTask.html @@ -0,0 +1,132 @@ + + + +AnalysisTask xref + + + +
      +1   /*
      +2    * This file is part of dependency-check-core.
      +3    *
      +4    * Licensed under the Apache License, Version 2.0 (the "License");
      +5    * you may not use this file except in compliance with the License.
      +6    * You may obtain a copy of the License at
      +7    *
      +8    *     http://www.apache.org/licenses/LICENSE-2.0
      +9    *
      +10   * Unless required by applicable law or agreed to in writing, software
      +11   * distributed under the License is distributed on an "AS IS" BASIS,
      +12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      +13   * See the License for the specific language governing permissions and
      +14   * limitations under the License.
      +15   *
      +16   * Copyright (c) 2016 Stefan Neuhaus. All Rights Reserved.
      +17   */
      +18  package org.owasp.dependencycheck;
      +19  
      +20  import org.owasp.dependencycheck.analyzer.Analyzer;
      +21  import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
      +22  import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
      +23  import org.owasp.dependencycheck.dependency.Dependency;
      +24  import org.owasp.dependencycheck.utils.Settings;
      +25  import org.slf4j.Logger;
      +26  import org.slf4j.LoggerFactory;
      +27  
      +28  import java.util.List;
      +29  import java.util.concurrent.Callable;
      +30  
      +31  /**
      +32   * Task to support parallelism of dependency-check analysis.
      +33   * Analyses a single {@link Dependency} by a specific {@link Analyzer}.
      +34   *
      +35   * @author Stefan Neuhaus
      +36   */
      +37  class AnalysisTask implements Callable<Void> {
      +38  
      +39      /**
      +40       * Instance of the logger.
      +41       */
      +42      private static final Logger LOGGER = LoggerFactory.getLogger(AnalysisTask.class);
      +43  
      +44      /**
      +45       * A reference to the analyzer.
      +46       */
      +47      private final Analyzer analyzer;
      +48      /**
      +49       * The dependency to analyze.
      +50       */
      +51      private final Dependency dependency;
      +52      /**
      +53       * A reference to the dependency-check engine.
      +54       */
      +55      private final Engine engine;
      +56      /**
      +57       * The list of exceptions that may occur during analysis.
      +58       */
      +59      private final List<Throwable> exceptions;
      +60  
      +61      /**
      +62       * Creates a new analysis task.
      +63       *
      +64       * @param analyzer a reference of the analyzer to execute
      +65       * @param dependency the dependency to analyze
      +66       * @param engine the dependency-check engine
      +67       * @param exceptions exceptions that occur during analysis will be added to
      +68       * this collection of exceptions
      +69       */
      +70      AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List<Throwable> exceptions) {
      +71          this.analyzer = analyzer;
      +72          this.dependency = dependency;
      +73          this.engine = engine;
      +74          this.exceptions = exceptions;
      +75      }
      +76  
      +77      /**
      +78       * Executes the analysis task.
      +79       *
      +80       * @return null
      +81       * @throws Exception thrown if unable to execute the analysis task
      +82       */
      +83      @Override
      +84      public Void call() {
      +85          Settings.initialize();
      +86  
      +87          if (shouldAnalyze()) {
      +88              LOGGER.debug("Begin Analysis of '{}' ({})", dependency.getActualFilePath(), analyzer.getName());
      +89              try {
      +90                  analyzer.analyze(dependency, engine);
      +91              } catch (AnalysisException ex) {
      +92                  LOGGER.warn("An error occurred while analyzing '{}' ({}).", dependency.getActualFilePath(), analyzer.getName());
      +93                  LOGGER.debug("", ex);
      +94                  exceptions.add(ex);
      +95              } catch (Throwable ex) {
      +96                  LOGGER.warn("An unexpected error occurred during analysis of '{}' ({}): {}",
      +97                          dependency.getActualFilePath(), analyzer.getName(), ex.getMessage());
      +98                  LOGGER.debug("", ex);
      +99                  exceptions.add(ex);
      +100             }
      +101         }
      +102 
      +103         return null;
      +104     }
      +105 
      +106     /**
      +107      * Determines if the analyzer can analyze the given dependency.
      +108      *
      +109      * @return whether or not the analyzer can analyze the dependency
      +110      */
      +111     boolean shouldAnalyze() {
      +112         if (analyzer instanceof FileTypeAnalyzer) {
      +113             final FileTypeAnalyzer fileTypeAnalyzer = (FileTypeAnalyzer) analyzer;
      +114             return fileTypeAnalyzer.accept(dependency.getActualFile());
      +115         }
      +116 
      +117         return true;
      +118     }
      +119 }
      +
      +
      + + + diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/Engine.html b/dependency-check-core/xref/org/owasp/dependencycheck/Engine.html index e4cd6cf99..587799cf5 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/Engine.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/Engine.html @@ -29,546 +29,758 @@ 21 import org.owasp.dependencycheck.analyzer.Analyzer; 22 import org.owasp.dependencycheck.analyzer.AnalyzerService; 23 import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer; -24 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -25 import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory; -26 import org.owasp.dependencycheck.data.nvdcve.CveDB; -27 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -28 import org.owasp.dependencycheck.data.update.CachedWebDataSource; -29 import org.owasp.dependencycheck.data.update.UpdateService; -30 import org.owasp.dependencycheck.data.update.exception.UpdateException; -31 import org.owasp.dependencycheck.dependency.Dependency; -32 import org.owasp.dependencycheck.exception.NoDataException; -33 import org.owasp.dependencycheck.exception.ExceptionCollection; -34 import org.owasp.dependencycheck.exception.InitializationException; -35 import org.owasp.dependencycheck.utils.InvalidSettingException; -36 import org.owasp.dependencycheck.utils.Settings; -37 import org.slf4j.Logger; -38 import org.slf4j.LoggerFactory; -39 -40 import java.io.File; -41 import java.io.FileFilter; -42 import java.util.ArrayList; -43 import java.util.Collection; +24 import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory; +25 import org.owasp.dependencycheck.data.nvdcve.CveDB; +26 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +27 import org.owasp.dependencycheck.data.update.CachedWebDataSource; +28 import org.owasp.dependencycheck.data.update.UpdateService; +29 import org.owasp.dependencycheck.data.update.exception.UpdateException; +30 import org.owasp.dependencycheck.dependency.Dependency; +31 import org.owasp.dependencycheck.exception.ExceptionCollection; +32 import org.owasp.dependencycheck.exception.InitializationException; +33 import org.owasp.dependencycheck.exception.NoDataException; +34 import org.owasp.dependencycheck.utils.InvalidSettingException; +35 import org.owasp.dependencycheck.utils.Settings; +36 import org.slf4j.Logger; +37 import org.slf4j.LoggerFactory; +38 +39 import java.io.File; +40 import java.io.FileFilter; +41 import java.util.ArrayList; +42 import java.util.Collection; +43 import java.util.Collections; 44 import java.util.EnumMap; 45 import java.util.HashSet; 46 import java.util.Iterator; 47 import java.util.List; 48 import java.util.Map; 49 import java.util.Set; -50 -51 /** -52 * Scans files, directories, etc. for Dependencies. Analyzers are loaded and -53 * used to process the files found by the scan, if a file is encountered and an -54 * Analyzer is associated with the file type then the file is turned into a -55 * dependency. -56 * -57 * @author Jeremy Long -58 */ -59 public class Engine implements FileFilter { -60 -61 /** -62 * The list of dependencies. -63 */ -64 private List<Dependency> dependencies = new ArrayList<Dependency>(); -65 /** -66 * A Map of analyzers grouped by Analysis phase. -67 */ -68 private final Map<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class); -69 -70 /** -71 * A Map of analyzers grouped by Analysis phase. -72 */ -73 private final Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>(); -74 -75 /** -76 * The ClassLoader to use when dynamically loading Analyzer and Update -77 * services. +50 import java.util.concurrent.CancellationException; +51 import java.util.concurrent.ExecutionException; +52 import java.util.concurrent.ExecutorService; +53 import java.util.concurrent.Executors; +54 import java.util.concurrent.Future; +55 import java.util.concurrent.TimeUnit; +56 +57 /** +58 * Scans files, directories, etc. for Dependencies. Analyzers are loaded and +59 * used to process the files found by the scan, if a file is encountered and an +60 * Analyzer is associated with the file type then the file is turned into a +61 * dependency. +62 * +63 * @author Jeremy Long +64 */ +65 public class Engine implements FileFilter { +66 +67 /** +68 * The list of dependencies. +69 */ +70 private final List<Dependency> dependencies = Collections.synchronizedList(new ArrayList<Dependency>()); +71 /** +72 * A Map of analyzers grouped by Analysis phase. +73 */ +74 private final Map<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class); +75 +76 /** +77 * A Map of analyzers grouped by Analysis phase. 78 */ -79 private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader(); -80 /** -81 * The Logger for use throughout the class. -82 */ -83 private static final Logger LOGGER = LoggerFactory.getLogger(Engine.class); -84 -85 /** -86 * Creates a new Engine. -87 * -88 * @throws DatabaseException thrown if there is an error connecting to the -89 * database -90 */ -91 public Engine() throws DatabaseException { -92 initializeEngine(); -93 } -94 -95 /** -96 * Creates a new Engine. -97 * -98 * @param serviceClassLoader a reference the class loader being used -99 * @throws DatabaseException thrown if there is an error connecting to the -100 * database -101 */ -102 public Engine(ClassLoader serviceClassLoader) throws DatabaseException { -103 this.serviceClassLoader = serviceClassLoader; -104 initializeEngine(); -105 } -106 -107 /** -108 * Creates a new Engine using the specified classloader to dynamically load -109 * Analyzer and Update services. -110 * -111 * @throws DatabaseException thrown if there is an error connecting to the -112 * database -113 */ -114 protected final void initializeEngine() throws DatabaseException { -115 ConnectionFactory.initialize(); -116 loadAnalyzers(); -117 } -118 -119 /** -120 * Properly cleans up resources allocated during analysis. -121 */ -122 public void cleanup() { -123 ConnectionFactory.cleanup(); -124 } -125 -126 /** -127 * Loads the analyzers specified in the configuration file (or system -128 * properties). -129 */ -130 private void loadAnalyzers() { -131 if (!analyzers.isEmpty()) { -132 return; -133 } -134 for (AnalysisPhase phase : AnalysisPhase.values()) { -135 analyzers.put(phase, new ArrayList<Analyzer>()); -136 } -137 -138 final AnalyzerService service = new AnalyzerService(serviceClassLoader); -139 final List<Analyzer> iterator = service.getAnalyzers(); -140 for (Analyzer a : iterator) { -141 analyzers.get(a.getAnalysisPhase()).add(a); -142 if (a instanceof FileTypeAnalyzer) { -143 this.fileTypeAnalyzers.add((FileTypeAnalyzer) a); -144 } -145 } -146 } -147 -148 /** -149 * Get the List of the analyzers for a specific phase of analysis. -150 * -151 * @param phase the phase to get the configured analyzers. -152 * @return the analyzers loaded -153 */ -154 public List<Analyzer> getAnalyzers(AnalysisPhase phase) { -155 return analyzers.get(phase); -156 } -157 -158 /** -159 * Get the dependencies identified. -160 * -161 * @return the dependencies identified -162 */ -163 public List<Dependency> getDependencies() { -164 return dependencies; -165 } -166 -167 /** -168 * Sets the dependencies. +79 private final Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>(); +80 +81 /** +82 * The ClassLoader to use when dynamically loading Analyzer and Update +83 * services. +84 */ +85 private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader(); +86 /** +87 * The Logger for use throughout the class. +88 */ +89 private static final Logger LOGGER = LoggerFactory.getLogger(Engine.class); +90 +91 /** +92 * Creates a new Engine. +93 * +94 * @throws DatabaseException thrown if there is an error connecting to the +95 * database +96 */ +97 public Engine() throws DatabaseException { +98 initializeEngine(); +99 } +100 +101 /** +102 * Creates a new Engine. +103 * +104 * @param serviceClassLoader a reference the class loader being used +105 * @throws DatabaseException thrown if there is an error connecting to the +106 * database +107 */ +108 public Engine(ClassLoader serviceClassLoader) throws DatabaseException { +109 this.serviceClassLoader = serviceClassLoader; +110 initializeEngine(); +111 } +112 +113 /** +114 * Creates a new Engine using the specified classloader to dynamically load +115 * Analyzer and Update services. +116 * +117 * @throws DatabaseException thrown if there is an error connecting to the +118 * database +119 */ +120 protected final void initializeEngine() throws DatabaseException { +121 ConnectionFactory.initialize(); +122 loadAnalyzers(); +123 } +124 +125 /** +126 * Properly cleans up resources allocated during analysis. +127 */ +128 public void cleanup() { +129 ConnectionFactory.cleanup(); +130 } +131 +132 /** +133 * Loads the analyzers specified in the configuration file (or system +134 * properties). +135 */ +136 private void loadAnalyzers() { +137 if (!analyzers.isEmpty()) { +138 return; +139 } +140 for (AnalysisPhase phase : AnalysisPhase.values()) { +141 analyzers.put(phase, new ArrayList<Analyzer>()); +142 } +143 +144 final AnalyzerService service = new AnalyzerService(serviceClassLoader); +145 final List<Analyzer> iterator = service.getAnalyzers(); +146 for (Analyzer a : iterator) { +147 analyzers.get(a.getAnalysisPhase()).add(a); +148 if (a instanceof FileTypeAnalyzer) { +149 this.fileTypeAnalyzers.add((FileTypeAnalyzer) a); +150 } +151 } +152 } +153 +154 /** +155 * Get the List of the analyzers for a specific phase of analysis. +156 * +157 * @param phase the phase to get the configured analyzers. +158 * @return the analyzers loaded +159 */ +160 public List<Analyzer> getAnalyzers(AnalysisPhase phase) { +161 return analyzers.get(phase); +162 } +163 +164 /** +165 * Get the dependencies identified. The returned list is a reference to the +166 * engine's synchronized list. You must synchronize on it, when you modify +167 * and iterate over it from multiple threads. E.g. this holds for analyzers +168 * supporting parallel processing during their analysis phase. 169 * -170 * @param dependencies the dependencies -171 */ -172 public void setDependencies(List<Dependency> dependencies) { -173 this.dependencies = dependencies; -174 } -175 -176 /** -177 * Scans an array of files or directories. If a directory is specified, it -178 * will be scanned recursively. Any dependencies identified are added to the -179 * dependency collection. +170 * @return the dependencies identified +171 * @see Collections#synchronizedList(List) +172 * @see Analyzer#supportsParallelProcessing() +173 */ +174 public List<Dependency> getDependencies() { +175 return dependencies; +176 } +177 +178 /** +179 * Sets the dependencies. 180 * -181 * @param paths an array of paths to files or directories to be analyzed -182 * @return the list of dependencies scanned -183 * @since v0.3.2.5 -184 */ -185 public List<Dependency> scan(String[] paths) { -186 final List<Dependency> deps = new ArrayList<Dependency>(); -187 for (String path : paths) { -188 final List<Dependency> d = scan(path); -189 if (d != null) { -190 deps.addAll(d); -191 } -192 } -193 return deps; -194 } -195 -196 /** -197 * Scans a given file or directory. If a directory is specified, it will be -198 * scanned recursively. Any dependencies identified are added to the -199 * dependency collection. -200 * -201 * @param path the path to a file or directory to be analyzed -202 * @return the list of dependencies scanned -203 */ -204 public List<Dependency> scan(String path) { -205 final File file = new File(path); -206 return scan(file); -207 } -208 -209 /** -210 * Scans an array of files or directories. If a directory is specified, it -211 * will be scanned recursively. Any dependencies identified are added to the -212 * dependency collection. -213 * -214 * @param files an array of paths to files or directories to be analyzed. -215 * @return the list of dependencies -216 * @since v0.3.2.5 -217 */ -218 public List<Dependency> scan(File[] files) { -219 final List<Dependency> deps = new ArrayList<Dependency>(); -220 for (File file : files) { -221 final List<Dependency> d = scan(file); -222 if (d != null) { -223 deps.addAll(d); -224 } -225 } -226 return deps; -227 } -228 -229 /** -230 * Scans a collection of files or directories. If a directory is specified, -231 * it will be scanned recursively. Any dependencies identified are added to -232 * the dependency collection. -233 * -234 * @param files a set of paths to files or directories to be analyzed -235 * @return the list of dependencies scanned -236 * @since v0.3.2.5 -237 */ -238 public List<Dependency> scan(Collection<File> files) { -239 final List<Dependency> deps = new ArrayList<Dependency>(); -240 for (File file : files) { -241 final List<Dependency> d = scan(file); -242 if (d != null) { -243 deps.addAll(d); -244 } -245 } -246 return deps; -247 } -248 -249 /** -250 * Scans a given file or directory. If a directory is specified, it will be -251 * scanned recursively. Any dependencies identified are added to the -252 * dependency collection. -253 * -254 * @param file the path to a file or directory to be analyzed -255 * @return the list of dependencies scanned -256 * @since v0.3.2.4 -257 */ -258 public List<Dependency> scan(File file) { -259 if (file.exists()) { -260 if (file.isDirectory()) { -261 return scanDirectory(file); -262 } else { -263 final Dependency d = scanFile(file); -264 if (d != null) { -265 final List<Dependency> deps = new ArrayList<Dependency>(); -266 deps.add(d); -267 return deps; -268 } -269 } -270 } -271 return null; -272 } -273 -274 /** -275 * Recursively scans files and directories. Any dependencies identified are -276 * added to the dependency collection. -277 * -278 * @param dir the directory to scan -279 * @return the list of Dependency objects scanned -280 */ -281 protected List<Dependency> scanDirectory(File dir) { -282 final File[] files = dir.listFiles(); -283 final List<Dependency> deps = new ArrayList<Dependency>(); -284 if (files != null) { -285 for (File f : files) { -286 if (f.isDirectory()) { -287 final List<Dependency> d = scanDirectory(f); -288 if (d != null) { -289 deps.addAll(d); -290 } -291 } else { -292 final Dependency d = scanFile(f); -293 deps.add(d); -294 } -295 } -296 } -297 return deps; -298 } -299 -300 /** -301 * Scans a specified file. If a dependency is identified it is added to the -302 * dependency collection. -303 * -304 * @param file The file to scan -305 * @return the scanned dependency -306 */ -307 protected Dependency scanFile(File file) { -308 Dependency dependency = null; -309 if (file.isFile()) { -310 if (accept(file)) { -311 dependency = new Dependency(file); -312 dependencies.add(dependency); -313 } -314 } else { -315 LOGGER.debug("Path passed to scanFile(File) is not a file: {}. Skipping the file.", file); -316 } -317 return dependency; -318 } -319 -320 /** -321 * Runs the analyzers against all of the dependencies. Since the mutable -322 * dependencies list is exposed via {@link #getDependencies()}, this method -323 * iterates over a copy of the dependencies list. Thus, the potential for -324 * {@link java.util.ConcurrentModificationException}s is avoided, and -325 * analyzers may safely add or remove entries from the dependencies list. -326 * -327 * Every effort is made to complete analysis on the dependencies. In some -328 * cases an exception will occur with part of the analysis being performed -329 * which may not affect the entire analysis. If an exception occurs it will -330 * be included in the thrown exception collection. -331 * -332 * @throws ExceptionCollection a collections of any exceptions that occurred -333 * during analysis -334 */ -335 public void analyzeDependencies() throws ExceptionCollection { -336 final List<Throwable> exceptions = new ArrayList<Throwable>(); -337 boolean autoUpdate = true; -338 try { -339 autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); -340 } catch (InvalidSettingException ex) { -341 LOGGER.debug("Invalid setting for auto-update; using true."); -342 exceptions.add(ex); -343 } -344 if (autoUpdate) { -345 try { -346 doUpdates(); -347 } catch (UpdateException ex) { -348 exceptions.add(ex); -349 LOGGER.warn("Unable to update Cached Web DataSource, using local " -350 + "data instead. Results may not include recent vulnerabilities."); -351 LOGGER.debug("Update Error", ex); -352 } -353 } -354 -355 //need to ensure that data exists -356 try { -357 ensureDataExists(); -358 } catch (NoDataException ex) { -359 LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage()); -360 LOGGER.debug("", ex); -361 exceptions.add(ex); -362 throw new ExceptionCollection("Unable to continue dependency-check analysis.", exceptions, true); -363 } catch (DatabaseException ex) { -364 LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage()); -365 LOGGER.debug("", ex); -366 exceptions.add(ex); -367 throw new ExceptionCollection("Unable to connect to the dependency-check database", exceptions, true); -368 } -369 -370 LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------"); -371 LOGGER.info("Analysis Started"); -372 final long analysisStart = System.currentTimeMillis(); +181 * @param dependencies the dependencies +182 */ +183 public void setDependencies(List<Dependency> dependencies) { +184 synchronized (this.dependencies) { +185 this.dependencies.clear(); +186 this.dependencies.addAll(dependencies); +187 } +188 } +189 +190 /** +191 * Scans an array of files or directories. If a directory is specified, it +192 * will be scanned recursively. Any dependencies identified are added to the +193 * dependency collection. +194 * +195 * @param paths an array of paths to files or directories to be analyzed +196 * @return the list of dependencies scanned +197 * @since v0.3.2.5 +198 */ +199 public List<Dependency> scan(String[] paths) { +200 return scan(paths, null); +201 } +202 +203 /** +204 * Scans an array of files or directories. If a directory is specified, it +205 * will be scanned recursively. Any dependencies identified are added to the +206 * dependency collection. +207 * +208 * @param paths an array of paths to files or directories to be analyzed +209 * @param projectReference the name of the project or scope in which the +210 * dependency was identified +211 * @return the list of dependencies scanned +212 * @since v1.4.4 +213 */ +214 public List<Dependency> scan(String[] paths, String projectReference) { +215 final List<Dependency> deps = new ArrayList<Dependency>(); +216 for (String path : paths) { +217 final List<Dependency> d = scan(path, projectReference); +218 if (d != null) { +219 deps.addAll(d); +220 } +221 } +222 return deps; +223 } +224 +225 /** +226 * Scans a given file or directory. If a directory is specified, it will be +227 * scanned recursively. Any dependencies identified are added to the +228 * dependency collection. +229 * +230 * @param path the path to a file or directory to be analyzed +231 * @return the list of dependencies scanned +232 */ +233 public List<Dependency> scan(String path) { +234 return scan(path, null); +235 } +236 +237 /** +238 * Scans a given file or directory. If a directory is specified, it will be +239 * scanned recursively. Any dependencies identified are added to the +240 * dependency collection. +241 * +242 * @param path the path to a file or directory to be analyzed +243 * @param projectReference the name of the project or scope in which the +244 * dependency was identified +245 * @return the list of dependencies scanned +246 * @since v1.4.4 +247 */ +248 public List<Dependency> scan(String path, String projectReference) { +249 final File file = new File(path); +250 return scan(file, projectReference); +251 } +252 +253 /** +254 * Scans an array of files or directories. If a directory is specified, it +255 * will be scanned recursively. Any dependencies identified are added to the +256 * dependency collection. +257 * +258 * @param files an array of paths to files or directories to be analyzed. +259 * @return the list of dependencies +260 * @since v0.3.2.5 +261 */ +262 public List<Dependency> scan(File[] files) { +263 return scan(files, null); +264 } +265 +266 /** +267 * Scans an array of files or directories. If a directory is specified, it +268 * will be scanned recursively. Any dependencies identified are added to the +269 * dependency collection. +270 * +271 * @param files an array of paths to files or directories to be analyzed. +272 * @param projectReference the name of the project or scope in which the +273 * dependency was identified +274 * @return the list of dependencies +275 * @since v1.4.4 +276 */ +277 public List<Dependency> scan(File[] files, String projectReference) { +278 final List<Dependency> deps = new ArrayList<Dependency>(); +279 for (File file : files) { +280 final List<Dependency> d = scan(file, projectReference); +281 if (d != null) { +282 deps.addAll(d); +283 } +284 } +285 return deps; +286 } +287 +288 /** +289 * Scans a collection of files or directories. If a directory is specified, +290 * it will be scanned recursively. Any dependencies identified are added to +291 * the dependency collection. +292 * +293 * @param files a set of paths to files or directories to be analyzed +294 * @return the list of dependencies scanned +295 * @since v0.3.2.5 +296 */ +297 public List<Dependency> scan(Collection<File> files) { +298 return scan(files, null); +299 } +300 +301 /** +302 * Scans a collection of files or directories. If a directory is specified, +303 * it will be scanned recursively. Any dependencies identified are added to +304 * the dependency collection. +305 * +306 * @param files a set of paths to files or directories to be analyzed +307 * @param projectReference the name of the project or scope in which the +308 * dependency was identified +309 * @return the list of dependencies scanned +310 * @since v1.4.4 +311 */ +312 public List<Dependency> scan(Collection<File> files, String projectReference) { +313 final List<Dependency> deps = new ArrayList<Dependency>(); +314 for (File file : files) { +315 final List<Dependency> d = scan(file, projectReference); +316 if (d != null) { +317 deps.addAll(d); +318 } +319 } +320 return deps; +321 } +322 +323 /** +324 * Scans a given file or directory. If a directory is specified, it will be +325 * scanned recursively. Any dependencies identified are added to the +326 * dependency collection. +327 * +328 * @param file the path to a file or directory to be analyzed +329 * @return the list of dependencies scanned +330 * @since v0.3.2.4 +331 */ +332 public List<Dependency> scan(File file) { +333 return scan(file, null); +334 } +335 +336 /** +337 * Scans a given file or directory. If a directory is specified, it will be +338 * scanned recursively. Any dependencies identified are added to the +339 * dependency collection. +340 * +341 * @param file the path to a file or directory to be analyzed +342 * @param projectReference the name of the project or scope in which the +343 * dependency was identified +344 * @return the list of dependencies scanned +345 * @since v1.4.4 +346 */ +347 public List<Dependency> scan(File file, String projectReference) { +348 if (file.exists()) { +349 if (file.isDirectory()) { +350 return scanDirectory(file, projectReference); +351 } else { +352 final Dependency d = scanFile(file, projectReference); +353 if (d != null) { +354 final List<Dependency> deps = new ArrayList<Dependency>(); +355 deps.add(d); +356 return deps; +357 } +358 } +359 } +360 return null; +361 } +362 +363 /** +364 * Recursively scans files and directories. Any dependencies identified are +365 * added to the dependency collection. +366 * +367 * @param dir the directory to scan +368 * @return the list of Dependency objects scanned +369 */ +370 protected List<Dependency> scanDirectory(File dir) { +371 return scanDirectory(dir, null); +372 } 373 -374 // analysis phases -375 for (AnalysisPhase phase : AnalysisPhase.values()) { -376 final List<Analyzer> analyzerList = analyzers.get(phase); -377 -378 for (Analyzer a : analyzerList) { -379 try { -380 a = initializeAnalyzer(a); -381 } catch (InitializationException ex) { -382 exceptions.add(ex); -383 continue; -384 } -385 -386 /* need to create a copy of the collection because some of the -387 * analyzers may modify it. This prevents ConcurrentModificationExceptions. -388 * This is okay for adds/deletes because it happens per analyzer. -389 */ -390 LOGGER.debug("Begin Analyzer '{}'", a.getName()); -391 final Set<Dependency> dependencySet = new HashSet<Dependency>(dependencies); -392 for (Dependency d : dependencySet) { -393 boolean shouldAnalyze = true; -394 if (a instanceof FileTypeAnalyzer) { -395 final FileTypeAnalyzer fAnalyzer = (FileTypeAnalyzer) a; -396 shouldAnalyze = fAnalyzer.accept(d.getActualFile()); -397 } -398 if (shouldAnalyze) { -399 LOGGER.debug("Begin Analysis of '{}'", d.getActualFilePath()); -400 try { -401 a.analyze(d, this); -402 } catch (AnalysisException ex) { -403 LOGGER.warn("An error occurred while analyzing '{}'.", d.getActualFilePath()); -404 LOGGER.debug("", ex); -405 exceptions.add(ex); -406 } catch (Throwable ex) { -407 //final AnalysisException ax = new AnalysisException(axMsg, ex); -408 LOGGER.warn("An unexpected error occurred during analysis of '{}'", d.getActualFilePath()); -409 LOGGER.debug("", ex); -410 exceptions.add(ex); -411 } -412 } -413 } -414 } -415 } -416 for (AnalysisPhase phase : AnalysisPhase.values()) { -417 final List<Analyzer> analyzerList = analyzers.get(phase); -418 -419 for (Analyzer a : analyzerList) { -420 closeAnalyzer(a); -421 } -422 } -423 -424 LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------"); -425 LOGGER.info("Analysis Complete ({} ms)", System.currentTimeMillis() - analysisStart); -426 if (exceptions.size() > 0) { -427 throw new ExceptionCollection("One or more exceptions occured during dependency-check analysis", exceptions); -428 } -429 } -430 -431 /** -432 * Initializes the given analyzer. -433 * -434 * @param analyzer the analyzer to initialize -435 * @return the initialized analyzer -436 * @throws InitializationException thrown when there is a problem -437 * initializing the analyzer -438 */ -439 protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException { -440 try { -441 LOGGER.debug("Initializing {}", analyzer.getName()); -442 analyzer.initialize(); -443 } catch (InitializationException ex) { -444 LOGGER.error("Exception occurred initializing {}.", analyzer.getName()); -445 LOGGER.debug("", ex); -446 try { -447 analyzer.close(); -448 } catch (Throwable ex1) { -449 LOGGER.trace("", ex1); -450 } -451 throw ex; -452 } catch (Throwable ex) { -453 LOGGER.error("Unexpected exception occurred initializing {}.", analyzer.getName()); -454 LOGGER.debug("", ex); -455 try { -456 analyzer.close(); -457 } catch (Throwable ex1) { -458 LOGGER.trace("", ex1); -459 } -460 throw new InitializationException("Unexpected Exception", ex); -461 } -462 return analyzer; -463 } -464 -465 /** -466 * Closes the given analyzer. -467 * -468 * @param analyzer the analyzer to close -469 */ -470 protected void closeAnalyzer(Analyzer analyzer) { -471 LOGGER.debug("Closing Analyzer '{}'", analyzer.getName()); -472 try { -473 analyzer.close(); -474 } catch (Throwable ex) { -475 LOGGER.trace("", ex); -476 } -477 } -478 -479 /** -480 * Cycles through the cached web data sources and calls update on all of -481 * them. -482 * -483 * @throws UpdateException thrown if the operation fails -484 */ -485 public void doUpdates() throws UpdateException { -486 LOGGER.info("Checking for updates"); -487 final long updateStart = System.currentTimeMillis(); -488 final UpdateService service = new UpdateService(serviceClassLoader); -489 final Iterator<CachedWebDataSource> iterator = service.getDataSources(); -490 while (iterator.hasNext()) { -491 final CachedWebDataSource source = iterator.next(); -492 source.update(); -493 } -494 LOGGER.info("Check for updates complete ({} ms)", System.currentTimeMillis() - updateStart); -495 } -496 -497 /** -498 * Returns a full list of all of the analyzers. This is useful for reporting -499 * which analyzers where used. -500 * -501 * @return a list of Analyzers -502 */ -503 public List<Analyzer> getAnalyzers() { -504 final List<Analyzer> ret = new ArrayList<Analyzer>(); -505 for (AnalysisPhase phase : AnalysisPhase.values()) { -506 final List<Analyzer> analyzerList = analyzers.get(phase); -507 ret.addAll(analyzerList); -508 } -509 return ret; -510 } -511 -512 /** -513 * Checks all analyzers to see if an extension is supported. -514 * -515 * @param file a file extension -516 * @return true or false depending on whether or not the file extension is -517 * supported -518 */ -519 @Override -520 public boolean accept(File file) { -521 if (file == null) { -522 return false; -523 } -524 boolean scan = false; -525 for (FileTypeAnalyzer a : this.fileTypeAnalyzers) { -526 /* note, we can't break early on this loop as the analyzers need to know if -527 they have files to work on prior to initialization */ -528 scan |= a.accept(file); -529 } -530 return scan; -531 } -532 -533 /** -534 * Returns the set of file type analyzers. -535 * -536 * @return the set of file type analyzers -537 */ -538 public Set<FileTypeAnalyzer> getFileTypeAnalyzers() { -539 return this.fileTypeAnalyzers; -540 } -541 -542 /** -543 * Checks the CPE Index to ensure documents exists. If none exist a -544 * NoDataException is thrown. -545 * -546 * @throws NoDataException thrown if no data exists in the CPE Index -547 * @throws DatabaseException thrown if there is an exception opening the -548 * database -549 */ -550 private void ensureDataExists() throws NoDataException, DatabaseException { -551 final CveDB cve = new CveDB(); -552 try { -553 cve.open(); -554 if (!cve.dataExists()) { -555 throw new NoDataException("No documents exist"); -556 } -557 } catch (DatabaseException ex) { -558 throw new NoDataException(ex.getMessage(), ex); -559 } finally { -560 cve.close(); -561 } -562 } -563 } +374 /** +375 * Recursively scans files and directories. Any dependencies identified are +376 * added to the dependency collection. +377 * +378 * @param dir the directory to scan +379 * @param projectReference the name of the project or scope in which the +380 * dependency was identified +381 * @return the list of Dependency objects scanned +382 * @since v1.4.4 +383 */ +384 protected List<Dependency> scanDirectory(File dir, String projectReference) { +385 final File[] files = dir.listFiles(); +386 final List<Dependency> deps = new ArrayList<Dependency>(); +387 if (files != null) { +388 for (File f : files) { +389 if (f.isDirectory()) { +390 final List<Dependency> d = scanDirectory(f, projectReference); +391 if (d != null) { +392 deps.addAll(d); +393 } +394 } else { +395 final Dependency d = scanFile(f, projectReference); +396 deps.add(d); +397 } +398 } +399 } +400 return deps; +401 } +402 +403 /** +404 * Scans a specified file. If a dependency is identified it is added to the +405 * dependency collection. +406 * +407 * @param file The file to scan +408 * @return the scanned dependency +409 */ +410 protected Dependency scanFile(File file) { +411 return scanFile(file, null); +412 } +413 +414 /** +415 * Scans a specified file. If a dependency is identified it is added to the +416 * dependency collection. +417 * +418 * @param file The file to scan +419 * @param projectReference the name of the project or scope in which the +420 * dependency was identified +421 * @return the scanned dependency +422 * @since v1.4.4 +423 */ +424 protected Dependency scanFile(File file, String projectReference) { +425 Dependency dependency = null; +426 if (file.isFile()) { +427 if (accept(file)) { +428 dependency = new Dependency(file); +429 if (projectReference != null) { +430 dependency.addProjectReference(projectReference); +431 } +432 final String sha1 = dependency.getSha1sum(); +433 boolean found = false; +434 synchronized (dependencies) { +435 if (sha1 != null) { +436 for (Dependency existing : dependencies) { +437 if (sha1.equals(existing.getSha1sum())) { +438 found = true; +439 if (projectReference != null) { +440 existing.addProjectReference(projectReference); +441 } +442 if (existing.getActualFilePath() != null && dependency.getActualFilePath() != null +443 && !existing.getActualFilePath().equals(dependency.getActualFilePath())) { +444 existing.addRelatedDependency(dependency); +445 } else { +446 dependency = existing; +447 } +448 break; +449 } +450 } +451 } +452 if (!found) { +453 dependencies.add(dependency); +454 } +455 } +456 } else { +457 LOGGER.debug("Path passed to scanFile(File) is not a file: {}. Skipping the file.", file); +458 } +459 } +460 return dependency; +461 } +462 +463 /** +464 * Runs the analyzers against all of the dependencies. Since the mutable +465 * dependencies list is exposed via {@link #getDependencies()}, this method +466 * iterates over a copy of the dependencies list. Thus, the potential for +467 * {@link java.util.ConcurrentModificationException}s is avoided, and +468 * analyzers may safely add or remove entries from the dependencies list. +469 * <p> +470 * Every effort is made to complete analysis on the dependencies. In some +471 * cases an exception will occur with part of the analysis being performed +472 * which may not affect the entire analysis. If an exception occurs it will +473 * be included in the thrown exception collection. +474 * +475 * @throws ExceptionCollection a collections of any exceptions that occurred +476 * during analysis +477 */ +478 public void analyzeDependencies() throws ExceptionCollection { +479 final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>()); +480 boolean autoUpdate = true; +481 try { +482 autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); +483 } catch (InvalidSettingException ex) { +484 LOGGER.debug("Invalid setting for auto-update; using true."); +485 exceptions.add(ex); +486 } +487 if (autoUpdate) { +488 try { +489 doUpdates(); +490 } catch (UpdateException ex) { +491 exceptions.add(ex); +492 LOGGER.warn("Unable to update Cached Web DataSource, using local " +493 + "data instead. Results may not include recent vulnerabilities."); +494 LOGGER.debug("Update Error", ex); +495 } +496 } +497 +498 //need to ensure that data exists +499 try { +500 ensureDataExists(); +501 } catch (NoDataException ex) { +502 throwFatalExceptionCollection("Unable to continue dependency-check analysis.", ex, exceptions); +503 } catch (DatabaseException ex) { +504 throwFatalExceptionCollection("Unable to connect to the dependency-check database.", ex, exceptions); +505 } +506 +507 LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------"); +508 LOGGER.info("Analysis Started"); +509 final long analysisStart = System.currentTimeMillis(); +510 +511 // analysis phases +512 for (AnalysisPhase phase : AnalysisPhase.values()) { +513 final List<Analyzer> analyzerList = analyzers.get(phase); +514 +515 for (final Analyzer analyzer : analyzerList) { +516 final long analyzerStart = System.currentTimeMillis(); +517 try { +518 initializeAnalyzer(analyzer); +519 } catch (InitializationException ex) { +520 exceptions.add(ex); +521 continue; +522 } +523 +524 executeAnalysisTasks(analyzer, exceptions); +525 +526 final long analyzerDurationMillis = System.currentTimeMillis() - analyzerStart; +527 final long analyzerDurationSeconds = TimeUnit.MILLISECONDS.toSeconds(analyzerDurationMillis); +528 LOGGER.info("Finished {} ({} seconds)", analyzer.getName(), analyzerDurationSeconds); +529 } +530 } +531 for (AnalysisPhase phase : AnalysisPhase.values()) { +532 final List<Analyzer> analyzerList = analyzers.get(phase); +533 +534 for (Analyzer a : analyzerList) { +535 closeAnalyzer(a); +536 } +537 } +538 +539 LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------"); +540 final long analysisDurationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - analysisStart); +541 LOGGER.info("Analysis Complete ({} seconds)", analysisDurationSeconds); +542 if (exceptions.size() > 0) { +543 throw new ExceptionCollection("One or more exceptions occurred during dependency-check analysis", exceptions); +544 } +545 } +546 +547 /** +548 * Executes executes the analyzer using multiple threads. +549 * +550 * @param exceptions a collection of exceptions that occurred during +551 * analysis +552 * @param analyzer the analyzer to execute +553 * @throws ExceptionCollection thrown if exceptions occurred during analysis +554 */ +555 void executeAnalysisTasks(Analyzer analyzer, List<Throwable> exceptions) throws ExceptionCollection { +556 LOGGER.debug("Starting {}", analyzer.getName()); +557 final List<AnalysisTask> analysisTasks = getAnalysisTasks(analyzer, exceptions); +558 final ExecutorService executorService = getExecutorService(analyzer); +559 +560 try { +561 final List<Future<Void>> results = executorService.invokeAll(analysisTasks, 10, TimeUnit.MINUTES); +562 +563 // ensure there was no exception during execution +564 for (Future<Void> result : results) { +565 try { +566 result.get(); +567 } catch (ExecutionException e) { +568 throwFatalExceptionCollection("Analysis task failed with a fatal exception.", e, exceptions); +569 } catch (CancellationException e) { +570 throwFatalExceptionCollection("Analysis task timed out.", e, exceptions); +571 } +572 } +573 } catch (InterruptedException e) { +574 throwFatalExceptionCollection("Analysis has been interrupted.", e, exceptions); +575 } finally { +576 executorService.shutdown(); +577 } +578 } +579 +580 /** +581 * Returns the analysis tasks for the dependencies. +582 * +583 * @param analyzer the analyzer to create tasks for +584 * @param exceptions the collection of exceptions to collect +585 * @return a collection of analysis tasks +586 */ +587 List<AnalysisTask> getAnalysisTasks(Analyzer analyzer, List<Throwable> exceptions) { +588 final List<AnalysisTask> result = new ArrayList<AnalysisTask>(); +589 synchronized (dependencies) { +590 for (final Dependency dependency : dependencies) { +591 final AnalysisTask task = new AnalysisTask(analyzer, dependency, this, exceptions); +592 result.add(task); +593 } +594 } +595 return result; +596 } +597 +598 /** +599 * Returns the executor service for a given analyzer. +600 * +601 * @param analyzer the analyzer to obtain an executor +602 * @return the executor service +603 */ +604 ExecutorService getExecutorService(Analyzer analyzer) { +605 if (analyzer.supportsParallelProcessing()) { +606 // just a fair trade-off that should be reasonable for all analyzer types +607 final int maximumNumberOfThreads = 4 * Runtime.getRuntime().availableProcessors(); +608 +609 LOGGER.debug("Parallel processing with up to {} threads: {}.", maximumNumberOfThreads, analyzer.getName()); +610 return Executors.newFixedThreadPool(maximumNumberOfThreads); +611 } else { +612 LOGGER.debug("Parallel processing is not supported: {}.", analyzer.getName()); +613 return Executors.newSingleThreadExecutor(); +614 } +615 } +616 +617 /** +618 * Initializes the given analyzer. +619 * +620 * @param analyzer the analyzer to initialize +621 * @return the initialized analyzer +622 * @throws InitializationException thrown when there is a problem +623 * initializing the analyzer +624 */ +625 protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException { +626 try { +627 LOGGER.debug("Initializing {}", analyzer.getName()); +628 analyzer.initialize(); +629 } catch (InitializationException ex) { +630 LOGGER.error("Exception occurred initializing {}.", analyzer.getName()); +631 LOGGER.debug("", ex); +632 try { +633 analyzer.close(); +634 } catch (Throwable ex1) { +635 LOGGER.trace("", ex1); +636 } +637 throw ex; +638 } catch (Throwable ex) { +639 LOGGER.error("Unexpected exception occurred initializing {}.", analyzer.getName()); +640 LOGGER.debug("", ex); +641 try { +642 analyzer.close(); +643 } catch (Throwable ex1) { +644 LOGGER.trace("", ex1); +645 } +646 throw new InitializationException("Unexpected Exception", ex); +647 } +648 return analyzer; +649 } +650 +651 /** +652 * Closes the given analyzer. +653 * +654 * @param analyzer the analyzer to close +655 */ +656 protected void closeAnalyzer(Analyzer analyzer) { +657 LOGGER.debug("Closing Analyzer '{}'", analyzer.getName()); +658 try { +659 analyzer.close(); +660 } catch (Throwable ex) { +661 LOGGER.trace("", ex); +662 } +663 } +664 +665 /** +666 * Cycles through the cached web data sources and calls update on all of +667 * them. +668 * +669 * @throws UpdateException thrown if the operation fails +670 */ +671 public void doUpdates() throws UpdateException { +672 LOGGER.info("Checking for updates"); +673 final long updateStart = System.currentTimeMillis(); +674 final UpdateService service = new UpdateService(serviceClassLoader); +675 final Iterator<CachedWebDataSource> iterator = service.getDataSources(); +676 while (iterator.hasNext()) { +677 final CachedWebDataSource source = iterator.next(); +678 source.update(); +679 } +680 LOGGER.info("Check for updates complete ({} ms)", System.currentTimeMillis() - updateStart); +681 } +682 +683 /** +684 * Returns a full list of all of the analyzers. This is useful for reporting +685 * which analyzers where used. +686 * +687 * @return a list of Analyzers +688 */ +689 public List<Analyzer> getAnalyzers() { +690 final List<Analyzer> ret = new ArrayList<Analyzer>(); +691 for (AnalysisPhase phase : AnalysisPhase.values()) { +692 final List<Analyzer> analyzerList = analyzers.get(phase); +693 ret.addAll(analyzerList); +694 } +695 return ret; +696 } +697 +698 /** +699 * Checks all analyzers to see if an extension is supported. +700 * +701 * @param file a file extension +702 * @return true or false depending on whether or not the file extension is +703 * supported +704 */ +705 @Override +706 public boolean accept(File file) { +707 if (file == null) { +708 return false; +709 } +710 boolean scan = false; +711 for (FileTypeAnalyzer a : this.fileTypeAnalyzers) { +712 /* note, we can't break early on this loop as the analyzers need to know if +713 they have files to work on prior to initialization */ +714 scan |= a.accept(file); +715 } +716 return scan; +717 } +718 +719 /** +720 * Returns the set of file type analyzers. +721 * +722 * @return the set of file type analyzers +723 */ +724 public Set<FileTypeAnalyzer> getFileTypeAnalyzers() { +725 return this.fileTypeAnalyzers; +726 } +727 +728 /** +729 * Adds a file type analyzer. This has been added solely to assist in unit +730 * testing the Engine. +731 * +732 * @param fta the file type analyzer to add +733 */ +734 protected void addFileTypeAnalyzer(FileTypeAnalyzer fta) { +735 this.fileTypeAnalyzers.add(fta); +736 } +737 +738 /** +739 * Checks the CPE Index to ensure documents exists. If none exist a +740 * NoDataException is thrown. +741 * +742 * @throws NoDataException thrown if no data exists in the CPE Index +743 * @throws DatabaseException thrown if there is an exception opening the +744 * database +745 */ +746 private void ensureDataExists() throws NoDataException, DatabaseException { +747 final CveDB cve = new CveDB(); +748 try { +749 cve.open(); +750 if (!cve.dataExists()) { +751 throw new NoDataException("No documents exist"); +752 } +753 } catch (DatabaseException ex) { +754 throw new NoDataException(ex.getMessage(), ex); +755 } finally { +756 cve.close(); +757 } +758 } +759 +760 /** +761 * Constructs and throws a fatal exception collection. +762 * +763 * @param message the exception message +764 * @param throwable the cause +765 * @param exceptions a collection of exception to include +766 * @throws ExceptionCollection a collection of exceptions that occurred +767 * during analysis +768 */ +769 private void throwFatalExceptionCollection(String message, Throwable throwable, List<Throwable> exceptions) throws ExceptionCollection { +770 LOGGER.error("{}\n\n{}", throwable.getMessage(), message); +771 LOGGER.debug("", throwable); +772 exceptions.add(throwable); +773 throw new ExceptionCollection(message, exceptions, true); +774 } +775 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/agent/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/agent/package-frame.html index 9a2c6afe5..8f9dd0b63 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/agent/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/agent/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.agent + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.agent diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/agent/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/agent/package-summary.html index cf61e872d..eb120de0e 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/agent/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/agent/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.agent + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.agent diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html index a7a1237ad..aa8cbe6b5 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html @@ -54,7 +54,15 @@ 46 public void close() throws Exception { 47 //do nothing 48 } -49 } +49 +50 /** +51 * The default is to support parallel processing. +52 */ +53 @Override +54 public boolean supportsParallelProcessing() { +55 return true; +56 } +57 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html index 46135995f..2c1fc9a99 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html @@ -91,7 +91,7 @@ 83 /** 84 * A flag indicating whether or not the analyzer is enabled. 85 */ -86 private boolean enabled = true; +86 private volatile boolean enabled = true; 87 88 /** 89 * Get the value of enabled. diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html index dff6d6872..f30874653 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html @@ -163,42 +163,49 @@ 155 } 156 } 157 if (file != null) { -158 try { -159 rules.addAll(parser.parseSuppressionRules(file)); -160 LOGGER.debug("{} suppression rules were loaded.", rules.size()); -161 } catch (SuppressionParseException ex) { -162 LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath()); -163 LOGGER.warn(ex.getMessage()); -164 throw ex; -165 } -166 } -167 } catch (DownloadFailedException ex) { -168 throwSuppressionParseException("Unable to fetch the configured suppression file", ex); -169 } catch (MalformedURLException ex) { -170 throwSuppressionParseException("Configured suppression file has an invalid URL", ex); -171 } catch (IOException ex) { -172 throwSuppressionParseException("Unable to create temp file for suppressions", ex); -173 } finally { -174 if (deleteTempFile && file != null) { -175 FileUtils.delete(file); -176 } -177 } -178 } -179 -180 /** -181 * Utility method to throw parse exceptions. -182 * -183 * @param message the exception message -184 * @param exception the cause of the exception -185 * @throws SuppressionParseException throws the generated -186 * SuppressionParseException -187 */ -188 private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException { -189 LOGGER.warn(message); -190 LOGGER.debug("", exception); -191 throw new SuppressionParseException(message, exception); -192 } -193 } +158 if (!file.exists()) { +159 final String msg = String.format("Suppression file '%s' does not exists", file.getPath()); +160 LOGGER.warn(msg); +161 throw new SuppressionParseException(msg); +162 } +163 try { +164 rules.addAll(parser.parseSuppressionRules(file)); +165 LOGGER.debug("{} suppression rules were loaded.", rules.size()); +166 } catch (SuppressionParseException ex) { +167 LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath()); +168 LOGGER.warn(ex.getMessage()); +169 throw ex; +170 } +171 } +172 } catch (DownloadFailedException ex) { +173 throwSuppressionParseException("Unable to fetch the configured suppression file", ex); +174 } catch (MalformedURLException ex) { +175 throwSuppressionParseException("Configured suppression file has an invalid URL", ex); +176 } catch (SuppressionParseException ex) { +177 throw ex; +178 } catch (IOException ex) { +179 throwSuppressionParseException("Unable to create temp file for suppressions", ex); +180 } finally { +181 if (deleteTempFile && file != null) { +182 FileUtils.delete(file); +183 } +184 } +185 } +186 +187 /** +188 * Utility method to throw parse exceptions. +189 * +190 * @param message the exception message +191 * @param exception the cause of the exception +192 * @throws SuppressionParseException throws the generated +193 * SuppressionParseException +194 */ +195 private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException { +196 LOGGER.warn(message); +197 LOGGER.debug("", exception); +198 throw new SuppressionParseException(message, exception); +199 } +200 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/Analyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/Analyzer.html index b363ffba7..b894e05b0 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/Analyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/Analyzer.html @@ -83,7 +83,15 @@ 75 * @throws Exception is thrown if an exception occurs closing the analyzer. 76 */ 77 void close() throws Exception; -78 } +78 +79 /** +80 * Returns whether multiple instances of the same type of analyzer can run in parallel. +81 * Note that running analyzers of different types in parallel is not supported at all. +82 * +83 * @return {@code true} if the analyzer supports parallel processing, {@code false} else +84 */ +85 boolean supportsParallelProcessing(); +86 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html index 101341061..020d22f3d 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html @@ -33,570 +33,612 @@ 25 import java.io.FileNotFoundException; 26 import java.io.FileOutputStream; 27 import java.io.IOException; -28 import java.util.ArrayList; -29 import java.util.Collections; -30 import java.util.Enumeration; -31 import java.util.HashSet; -32 import java.util.List; -33 import java.util.Set; -34 -35 import org.apache.commons.compress.archivers.ArchiveEntry; -36 import org.apache.commons.compress.archivers.ArchiveInputStream; -37 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; -38 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -39 import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; -40 import org.apache.commons.compress.archivers.zip.ZipFile; -41 import org.apache.commons.compress.compressors.CompressorInputStream; -42 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; -43 import org.apache.commons.compress.compressors.bzip2.BZip2Utils; -44 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; -45 import org.apache.commons.compress.compressors.gzip.GzipUtils; -46 import org.apache.commons.compress.utils.IOUtils; -47 -48 import org.owasp.dependencycheck.Engine; -49 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -50 import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException; -51 import org.owasp.dependencycheck.dependency.Dependency; -52 import org.owasp.dependencycheck.exception.InitializationException; -53 import org.owasp.dependencycheck.utils.FileFilterBuilder; -54 import org.owasp.dependencycheck.utils.FileUtils; -55 import org.owasp.dependencycheck.utils.Settings; -56 -57 import org.slf4j.Logger; -58 import org.slf4j.LoggerFactory; -59 -60 /** -61 * <p> -62 * An analyzer that extracts files from archives and ensures any supported files -63 * contained within the archive are added to the dependency list.</p> -64 * -65 * @author Jeremy Long -66 */ -67 public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { -68 -69 /** -70 * The logger. -71 */ -72 private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveAnalyzer.class); -73 /** -74 * The count of directories created during analysis. This is used for -75 * creating temporary directories. -76 */ -77 private static int dirCount = 0; -78 /** -79 * The parent directory for the individual directories per archive. -80 */ -81 private File tempFileLocation = null; -82 /** -83 * The max scan depth that the analyzer will recursively extract nested -84 * archives. -85 */ -86 private static final int MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3); -87 /** -88 * Tracks the current scan/extraction depth for nested archives. -89 */ -90 private int scanDepth = 0; -91 -92 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> -93 /** -94 * The name of the analyzer. -95 */ -96 private static final String ANALYZER_NAME = "Archive Analyzer"; -97 /** -98 * The phase that this analyzer is intended to run in. -99 */ -100 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL; -101 /** -102 * The set of things we can handle with Zip methods -103 */ -104 private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg"); -105 /** -106 * The set of file extensions supported by this analyzer. Note for -107 * developers, any additions to this list will need to be explicitly handled -108 * in {@link #extractFiles(File, File, Engine)}. -109 */ -110 private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz", "bz2", "tbz2"); -111 -112 /** -113 * Detects files with extensions to remove from the engine's collection of -114 * dependencies. -115 */ -116 private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance().addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2") -117 .build(); -118 -119 static { -120 final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS); -121 if (additionalZipExt != null) { -122 final String[] ext = additionalZipExt.split("\\s*,\\s*"); -123 Collections.addAll(ZIPPABLES, ext); -124 } -125 EXTENSIONS.addAll(ZIPPABLES); -126 } -127 -128 /** -129 * The file filter used to filter supported files. -130 */ -131 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build(); -132 -133 @Override -134 protected FileFilter getFileFilter() { -135 return FILTER; -136 } -137 -138 /** -139 * Detects files with .zip extension. -140 */ -141 private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build(); -142 -143 /** -144 * Returns the name of the analyzer. -145 * -146 * @return the name of the analyzer. -147 */ -148 @Override -149 public String getName() { -150 return ANALYZER_NAME; -151 } -152 -153 /** -154 * Returns the phase that the analyzer is intended to run in. -155 * -156 * @return the phase that the analyzer is intended to run in. -157 */ -158 @Override -159 public AnalysisPhase getAnalysisPhase() { -160 return ANALYSIS_PHASE; -161 } -162 //</editor-fold> -163 -164 /** -165 * Returns the key used in the properties file to reference the analyzer's -166 * enabled property. -167 * -168 * @return the analyzer's enabled property setting key -169 */ -170 @Override -171 protected String getAnalyzerEnabledSettingKey() { -172 return Settings.KEYS.ANALYZER_ARCHIVE_ENABLED; -173 } -174 -175 /** -176 * The initialize method does nothing for this Analyzer. -177 * -178 * @throws InitializationException is thrown if there is an exception -179 * deleting or creating temporary files -180 */ -181 @Override -182 public void initializeFileTypeAnalyzer() throws InitializationException { -183 try { -184 final File baseDir = Settings.getTempDirectory(); -185 tempFileLocation = File.createTempFile("check", "tmp", baseDir); -186 if (!tempFileLocation.delete()) { -187 setEnabled(false); -188 final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath()); -189 throw new InitializationException(msg); -190 } -191 if (!tempFileLocation.mkdirs()) { -192 setEnabled(false); -193 final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath()); -194 throw new InitializationException(msg); -195 } -196 } catch (IOException ex) { -197 setEnabled(false); -198 throw new InitializationException("Unable to create a temporary file", ex); -199 } -200 } -201 -202 /** -203 * The close method deletes any temporary files and directories created -204 * during analysis. -205 * -206 * @throws Exception thrown if there is an exception deleting temporary -207 * files -208 */ -209 @Override -210 public void close() throws Exception { -211 if (tempFileLocation != null && tempFileLocation.exists()) { -212 LOGGER.debug("Attempting to delete temporary files"); -213 final boolean success = FileUtils.delete(tempFileLocation); -214 if (!success && tempFileLocation.exists()) { -215 final String[] l = tempFileLocation.list(); -216 if (l != null && l.length > 0) { -217 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); -218 } -219 } -220 } -221 } -222 -223 /** -224 * Analyzes a given dependency. If the dependency is an archive, such as a -225 * WAR or EAR, the contents are extracted, scanned, and added to the list of -226 * dependencies within the engine. -227 * -228 * @param dependency the dependency to analyze -229 * @param engine the engine scanning -230 * @throws AnalysisException thrown if there is an analysis exception -231 */ -232 @Override -233 public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { -234 final File f = new File(dependency.getActualFilePath()); -235 final File tmpDir = getNextTempDirectory(); -236 extractFiles(f, tmpDir, engine); -237 -238 //make a copy -239 final Set<Dependency> dependencySet = findMoreDependencies(engine, tmpDir); -240 if (!dependencySet.isEmpty()) { -241 for (Dependency d : dependencySet) { -242 //fix the dependency's display name and path -243 final String displayPath = String.format("%s%s", -244 dependency.getFilePath(), -245 d.getActualFilePath().substring(tmpDir.getAbsolutePath().length())); -246 final String displayName = String.format("%s: %s", -247 dependency.getFileName(), -248 d.getFileName()); -249 d.setFilePath(displayPath); -250 d.setFileName(displayName); -251 -252 //TODO - can we get more evidence from the parent? EAR contains module name, etc. -253 //analyze the dependency (i.e. extract files) if it is a supported type. -254 if (this.accept(d.getActualFile()) && scanDepth < MAX_SCAN_DEPTH) { -255 scanDepth += 1; -256 analyze(d, engine); -257 scanDepth -= 1; -258 } -259 } -260 } -261 if (REMOVE_FROM_ANALYSIS.accept(dependency.getActualFile())) { -262 addDisguisedJarsToDependencies(dependency, engine); -263 engine.getDependencies().remove(dependency); -264 } -265 Collections.sort(engine.getDependencies()); -266 } -267 -268 /** -269 * If a zip file was identified as a possible JAR, this method will add the -270 * zip to the list of dependencies. -271 * -272 * @param dependency the zip file -273 * @param engine the engine -274 * @throws AnalysisException thrown if there is an issue -275 */ -276 private void addDisguisedJarsToDependencies(Dependency dependency, Engine engine) throws AnalysisException { -277 if (ZIP_FILTER.accept(dependency.getActualFile()) && isZipFileActuallyJarFile(dependency)) { -278 final File tdir = getNextTempDirectory(); -279 final String fileName = dependency.getFileName(); -280 -281 LOGGER.info("The zip file '{}' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName); -282 -283 final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar"); -284 try { -285 org.apache.commons.io.FileUtils.copyFile(tdir, tmpLoc); -286 final Set<Dependency> dependencySet = findMoreDependencies(engine, tmpLoc); -287 if (!dependencySet.isEmpty()) { -288 if (dependencySet.size() != 1) { -289 LOGGER.info("Deep copy of ZIP to JAR file resulted in more than one dependency?"); -290 } -291 for (Dependency d : dependencySet) { -292 //fix the dependency's display name and path -293 d.setFilePath(dependency.getFilePath()); -294 d.setDisplayFileName(dependency.getFileName()); -295 } -296 } -297 } catch (IOException ex) { -298 LOGGER.debug("Unable to perform deep copy on '{}'", dependency.getActualFile().getPath(), ex); -299 } -300 } -301 } -302 /** -303 * An empty dependency set. -304 */ -305 private static final Set<Dependency> EMPTY_DEPENDENCY_SET = Collections.emptySet(); -306 -307 /** -308 * Scan the given file/folder, and return any new dependencies found. -309 * -310 * @param engine used to scan -311 * @param file target of scanning -312 * @return any dependencies that weren't known to the engine before -313 */ -314 private static Set<Dependency> findMoreDependencies(Engine engine, File file) { -315 final List<Dependency> before = new ArrayList<Dependency>(engine.getDependencies()); -316 engine.scan(file); -317 final List<Dependency> after = engine.getDependencies(); -318 final boolean sizeChanged = before.size() != after.size(); -319 final Set<Dependency> newDependencies; -320 if (sizeChanged) { -321 //get the new dependencies -322 newDependencies = new HashSet<Dependency>(after); -323 newDependencies.removeAll(before); -324 } else { -325 newDependencies = EMPTY_DEPENDENCY_SET; -326 } -327 return newDependencies; -328 } -329 -330 /** -331 * Retrieves the next temporary directory to extract an archive too. -332 * -333 * @return a directory -334 * @throws AnalysisException thrown if unable to create temporary directory -335 */ -336 private File getNextTempDirectory() throws AnalysisException { -337 dirCount += 1; -338 final File directory = new File(tempFileLocation, String.valueOf(dirCount)); -339 //getting an exception for some directories not being able to be created; might be because the directory already exists? -340 if (directory.exists()) { -341 return getNextTempDirectory(); -342 } -343 if (!directory.mkdirs()) { -344 final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath()); -345 throw new AnalysisException(msg); -346 } -347 return directory; -348 } -349 -350 /** -351 * Extracts the contents of an archive into the specified directory. -352 * -353 * @param archive an archive file such as a WAR or EAR -354 * @param destination a directory to extract the contents to -355 * @param engine the scanning engine -356 * @throws AnalysisException thrown if the archive is not found -357 */ -358 private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException { -359 if (archive != null && destination != null) { -360 String archiveExt = FileUtils.getFileExtension(archive.getName()); -361 if (archiveExt == null) { -362 return; -363 } -364 archiveExt = archiveExt.toLowerCase(); -365 -366 FileInputStream fis; -367 try { -368 fis = new FileInputStream(archive); -369 } catch (FileNotFoundException ex) { -370 LOGGER.debug("", ex); -371 throw new AnalysisException("Archive file was not found.", ex); -372 } -373 try { -374 if (ZIPPABLES.contains(archiveExt)) { -375 final BufferedInputStream in = new BufferedInputStream(fis); -376 ensureReadableJar(archiveExt, in); -377 extractArchive(new ZipArchiveInputStream(in), destination, engine); -378 } else if ("tar".equals(archiveExt)) { -379 extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine); -380 } else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) { -381 final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName()); -382 final File f = new File(destination, uncompressedName); -383 if (engine.accept(f)) { -384 decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), f); -385 } -386 } else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) { -387 final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName()); -388 final File f = new File(destination, uncompressedName); -389 if (engine.accept(f)) { -390 decompressFile(new BZip2CompressorInputStream(new BufferedInputStream(fis)), f); -391 } -392 } -393 } catch (ArchiveExtractionException ex) { -394 LOGGER.warn("Exception extracting archive '{}'.", archive.getName()); -395 LOGGER.debug("", ex); -396 } catch (IOException ex) { -397 LOGGER.warn("Exception reading archive '{}'.", archive.getName()); -398 LOGGER.debug("", ex); -399 } finally { -400 close(fis); -401 } -402 } -403 } -404 -405 /** -406 * Checks if the file being scanned is a JAR that begins with '#!/bin' which -407 * indicates it is a fully executable jar. If a fully executable JAR is -408 * identified the input stream will be advanced to the start of the actual -409 * JAR file ( skipping the script). -410 * -411 * @see -412 * <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing -413 * Spring Boot Applications</a> -414 * @param archiveExt the file extension -415 * @param in the input stream -416 * @throws IOException thrown if there is an error reading the stream -417 */ -418 private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException { -419 if ("jar".equals(archiveExt) && in.markSupported()) { -420 in.mark(7); -421 final byte[] b = new byte[7]; -422 final int read = in.read(b); -423 if (read == 7 -424 && b[0] == '#' -425 && b[1] == '!' -426 && b[2] == '/' -427 && b[3] == 'b' -428 && b[4] == 'i' -429 && b[5] == 'n' -430 && b[6] == '/') { -431 boolean stillLooking = true; -432 int chr, nxtChr; -433 while (stillLooking && (chr = in.read()) != -1) { -434 if (chr == '\n' || chr == '\r') { -435 in.mark(4); -436 if ((chr = in.read()) != -1) { -437 if (chr == 'P' && (chr = in.read()) != -1) { -438 if (chr == 'K' && (chr = in.read()) != -1) { -439 if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) { -440 if (nxtChr == chr + 1) { -441 stillLooking = false; -442 in.reset(); -443 } -444 } -445 } -446 } -447 } -448 } -449 } -450 } else { -451 in.reset(); -452 } -453 } -454 } -455 -456 /** -457 * Extracts files from an archive. -458 * -459 * @param input the archive to extract files from -460 * @param destination the location to write the files too -461 * @param engine the dependency-check engine -462 * @throws ArchiveExtractionException thrown if there is an exception -463 * extracting files from the archive -464 */ -465 private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException { -466 ArchiveEntry entry; -467 try { -468 while ((entry = input.getNextEntry()) != null) { -469 final File file = new File(destination, entry.getName()); -470 if (entry.isDirectory()) { -471 if (!file.exists() && !file.mkdirs()) { -472 final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath()); -473 throw new AnalysisException(msg); -474 } -475 } else if (engine.accept(file)) { -476 extractAcceptedFile(input, file); -477 } -478 } -479 } catch (Throwable ex) { -480 throw new ArchiveExtractionException(ex); -481 } finally { -482 close(input); -483 } -484 } -485 -486 /** -487 * Extracts a file from an archive. -488 * -489 * @param input the archives input stream -490 * @param file the file to extract -491 * @throws AnalysisException thrown if there is an error -492 */ -493 private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException { -494 LOGGER.debug("Extracting '{}'", file.getPath()); -495 FileOutputStream fos = null; -496 try { -497 final File parent = file.getParentFile(); -498 if (!parent.isDirectory() && !parent.mkdirs()) { -499 final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath()); -500 throw new AnalysisException(msg); -501 } -502 fos = new FileOutputStream(file); -503 IOUtils.copy(input, fos); -504 } catch (FileNotFoundException ex) { -505 LOGGER.debug("", ex); -506 final String msg = String.format("Unable to find file '%s'.", file.getName()); -507 throw new AnalysisException(msg, ex); -508 } catch (IOException ex) { -509 LOGGER.debug("", ex); -510 final String msg = String.format("IO Exception while parsing file '%s'.", file.getName()); -511 throw new AnalysisException(msg, ex); -512 } finally { -513 close(fos); -514 } -515 } -516 -517 /** -518 * Decompresses a file. -519 * -520 * @param inputStream the compressed file -521 * @param outputFile the location to write the decompressed file -522 * @throws ArchiveExtractionException thrown if there is an exception -523 * decompressing the file -524 */ -525 private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException { -526 LOGGER.debug("Decompressing '{}'", outputFile.getPath()); -527 FileOutputStream out = null; -528 try { -529 out = new FileOutputStream(outputFile); -530 IOUtils.copy(inputStream, out); -531 } catch (FileNotFoundException ex) { -532 LOGGER.debug("", ex); -533 throw new ArchiveExtractionException(ex); -534 } catch (IOException ex) { -535 LOGGER.debug("", ex); -536 throw new ArchiveExtractionException(ex); -537 } finally { -538 close(out); -539 } -540 } -541 -542 /** -543 * Close the given {@link Closeable} instance, ignoring nulls, and logging -544 * any thrown {@link IOException}. -545 * -546 * @param closeable to be closed -547 */ -548 private static void close(Closeable closeable) { -549 if (null != closeable) { -550 try { -551 closeable.close(); -552 } catch (IOException ex) { -553 LOGGER.trace("", ex); -554 } -555 } -556 } -557 -558 /** -559 * Attempts to determine if a zip file is actually a JAR file. -560 * -561 * @param dependency the dependency to check -562 * @return true if the dependency appears to be a JAR file; otherwise false -563 */ -564 private boolean isZipFileActuallyJarFile(Dependency dependency) { -565 boolean isJar = false; -566 ZipFile zip = null; -567 try { -568 zip = new ZipFile(dependency.getActualFilePath()); -569 if (zip.getEntry("META-INF/MANIFEST.MF") != null -570 || zip.getEntry("META-INF/maven") != null) { -571 final Enumeration<ZipArchiveEntry> entries = zip.getEntries(); -572 while (entries.hasMoreElements()) { -573 final ZipArchiveEntry entry = entries.nextElement(); -574 if (!entry.isDirectory()) { -575 final String name = entry.getName().toLowerCase(); -576 if (name.endsWith(".class")) { -577 isJar = true; -578 break; -579 } -580 } -581 } -582 } -583 } catch (IOException ex) { -584 LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex); -585 } finally { -586 ZipFile.closeQuietly(zip); -587 } -588 -589 return isJar; -590 } -591 } +28 import java.util.Collections; +29 import java.util.Enumeration; +30 import java.util.List; +31 import java.util.Set; +32 +33 import org.apache.commons.compress.archivers.ArchiveEntry; +34 import org.apache.commons.compress.archivers.ArchiveInputStream; +35 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +36 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +37 import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +38 import org.apache.commons.compress.archivers.zip.ZipFile; +39 import org.apache.commons.compress.compressors.CompressorInputStream; +40 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; +41 import org.apache.commons.compress.compressors.bzip2.BZip2Utils; +42 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; +43 import org.apache.commons.compress.compressors.gzip.GzipUtils; +44 import org.apache.commons.compress.utils.IOUtils; +45 +46 import org.owasp.dependencycheck.Engine; +47 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +48 import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException; +49 import org.owasp.dependencycheck.dependency.Dependency; +50 import org.owasp.dependencycheck.exception.InitializationException; +51 import org.owasp.dependencycheck.utils.FileFilterBuilder; +52 import org.owasp.dependencycheck.utils.FileUtils; +53 import org.owasp.dependencycheck.utils.Settings; +54 +55 import org.slf4j.Logger; +56 import org.slf4j.LoggerFactory; +57 +58 /** +59 * <p> +60 * An analyzer that extracts files from archives and ensures any supported files +61 * contained within the archive are added to the dependency list.</p> +62 * +63 * @author Jeremy Long +64 */ +65 public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { +66 +67 /** +68 * The logger. +69 */ +70 private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveAnalyzer.class); +71 /** +72 * The count of directories created during analysis. This is used for +73 * creating temporary directories. +74 */ +75 private static int dirCount = 0; +76 /** +77 * The parent directory for the individual directories per archive. +78 */ +79 private File tempFileLocation = null; +80 /** +81 * The max scan depth that the analyzer will recursively extract nested +82 * archives. +83 */ +84 private static final int MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3); +85 /** +86 * Tracks the current scan/extraction depth for nested archives. +87 */ +88 private int scanDepth = 0; +89 +90 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> +91 /** +92 * The name of the analyzer. +93 */ +94 private static final String ANALYZER_NAME = "Archive Analyzer"; +95 /** +96 * The phase that this analyzer is intended to run in. +97 */ +98 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL; +99 /** +100 * The set of things we can handle with Zip methods +101 */ +102 private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg"); +103 /** +104 * The set of file extensions supported by this analyzer. Note for +105 * developers, any additions to this list will need to be explicitly handled +106 * in {@link #extractFiles(File, File, Engine)}. +107 */ +108 private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz", "bz2", "tbz2"); +109 +110 /** +111 * Detects files with extensions to remove from the engine's collection of +112 * dependencies. +113 */ +114 private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance().addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2") +115 .build(); +116 +117 static { +118 final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS); +119 if (additionalZipExt != null) { +120 final String[] ext = additionalZipExt.split("\\s*,\\s*"); +121 Collections.addAll(ZIPPABLES, ext); +122 } +123 EXTENSIONS.addAll(ZIPPABLES); +124 } +125 +126 /** +127 * The file filter used to filter supported files. +128 */ +129 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build(); +130 +131 @Override +132 protected FileFilter getFileFilter() { +133 return FILTER; +134 } +135 +136 /** +137 * Detects files with .zip extension. +138 */ +139 private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build(); +140 +141 /** +142 * Returns the name of the analyzer. +143 * +144 * @return the name of the analyzer. +145 */ +146 @Override +147 public String getName() { +148 return ANALYZER_NAME; +149 } +150 +151 /** +152 * Returns the phase that the analyzer is intended to run in. +153 * +154 * @return the phase that the analyzer is intended to run in. +155 */ +156 @Override +157 public AnalysisPhase getAnalysisPhase() { +158 return ANALYSIS_PHASE; +159 } +160 //</editor-fold> +161 +162 /** +163 * Returns the key used in the properties file to reference the analyzer's +164 * enabled property. +165 * +166 * @return the analyzer's enabled property setting key +167 */ +168 @Override +169 protected String getAnalyzerEnabledSettingKey() { +170 return Settings.KEYS.ANALYZER_ARCHIVE_ENABLED; +171 } +172 +173 /** +174 * The initialize method does nothing for this Analyzer. +175 * +176 * @throws InitializationException is thrown if there is an exception +177 * deleting or creating temporary files +178 */ +179 @Override +180 public void initializeFileTypeAnalyzer() throws InitializationException { +181 try { +182 final File baseDir = Settings.getTempDirectory(); +183 tempFileLocation = File.createTempFile("check", "tmp", baseDir); +184 if (!tempFileLocation.delete()) { +185 setEnabled(false); +186 final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath()); +187 throw new InitializationException(msg); +188 } +189 if (!tempFileLocation.mkdirs()) { +190 setEnabled(false); +191 final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath()); +192 throw new InitializationException(msg); +193 } +194 } catch (IOException ex) { +195 setEnabled(false); +196 throw new InitializationException("Unable to create a temporary file", ex); +197 } +198 } +199 +200 /** +201 * The close method deletes any temporary files and directories created +202 * during analysis. +203 * +204 * @throws Exception thrown if there is an exception deleting temporary +205 * files +206 */ +207 @Override +208 public void close() throws Exception { +209 if (tempFileLocation != null && tempFileLocation.exists()) { +210 LOGGER.debug("Attempting to delete temporary files"); +211 final boolean success = FileUtils.delete(tempFileLocation); +212 if (!success && tempFileLocation.exists()) { +213 final String[] l = tempFileLocation.list(); +214 if (l != null && l.length > 0) { +215 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); +216 } +217 } +218 } +219 } +220 +221 /** +222 * Does not support parallel processing as it both modifies and iterates +223 * over the engine's list of dependencies. +224 * +225 * @see #analyzeFileType(Dependency, Engine) +226 * @see #findMoreDependencies(Engine, File) +227 */ +228 @Override +229 public boolean supportsParallelProcessing() { +230 return false; +231 } +232 +233 /** +234 * Analyzes a given dependency. If the dependency is an archive, such as a +235 * WAR or EAR, the contents are extracted, scanned, and added to the list of +236 * dependencies within the engine. +237 * +238 * @param dependency the dependency to analyze +239 * @param engine the engine scanning +240 * @throws AnalysisException thrown if there is an analysis exception +241 */ +242 @Override +243 public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { +244 final File f = new File(dependency.getActualFilePath()); +245 final File tmpDir = getNextTempDirectory(); +246 extractFiles(f, tmpDir, engine); +247 +248 //make a copy +249 final List<Dependency> dependencySet = findMoreDependencies(engine, tmpDir); +250 +251 if (!dependencySet.isEmpty()) { +252 for (Dependency d : dependencySet) { +253 if (d.getFilePath().startsWith(tmpDir.getAbsolutePath())) { +254 //fix the dependency's display name and path +255 final String displayPath = String.format("%s%s", +256 dependency.getFilePath(), +257 d.getActualFilePath().substring(tmpDir.getAbsolutePath().length())); +258 final String displayName = String.format("%s: %s", +259 dependency.getFileName(), +260 d.getFileName()); +261 d.setFilePath(displayPath); +262 d.setFileName(displayName); +263 d.setProjectReferences(dependency.getProjectReferences()); +264 +265 //TODO - can we get more evidence from the parent? EAR contains module name, etc. +266 //analyze the dependency (i.e. extract files) if it is a supported type. +267 if (this.accept(d.getActualFile()) && scanDepth < MAX_SCAN_DEPTH) { +268 scanDepth += 1; +269 analyze(d, engine); +270 scanDepth -= 1; +271 } +272 } else { +273 for (Dependency sub : dependencySet) { +274 if (sub.getFilePath().startsWith(tmpDir.getAbsolutePath())) { +275 final String displayPath = String.format("%s%s", +276 dependency.getFilePath(), +277 sub.getActualFilePath().substring(tmpDir.getAbsolutePath().length())); +278 final String displayName = String.format("%s: %s", +279 dependency.getFileName(), +280 sub.getFileName()); +281 sub.setFilePath(displayPath); +282 sub.setFileName(displayName); +283 } +284 } +285 } +286 } +287 } +288 if (REMOVE_FROM_ANALYSIS.accept(dependency.getActualFile())) { +289 addDisguisedJarsToDependencies(dependency, engine); +290 engine.getDependencies().remove(dependency); +291 } +292 Collections.sort(engine.getDependencies()); +293 } +294 +295 /** +296 * If a zip file was identified as a possible JAR, this method will add the +297 * zip to the list of dependencies. +298 * +299 * @param dependency the zip file +300 * @param engine the engine +301 * @throws AnalysisException thrown if there is an issue +302 */ +303 private void addDisguisedJarsToDependencies(Dependency dependency, Engine engine) throws AnalysisException { +304 if (ZIP_FILTER.accept(dependency.getActualFile()) && isZipFileActuallyJarFile(dependency)) { +305 final File tdir = getNextTempDirectory(); +306 final String fileName = dependency.getFileName(); +307 +308 LOGGER.info("The zip file '{}' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName); +309 final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar"); +310 //store the archives sha1 and change it so that the engine doesn't think the zip and jar file are the same +311 // and add it is a related dependency. +312 final String archiveSha1 = dependency.getSha1sum(); +313 try { +314 dependency.setSha1sum(""); +315 org.apache.commons.io.FileUtils.copyFile(dependency.getActualFile(), tmpLoc); +316 final List<Dependency> dependencySet = findMoreDependencies(engine, tmpLoc); +317 if (!dependencySet.isEmpty()) { +318 for (Dependency d : dependencySet) { +319 //fix the dependency's display name and path +320 if (d.getActualFile().equals(tmpLoc)) { +321 d.setFilePath(dependency.getFilePath()); +322 d.setDisplayFileName(dependency.getFileName()); +323 } else { +324 for (Dependency sub : d.getRelatedDependencies()) { +325 if (sub.getActualFile().equals(tmpLoc)) { +326 sub.setFilePath(dependency.getFilePath()); +327 sub.setDisplayFileName(dependency.getFileName()); +328 } +329 } +330 } +331 } +332 } +333 } catch (IOException ex) { +334 LOGGER.debug("Unable to perform deep copy on '{}'", dependency.getActualFile().getPath(), ex); +335 } finally { +336 dependency.setSha1sum(archiveSha1); +337 } +338 } +339 } +340 +341 /** +342 * Scan the given file/folder, and return any new dependencies found. +343 * +344 * @param engine used to scan +345 * @param file target of scanning +346 * @return any dependencies that weren't known to the engine before +347 */ +348 private static List<Dependency> findMoreDependencies(Engine engine, File file) { +349 final List<Dependency> added = engine.scan(file); +350 return added; +351 } +352 +353 /** +354 * Retrieves the next temporary directory to extract an archive too. +355 * +356 * @return a directory +357 * @throws AnalysisException thrown if unable to create temporary directory +358 */ +359 private File getNextTempDirectory() throws AnalysisException { +360 dirCount += 1; +361 final File directory = new File(tempFileLocation, String.valueOf(dirCount)); +362 //getting an exception for some directories not being able to be created; might be because the directory already exists? +363 if (directory.exists()) { +364 return getNextTempDirectory(); +365 } +366 if (!directory.mkdirs()) { +367 final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath()); +368 throw new AnalysisException(msg); +369 } +370 return directory; +371 } +372 +373 /** +374 * Extracts the contents of an archive into the specified directory. +375 * +376 * @param archive an archive file such as a WAR or EAR +377 * @param destination a directory to extract the contents to +378 * @param engine the scanning engine +379 * @throws AnalysisException thrown if the archive is not found +380 */ +381 private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException { +382 if (archive != null && destination != null) { +383 String archiveExt = FileUtils.getFileExtension(archive.getName()); +384 if (archiveExt == null) { +385 return; +386 } +387 archiveExt = archiveExt.toLowerCase(); +388 +389 final FileInputStream fis; +390 try { +391 fis = new FileInputStream(archive); +392 } catch (FileNotFoundException ex) { +393 LOGGER.debug("", ex); +394 throw new AnalysisException("Archive file was not found.", ex); +395 } +396 BufferedInputStream in = null; +397 ZipArchiveInputStream zin = null; +398 TarArchiveInputStream tin = null; +399 GzipCompressorInputStream gin = null; +400 BZip2CompressorInputStream bzin = null; +401 try { +402 if (ZIPPABLES.contains(archiveExt)) { +403 in = new BufferedInputStream(fis); +404 ensureReadableJar(archiveExt, in); +405 zin = new ZipArchiveInputStream(in); +406 extractArchive(zin, destination, engine); +407 } else if ("tar".equals(archiveExt)) { +408 in = new BufferedInputStream(fis); +409 tin = new TarArchiveInputStream(in); +410 extractArchive(tin, destination, engine); +411 } else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) { +412 final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName()); +413 final File f = new File(destination, uncompressedName); +414 if (engine.accept(f)) { +415 in = new BufferedInputStream(fis); +416 gin = new GzipCompressorInputStream(in); +417 decompressFile(gin, f); +418 } +419 } else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) { +420 final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName()); +421 final File f = new File(destination, uncompressedName); +422 if (engine.accept(f)) { +423 in = new BufferedInputStream(fis); +424 bzin = new BZip2CompressorInputStream(in); +425 decompressFile(bzin, f); +426 } +427 } +428 } catch (ArchiveExtractionException ex) { +429 LOGGER.warn("Exception extracting archive '{}'.", archive.getName()); +430 LOGGER.debug("", ex); +431 } catch (IOException ex) { +432 LOGGER.warn("Exception reading archive '{}'.", archive.getName()); +433 LOGGER.debug("", ex); +434 } finally { +435 //overly verbose and not needed... but keeping it anyway due to +436 //having issue with file handles being left open +437 close(fis); +438 close(in); +439 close(zin); +440 close(tin); +441 close(gin); +442 close(bzin); +443 } +444 } +445 } +446 +447 /** +448 * Checks if the file being scanned is a JAR that begins with '#!/bin' which +449 * indicates it is a fully executable jar. If a fully executable JAR is +450 * identified the input stream will be advanced to the start of the actual +451 * JAR file ( skipping the script). +452 * +453 * @see +454 * <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing +455 * Spring Boot Applications</a> +456 * @param archiveExt the file extension +457 * @param in the input stream +458 * @throws IOException thrown if there is an error reading the stream +459 */ +460 private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException { +461 if ("jar".equals(archiveExt) && in.markSupported()) { +462 in.mark(7); +463 final byte[] b = new byte[7]; +464 final int read = in.read(b); +465 if (read == 7 +466 && b[0] == '#' +467 && b[1] == '!' +468 && b[2] == '/' +469 && b[3] == 'b' +470 && b[4] == 'i' +471 && b[5] == 'n' +472 && b[6] == '/') { +473 boolean stillLooking = true; +474 int chr, nxtChr; +475 while (stillLooking && (chr = in.read()) != -1) { +476 if (chr == '\n' || chr == '\r') { +477 in.mark(4); +478 if ((chr = in.read()) != -1) { +479 if (chr == 'P' && (chr = in.read()) != -1) { +480 if (chr == 'K' && (chr = in.read()) != -1) { +481 if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) { +482 if (nxtChr == chr + 1) { +483 stillLooking = false; +484 in.reset(); +485 } +486 } +487 } +488 } +489 } +490 } +491 } +492 } else { +493 in.reset(); +494 } +495 } +496 } +497 +498 /** +499 * Extracts files from an archive. +500 * +501 * @param input the archive to extract files from +502 * @param destination the location to write the files too +503 * @param engine the dependency-check engine +504 * @throws ArchiveExtractionException thrown if there is an exception +505 * extracting files from the archive +506 */ +507 private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException { +508 ArchiveEntry entry; +509 try { +510 while ((entry = input.getNextEntry()) != null) { +511 final File file = new File(destination, entry.getName()); +512 if (entry.isDirectory()) { +513 if (!file.exists() && !file.mkdirs()) { +514 final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath()); +515 throw new AnalysisException(msg); +516 } +517 } else if (engine.accept(file)) { +518 extractAcceptedFile(input, file); +519 } +520 } +521 } catch (Throwable ex) { +522 throw new ArchiveExtractionException(ex); +523 } finally { +524 close(input); +525 } +526 } +527 +528 /** +529 * Extracts a file from an archive. +530 * +531 * @param input the archives input stream +532 * @param file the file to extract +533 * @throws AnalysisException thrown if there is an error +534 */ +535 private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException { +536 LOGGER.debug("Extracting '{}'", file.getPath()); +537 FileOutputStream fos = null; +538 try { +539 final File parent = file.getParentFile(); +540 if (!parent.isDirectory() && !parent.mkdirs()) { +541 final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath()); +542 throw new AnalysisException(msg); +543 } +544 fos = new FileOutputStream(file); +545 IOUtils.copy(input, fos); +546 } catch (FileNotFoundException ex) { +547 LOGGER.debug("", ex); +548 final String msg = String.format("Unable to find file '%s'.", file.getName()); +549 throw new AnalysisException(msg, ex); +550 } catch (IOException ex) { +551 LOGGER.debug("", ex); +552 final String msg = String.format("IO Exception while parsing file '%s'.", file.getName()); +553 throw new AnalysisException(msg, ex); +554 } finally { +555 close(fos); +556 } +557 } +558 +559 /** +560 * Decompresses a file. +561 * +562 * @param inputStream the compressed file +563 * @param outputFile the location to write the decompressed file +564 * @throws ArchiveExtractionException thrown if there is an exception +565 * decompressing the file +566 */ +567 private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException { +568 LOGGER.debug("Decompressing '{}'", outputFile.getPath()); +569 FileOutputStream out = null; +570 try { +571 out = new FileOutputStream(outputFile); +572 IOUtils.copy(inputStream, out); +573 } catch (FileNotFoundException ex) { +574 LOGGER.debug("", ex); +575 throw new ArchiveExtractionException(ex); +576 } catch (IOException ex) { +577 LOGGER.debug("", ex); +578 throw new ArchiveExtractionException(ex); +579 } finally { +580 close(out); +581 } +582 } +583 +584 /** +585 * Close the given {@link Closeable} instance, ignoring nulls, and logging +586 * any thrown {@link IOException}. +587 * +588 * @param closeable to be closed +589 */ +590 private static void close(Closeable closeable) { +591 if (null != closeable) { +592 try { +593 closeable.close(); +594 } catch (IOException ex) { +595 LOGGER.trace("", ex); +596 } +597 } +598 } +599 +600 /** +601 * Attempts to determine if a zip file is actually a JAR file. +602 * +603 * @param dependency the dependency to check +604 * @return true if the dependency appears to be a JAR file; otherwise false +605 */ +606 private boolean isZipFileActuallyJarFile(Dependency dependency) { +607 boolean isJar = false; +608 ZipFile zip = null; +609 try { +610 zip = new ZipFile(dependency.getActualFilePath()); +611 if (zip.getEntry("META-INF/MANIFEST.MF") != null +612 || zip.getEntry("META-INF/maven") != null) { +613 final Enumeration<ZipArchiveEntry> entries = zip.getEntries(); +614 while (entries.hasMoreElements()) { +615 final ZipArchiveEntry entry = entries.nextElement(); +616 if (!entry.isDirectory()) { +617 final String name = entry.getName().toLowerCase(); +618 if (name.endsWith(".class")) { +619 isJar = true; +620 break; +621 } +622 } +623 } +624 } +625 } catch (IOException ex) { +626 LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex); +627 } finally { +628 ZipFile.closeQuietly(zip); +629 } +630 +631 return isJar; +632 } +633 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html index 34acd7d46..1be2f72b4 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html @@ -81,302 +81,298 @@ 73 */ 74 private File grokAssemblyExe = null; 75 /** -76 * The DocumentBuilder for parsing the XML +76 * Logger 77 */ -78 private DocumentBuilder builder; -79 /** -80 * Logger -81 */ -82 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class); -83 -84 /** -85 * Builds the beginnings of a List for ProcessBuilder -86 * -87 * @return the list of arguments to begin populating the ProcessBuilder -88 */ -89 protected List<String> buildArgumentList() { -90 // Use file.separator as a wild guess as to whether this is Windows -91 final List<String> args = new ArrayList<String>(); -92 if (!SystemUtils.IS_OS_WINDOWS) { -93 if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) { -94 args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH)); -95 } else if (isInPath("mono")) { -96 args.add("mono"); -97 } else { -98 return null; -99 } -100 } -101 args.add(grokAssemblyExe.getPath()); -102 return args; -103 } -104 -105 /** -106 * Performs the analysis on a single Dependency. -107 * -108 * @param dependency the dependency to analyze -109 * @param engine the engine to perform the analysis under -110 * @throws AnalysisException if anything goes sideways -111 */ -112 @Override -113 public void analyzeFileType(Dependency dependency, Engine engine) -114 throws AnalysisException { -115 if (grokAssemblyExe == null) { -116 LOGGER.warn("GrokAssembly didn't get deployed"); -117 return; -118 } -119 -120 final List<String> args = buildArgumentList(); -121 if (args == null) { -122 LOGGER.warn("Assembly Analyzer was unable to execute"); -123 return; -124 } -125 args.add(dependency.getActualFilePath()); -126 final ProcessBuilder pb = new ProcessBuilder(args); -127 Document doc = null; -128 try { -129 final Process proc = pb.start(); -130 -131 doc = builder.parse(proc.getInputStream()); -132 -133 // Try evacuating the error stream -134 final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8"); -135 if (null != errorStream && !errorStream.isEmpty()) { -136 LOGGER.warn("Error from GrokAssembly: {}", errorStream); -137 } -138 -139 int rc = 0; -140 try { -141 rc = proc.waitFor(); -142 } catch (InterruptedException ie) { -143 return; -144 } -145 if (rc == 3) { -146 LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check", -147 dependency.getActualFilePath()); -148 return; -149 } else if (rc != 0) { -150 LOGGER.warn("Return code {} from GrokAssembly", rc); -151 } -152 -153 final XPath xpath = XPathFactory.newInstance().newXPath(); -154 -155 // First, see if there was an error -156 final String error = xpath.evaluate("/assembly/error", doc); -157 if (error != null && !error.isEmpty()) { -158 throw new AnalysisException(error); -159 } -160 -161 final String version = xpath.evaluate("/assembly/version", doc); -162 if (version != null) { -163 dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version", -164 version, Confidence.HIGHEST)); -165 } -166 -167 final String vendor = xpath.evaluate("/assembly/company", doc); -168 if (vendor != null) { -169 dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor", -170 vendor, Confidence.HIGH)); -171 } -172 -173 final String product = xpath.evaluate("/assembly/product", doc); -174 if (product != null) { -175 dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product", -176 product, Confidence.HIGH)); -177 } -178 -179 } catch (IOException ioe) { -180 throw new AnalysisException(ioe); -181 } catch (SAXException saxe) { -182 throw new AnalysisException("Couldn't parse GrokAssembly result", saxe); -183 } catch (XPathExpressionException xpe) { -184 // This shouldn't happen -185 throw new AnalysisException(xpe); -186 } -187 } -188 -189 /** -190 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a -191 * temporary location. -192 * -193 * @throws InitializationException thrown if anything goes wrong -194 */ -195 @Override -196 public void initializeFileTypeAnalyzer() throws InitializationException { -197 final File tempFile; -198 try { -199 tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory()); -200 } catch (IOException ex) { -201 setEnabled(false); -202 throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex); -203 } -204 FileOutputStream fos = null; -205 InputStream is = null; -206 try { -207 fos = new FileOutputStream(tempFile); -208 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe"); -209 IOUtils.copy(is, fos); -210 -211 grokAssemblyExe = tempFile; -212 LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath()); -213 } catch (IOException ioe) { -214 this.setEnabled(false); -215 LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage()); -216 throw new InitializationException("Could not extract GrokAssembly.exe", ioe); -217 } finally { -218 if (fos != null) { -219 try { -220 fos.close(); -221 } catch (Throwable e) { -222 LOGGER.debug("Error closing output stream"); -223 } -224 } -225 if (is != null) { -226 try { -227 is.close(); -228 } catch (Throwable e) { -229 LOGGER.debug("Error closing input stream"); -230 } -231 } -232 } -233 -234 // Now, need to see if GrokAssembly actually runs from this location. -235 final List<String> args = buildArgumentList(); -236 //TODO this creaes an "unreported" error - if someone doesn't look -237 // at the command output this could easily be missed (especially in an -238 // Ant or Mmaven build. -239 // -240 // We need to create a non-fatal warning error type that will -241 // get added to the report. -242 //TOOD this idea needs to get replicated to the bundle audit analyzer. -243 if (args == null) { -244 setEnabled(false); -245 LOGGER.error("----------------------------------------------------"); -246 LOGGER.error(".NET Assembly Analyzer could not be initialized and at least one " -247 + "'exe' or 'dll' was scanned. The 'mono' executale could not be found on " -248 + "the path; either disable the Assembly Analyzer or configure the path mono."); -249 LOGGER.error("----------------------------------------------------"); -250 return; -251 } -252 try { -253 final ProcessBuilder pb = new ProcessBuilder(args); -254 final Process p = pb.start(); -255 // Try evacuating the error stream -256 IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM); -257 -258 final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream()); -259 final XPath xpath = XPathFactory.newInstance().newXPath(); -260 final String error = xpath.evaluate("/assembly/error", doc); -261 if (p.waitFor() != 1 || error == null || error.isEmpty()) { -262 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details."); -263 LOGGER.debug("GrokAssembly.exe is not working properly"); -264 grokAssemblyExe = null; -265 setEnabled(false); -266 throw new InitializationException("Could not execute .NET AssemblyAnalyzer"); -267 } -268 } catch (InitializationException e) { -269 setEnabled(false); -270 throw e; -271 } catch (Throwable e) { -272 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n" -273 + "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details."); -274 LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage()); -275 setEnabled(false); -276 throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e); -277 } -278 try { -279 builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); -280 } catch (ParserConfigurationException ex) { -281 setEnabled(false); -282 throw new InitializationException("Error initializing the assembly analyzer", ex); -283 } -284 } -285 -286 /** -287 * Removes resources used from the local file system. -288 * -289 * @throws Exception thrown if there is a problem closing the analyzer -290 */ -291 @Override -292 public void close() throws Exception { -293 super.close(); -294 try { -295 if (grokAssemblyExe != null && !grokAssemblyExe.delete()) { -296 LOGGER.debug("Unable to delete temporary GrokAssembly.exe; attempting delete on exit"); -297 grokAssemblyExe.deleteOnExit(); -298 } -299 } catch (SecurityException se) { -300 LOGGER.debug("Can't delete temporary GrokAssembly.exe"); -301 grokAssemblyExe.deleteOnExit(); -302 } -303 } -304 -305 /** -306 * The File Filter used to filter supported extensions. -307 */ -308 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions( -309 SUPPORTED_EXTENSIONS).build(); -310 -311 @Override -312 protected FileFilter getFileFilter() { -313 return FILTER; -314 } -315 -316 /** -317 * Gets this analyzer's name. -318 * -319 * @return the analyzer name -320 */ -321 @Override -322 public String getName() { -323 return ANALYZER_NAME; -324 } -325 -326 /** -327 * Returns the phase this analyzer runs under. -328 * -329 * @return the phase this runs under -330 */ -331 @Override -332 public AnalysisPhase getAnalysisPhase() { -333 return ANALYSIS_PHASE; -334 } -335 -336 /** -337 * Returns the key used in the properties file to reference the analyzer's -338 * enabled property. -339 * -340 * @return the analyzer's enabled property setting key -341 */ -342 @Override -343 protected String getAnalyzerEnabledSettingKey() { -344 return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED; -345 } -346 -347 /** -348 * Tests to see if a file is in the system path. <b>Note</b> - the current -349 * implementation only works on non-windows platforms. For purposes of the -350 * AssemblyAnalyzer this is okay as this is only needed on Mac/*nix. -351 * -352 * @param file the executable to look for -353 * @return <code>true</code> if the file exists; otherwise -354 * <code>false</code> -355 */ -356 private boolean isInPath(String file) { -357 final ProcessBuilder pb = new ProcessBuilder("which", file); -358 try { -359 final Process proc = pb.start(); -360 final int retCode = proc.waitFor(); -361 if (retCode == 0) { -362 return true; -363 } -364 } catch (IOException ex) { -365 LOGGER.debug("Path seach failed for " + file); -366 } catch (InterruptedException ex) { -367 LOGGER.debug("Path seach failed for " + file); -368 } -369 return false; -370 } -371 } +78 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class); +79 +80 /** +81 * Builds the beginnings of a List for ProcessBuilder +82 * +83 * @return the list of arguments to begin populating the ProcessBuilder +84 */ +85 protected List<String> buildArgumentList() { +86 // Use file.separator as a wild guess as to whether this is Windows +87 final List<String> args = new ArrayList<String>(); +88 if (!SystemUtils.IS_OS_WINDOWS) { +89 if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) { +90 args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH)); +91 } else if (isInPath("mono")) { +92 args.add("mono"); +93 } else { +94 return null; +95 } +96 } +97 args.add(grokAssemblyExe.getPath()); +98 return args; +99 } +100 +101 /** +102 * Performs the analysis on a single Dependency. +103 * +104 * @param dependency the dependency to analyze +105 * @param engine the engine to perform the analysis under +106 * @throws AnalysisException if anything goes sideways +107 */ +108 @Override +109 public void analyzeFileType(Dependency dependency, Engine engine) +110 throws AnalysisException { +111 if (grokAssemblyExe == null) { +112 LOGGER.warn("GrokAssembly didn't get deployed"); +113 return; +114 } +115 +116 final List<String> args = buildArgumentList(); +117 if (args == null) { +118 LOGGER.warn("Assembly Analyzer was unable to execute"); +119 return; +120 } +121 args.add(dependency.getActualFilePath()); +122 final ProcessBuilder pb = new ProcessBuilder(args); +123 Document doc = null; +124 try { +125 final Process proc = pb.start(); +126 +127 final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); +128 doc = builder.parse(proc.getInputStream()); +129 +130 // Try evacuating the error stream +131 final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8"); +132 if (null != errorStream && !errorStream.isEmpty()) { +133 LOGGER.warn("Error from GrokAssembly: {}", errorStream); +134 } +135 +136 int rc = 0; +137 try { +138 rc = proc.waitFor(); +139 } catch (InterruptedException ie) { +140 return; +141 } +142 if (rc == 3) { +143 LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check", +144 dependency.getActualFilePath()); +145 return; +146 } else if (rc != 0) { +147 LOGGER.warn("Return code {} from GrokAssembly", rc); +148 } +149 +150 final XPath xpath = XPathFactory.newInstance().newXPath(); +151 +152 // First, see if there was an error +153 final String error = xpath.evaluate("/assembly/error", doc); +154 if (error != null && !error.isEmpty()) { +155 throw new AnalysisException(error); +156 } +157 +158 final String version = xpath.evaluate("/assembly/version", doc); +159 if (version != null) { +160 dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version", +161 version, Confidence.HIGHEST)); +162 } +163 +164 final String vendor = xpath.evaluate("/assembly/company", doc); +165 if (vendor != null) { +166 dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor", +167 vendor, Confidence.HIGH)); +168 } +169 +170 final String product = xpath.evaluate("/assembly/product", doc); +171 if (product != null) { +172 dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product", +173 product, Confidence.HIGH)); +174 } +175 +176 } catch (ParserConfigurationException pce) { +177 throw new AnalysisException("Error initializing the assembly analyzer", pce); +178 } catch (IOException ioe) { +179 throw new AnalysisException(ioe); +180 } catch (SAXException saxe) { +181 throw new AnalysisException("Couldn't parse GrokAssembly result", saxe); +182 } catch (XPathExpressionException xpe) { +183 // This shouldn't happen +184 throw new AnalysisException(xpe); +185 } +186 } +187 +188 /** +189 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a +190 * temporary location. +191 * +192 * @throws InitializationException thrown if anything goes wrong +193 */ +194 @Override +195 public void initializeFileTypeAnalyzer() throws InitializationException { +196 final File tempFile; +197 try { +198 tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory()); +199 } catch (IOException ex) { +200 setEnabled(false); +201 throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex); +202 } +203 FileOutputStream fos = null; +204 InputStream is = null; +205 try { +206 fos = new FileOutputStream(tempFile); +207 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe"); +208 IOUtils.copy(is, fos); +209 +210 grokAssemblyExe = tempFile; +211 LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath()); +212 } catch (IOException ioe) { +213 this.setEnabled(false); +214 LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage()); +215 throw new InitializationException("Could not extract GrokAssembly.exe", ioe); +216 } finally { +217 if (fos != null) { +218 try { +219 fos.close(); +220 } catch (Throwable e) { +221 LOGGER.debug("Error closing output stream"); +222 } +223 } +224 if (is != null) { +225 try { +226 is.close(); +227 } catch (Throwable e) { +228 LOGGER.debug("Error closing input stream"); +229 } +230 } +231 } +232 +233 // Now, need to see if GrokAssembly actually runs from this location. +234 final List<String> args = buildArgumentList(); +235 //TODO this creates an "unreported" error - if someone doesn't look +236 // at the command output this could easily be missed (especially in an +237 // Ant or Maven build. +238 // +239 // We need to create a non-fatal warning error type that will +240 // get added to the report. +241 //TOOD this idea needs to get replicated to the bundle audit analyzer. +242 if (args == null) { +243 setEnabled(false); +244 LOGGER.error("----------------------------------------------------"); +245 LOGGER.error(".NET Assembly Analyzer could not be initialized and at least one " +246 + "'exe' or 'dll' was scanned. The 'mono' executable could not be found on " +247 + "the path; either disable the Assembly Analyzer or configure the path mono."); +248 LOGGER.error("----------------------------------------------------"); +249 return; +250 } +251 try { +252 final ProcessBuilder pb = new ProcessBuilder(args); +253 final Process p = pb.start(); +254 // Try evacuating the error stream +255 IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM); +256 +257 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +258 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +259 final DocumentBuilder builder = factory.newDocumentBuilder(); +260 final Document doc = builder.parse(p.getInputStream()); +261 final XPath xpath = XPathFactory.newInstance().newXPath(); +262 final String error = xpath.evaluate("/assembly/error", doc); +263 if (p.waitFor() != 1 || error == null || error.isEmpty()) { +264 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details."); +265 LOGGER.debug("GrokAssembly.exe is not working properly"); +266 grokAssemblyExe = null; +267 setEnabled(false); +268 throw new InitializationException("Could not execute .NET AssemblyAnalyzer"); +269 } +270 } catch (InitializationException e) { +271 setEnabled(false); +272 throw e; +273 } catch (Throwable e) { +274 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n" +275 + "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details."); +276 LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage()); +277 setEnabled(false); +278 throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e); +279 } +280 } +281 +282 /** +283 * Removes resources used from the local file system. +284 * +285 * @throws Exception thrown if there is a problem closing the analyzer +286 */ +287 @Override +288 public void close() throws Exception { +289 super.close(); +290 try { +291 if (grokAssemblyExe != null && !grokAssemblyExe.delete()) { +292 LOGGER.debug("Unable to delete temporary GrokAssembly.exe; attempting delete on exit"); +293 grokAssemblyExe.deleteOnExit(); +294 } +295 } catch (SecurityException se) { +296 LOGGER.debug("Can't delete temporary GrokAssembly.exe"); +297 grokAssemblyExe.deleteOnExit(); +298 } +299 } +300 +301 /** +302 * The File Filter used to filter supported extensions. +303 */ +304 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions( +305 SUPPORTED_EXTENSIONS).build(); +306 +307 @Override +308 protected FileFilter getFileFilter() { +309 return FILTER; +310 } +311 +312 /** +313 * Gets this analyzer's name. +314 * +315 * @return the analyzer name +316 */ +317 @Override +318 public String getName() { +319 return ANALYZER_NAME; +320 } +321 +322 /** +323 * Returns the phase this analyzer runs under. +324 * +325 * @return the phase this runs under +326 */ +327 @Override +328 public AnalysisPhase getAnalysisPhase() { +329 return ANALYSIS_PHASE; +330 } +331 +332 /** +333 * Returns the key used in the properties file to reference the analyzer's +334 * enabled property. +335 * +336 * @return the analyzer's enabled property setting key +337 */ +338 @Override +339 protected String getAnalyzerEnabledSettingKey() { +340 return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED; +341 } +342 +343 /** +344 * Tests to see if a file is in the system path. <b>Note</b> - the current +345 * implementation only works on non-windows platforms. For purposes of the +346 * AssemblyAnalyzer this is okay as this is only needed on Mac/*nix. +347 * +348 * @param file the executable to look for +349 * @return <code>true</code> if the file exists; otherwise +350 * <code>false</code> +351 */ +352 private boolean isInPath(String file) { +353 final ProcessBuilder pb = new ProcessBuilder("which", file); +354 try { +355 final Process proc = pb.start(); +356 final int retCode = proc.waitFor(); +357 if (retCode == 0) { +358 return true; +359 } +360 } catch (IOException ex) { +361 LOGGER.debug("Path seach failed for " + file); +362 } catch (InterruptedException ex) { +363 LOGGER.debug("Path seach failed for " + file); +364 } +365 return false; +366 } +367 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.html index 3ca94822e..91d72c650 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.html @@ -39,257 +39,251 @@ 31 import java.io.FileFilter; 32 import java.io.IOException; 33 import java.nio.charset.Charset; -34 import java.util.ArrayList; -35 import java.util.List; -36 import java.util.regex.Matcher; -37 import java.util.regex.Pattern; -38 import org.owasp.dependencycheck.exception.InitializationException; -39 -40 /** -41 * Used to analyze Autoconf input files named configure.ac or configure.in. -42 * Files simply named "configure" are also analyzed, assuming they are generated -43 * by Autoconf, and contain certain special package descriptor variables. -44 * -45 * @author Dale Visser -46 * @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project -47 * - Free Software Foundation (FSF)</a> -48 */ -49 @Experimental -50 public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer { -51 -52 /** -53 * Autoconf output filename. -54 */ -55 private static final String CONFIGURE = "configure"; -56 -57 /** -58 * Autoconf input filename. -59 */ -60 private static final String CONFIGURE_IN = "configure.in"; -61 -62 /** -63 * Autoconf input filename. -64 */ -65 private static final String CONFIGURE_AC = "configure.ac"; -66 -67 /** -68 * The name of the analyzer. -69 */ -70 private static final String ANALYZER_NAME = "Autoconf Analyzer"; -71 -72 /** -73 * The phase that this analyzer is intended to run in. -74 */ -75 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; -76 -77 /** -78 * The set of file extensions supported by this analyzer. -79 */ -80 private static final String[] EXTENSIONS = {"ac", "in"}; -81 -82 /** -83 * Matches AC_INIT variables in the output configure script. -84 */ -85 private static final Pattern PACKAGE_VAR = Pattern.compile( -86 "PACKAGE_(.+?)='(.*?)'", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); -87 -88 /** -89 * Matches AC_INIT statement in configure.ac file. -90 */ -91 private static final Pattern AC_INIT_PATTERN; -92 -93 static { -94 // each instance of param or sep_param has a capture group -95 final String param = "\\[{0,2}(.+?)\\]{0,2}"; -96 final String sepParam = "\\s*,\\s*" + param; -97 // Group 1: Package -98 // Group 2: Version -99 // Group 3: optional -100 // Group 4: Bug report address (if it exists) -101 // Group 5: optional -102 // Group 6: Tarname (if it exists) -103 // Group 7: optional -104 // Group 8: URL (if it exists) -105 AC_INIT_PATTERN = Pattern.compile(String.format( -106 "AC_INIT\\(%s%s(%s)?(%s)?(%s)?\\s*\\)", param, sepParam, -107 sepParam, sepParam, sepParam), Pattern.DOTALL -108 | Pattern.CASE_INSENSITIVE); -109 } -110 -111 /** -112 * The file filter used to determine which files this analyzer supports. -113 */ -114 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(CONFIGURE).addExtensions( -115 EXTENSIONS).build(); -116 -117 /** -118 * Returns the FileFilter -119 * -120 * @return the FileFilter -121 */ -122 @Override -123 protected FileFilter getFileFilter() { -124 return FILTER; -125 } -126 -127 /** -128 * Returns the name of the analyzer. -129 * -130 * @return the name of the analyzer. -131 */ -132 @Override -133 public String getName() { -134 return ANALYZER_NAME; -135 } -136 -137 /** -138 * Returns the phase that the analyzer is intended to run in. -139 * -140 * @return the phase that the analyzer is intended to run in. -141 */ -142 @Override -143 public AnalysisPhase getAnalysisPhase() { -144 return ANALYSIS_PHASE; -145 } -146 -147 /** -148 * Returns the key used in the properties file to reference the analyzer's -149 * enabled property. -150 * -151 * @return the analyzer's enabled property setting key -152 */ -153 @Override -154 protected String getAnalyzerEnabledSettingKey() { -155 return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED; -156 } -157 -158 @Override -159 protected void analyzeFileType(Dependency dependency, Engine engine) -160 throws AnalysisException { -161 final File actualFile = dependency.getActualFile(); -162 final String name = actualFile.getName(); -163 if (name.startsWith(CONFIGURE)) { -164 final File parent = actualFile.getParentFile(); -165 final String parentName = parent.getName(); -166 dependency.setDisplayFileName(parentName + "/" + name); -167 final boolean isOutputScript = CONFIGURE.equals(name); -168 if (isOutputScript || CONFIGURE_AC.equals(name) -169 || CONFIGURE_IN.equals(name)) { -170 final String contents = getFileContents(actualFile); -171 if (!contents.isEmpty()) { -172 if (isOutputScript) { -173 extractConfigureScriptEvidence(dependency, name, -174 contents); -175 } else { -176 gatherEvidence(dependency, name, contents); -177 } -178 } -179 } -180 } else { -181 // copy, alter and set in case some other thread is iterating over -182 final List<Dependency> dependencies = new ArrayList<Dependency>( -183 engine.getDependencies()); -184 dependencies.remove(dependency); -185 engine.setDependencies(dependencies); -186 } -187 } -188 -189 /** -190 * Extracts evidence from the configuration. -191 * -192 * @param dependency the dependency being analyzed -193 * @param name the name of the source of evidence -194 * @param contents the contents to analyze for evidence -195 */ -196 private void extractConfigureScriptEvidence(Dependency dependency, -197 final String name, final String contents) { -198 final Matcher matcher = PACKAGE_VAR.matcher(contents); -199 while (matcher.find()) { -200 final String variable = matcher.group(1); -201 final String value = matcher.group(2); -202 if (!value.isEmpty()) { -203 if (variable.endsWith("NAME")) { -204 dependency.getProductEvidence().addEvidence(name, variable, -205 value, Confidence.HIGHEST); -206 } else if ("VERSION".equals(variable)) { -207 dependency.getVersionEvidence().addEvidence(name, variable, -208 value, Confidence.HIGHEST); -209 } else if ("BUGREPORT".equals(variable)) { -210 dependency.getVendorEvidence().addEvidence(name, variable, -211 value, Confidence.HIGH); -212 } else if ("URL".equals(variable)) { -213 dependency.getVendorEvidence().addEvidence(name, variable, -214 value, Confidence.HIGH); -215 } -216 } -217 } -218 } -219 -220 /** -221 * Retrieves the contents of a given file. -222 * -223 * @param actualFile the file to read -224 * @return the contents of the file -225 * @throws AnalysisException thrown if there is an IO Exception -226 */ -227 private String getFileContents(final File actualFile) -228 throws AnalysisException { -229 try { -230 return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim(); -231 } catch (IOException e) { -232 throw new AnalysisException( -233 "Problem occurred while reading dependency file.", e); -234 } -235 } -236 -237 /** -238 * Gathers evidence from a given file -239 * -240 * @param dependency the dependency to add evidence to -241 * @param name the source of the evidence -242 * @param contents the evidence to analyze -243 */ -244 private void gatherEvidence(Dependency dependency, final String name, -245 String contents) { -246 final Matcher matcher = AC_INIT_PATTERN.matcher(contents); -247 if (matcher.find()) { -248 final EvidenceCollection productEvidence = dependency -249 .getProductEvidence(); -250 productEvidence.addEvidence(name, "Package", matcher.group(1), -251 Confidence.HIGHEST); -252 dependency.getVersionEvidence().addEvidence(name, -253 "Package Version", matcher.group(2), Confidence.HIGHEST); -254 final EvidenceCollection vendorEvidence = dependency -255 .getVendorEvidence(); -256 if (null != matcher.group(3)) { -257 vendorEvidence.addEvidence(name, "Bug report address", -258 matcher.group(4), Confidence.HIGH); -259 } -260 if (null != matcher.group(5)) { -261 productEvidence.addEvidence(name, "Tarname", matcher.group(6), -262 Confidence.HIGH); -263 } -264 if (null != matcher.group(7)) { -265 final String url = matcher.group(8); -266 if (UrlStringUtils.isUrl(url)) { -267 vendorEvidence.addEvidence(name, "URL", url, -268 Confidence.HIGH); -269 } -270 } -271 } -272 } -273 -274 /** -275 * Initializes the file type analyzer. -276 * -277 * @throws InitializationException thrown if there is an exception during -278 * initialization -279 */ -280 @Override -281 protected void initializeFileTypeAnalyzer() throws InitializationException { -282 // No initialization needed. -283 } -284 } +34 import java.util.regex.Matcher; +35 import java.util.regex.Pattern; +36 import org.owasp.dependencycheck.exception.InitializationException; +37 +38 /** +39 * Used to analyze Autoconf input files named configure.ac or configure.in. +40 * Files simply named "configure" are also analyzed, assuming they are generated +41 * by Autoconf, and contain certain special package descriptor variables. +42 * +43 * @author Dale Visser +44 * @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project +45 * - Free Software Foundation (FSF)</a> +46 */ +47 @Experimental +48 public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer { +49 +50 /** +51 * Autoconf output filename. +52 */ +53 private static final String CONFIGURE = "configure"; +54 +55 /** +56 * Autoconf input filename. +57 */ +58 private static final String CONFIGURE_IN = "configure.in"; +59 +60 /** +61 * Autoconf input filename. +62 */ +63 private static final String CONFIGURE_AC = "configure.ac"; +64 +65 /** +66 * The name of the analyzer. +67 */ +68 private static final String ANALYZER_NAME = "Autoconf Analyzer"; +69 +70 /** +71 * The phase that this analyzer is intended to run in. +72 */ +73 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; +74 +75 /** +76 * The set of file extensions supported by this analyzer. +77 */ +78 private static final String[] EXTENSIONS = {"ac", "in"}; +79 +80 /** +81 * Matches AC_INIT variables in the output configure script. +82 */ +83 private static final Pattern PACKAGE_VAR = Pattern.compile( +84 "PACKAGE_(.+?)='(.*?)'", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); +85 +86 /** +87 * Matches AC_INIT statement in configure.ac file. +88 */ +89 private static final Pattern AC_INIT_PATTERN; +90 +91 static { +92 // each instance of param or sep_param has a capture group +93 final String param = "\\[{0,2}(.+?)\\]{0,2}"; +94 final String sepParam = "\\s*,\\s*" + param; +95 // Group 1: Package +96 // Group 2: Version +97 // Group 3: optional +98 // Group 4: Bug report address (if it exists) +99 // Group 5: optional +100 // Group 6: Tarname (if it exists) +101 // Group 7: optional +102 // Group 8: URL (if it exists) +103 AC_INIT_PATTERN = Pattern.compile(String.format( +104 "AC_INIT\\(%s%s(%s)?(%s)?(%s)?\\s*\\)", param, sepParam, +105 sepParam, sepParam, sepParam), Pattern.DOTALL +106 | Pattern.CASE_INSENSITIVE); +107 } +108 +109 /** +110 * The file filter used to determine which files this analyzer supports. +111 */ +112 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(CONFIGURE).addExtensions( +113 EXTENSIONS).build(); +114 +115 /** +116 * Returns the FileFilter +117 * +118 * @return the FileFilter +119 */ +120 @Override +121 protected FileFilter getFileFilter() { +122 return FILTER; +123 } +124 +125 /** +126 * Returns the name of the analyzer. +127 * +128 * @return the name of the analyzer. +129 */ +130 @Override +131 public String getName() { +132 return ANALYZER_NAME; +133 } +134 +135 /** +136 * Returns the phase that the analyzer is intended to run in. +137 * +138 * @return the phase that the analyzer is intended to run in. +139 */ +140 @Override +141 public AnalysisPhase getAnalysisPhase() { +142 return ANALYSIS_PHASE; +143 } +144 +145 /** +146 * Returns the key used in the properties file to reference the analyzer's +147 * enabled property. +148 * +149 * @return the analyzer's enabled property setting key +150 */ +151 @Override +152 protected String getAnalyzerEnabledSettingKey() { +153 return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED; +154 } +155 +156 @Override +157 protected void analyzeFileType(Dependency dependency, Engine engine) +158 throws AnalysisException { +159 final File actualFile = dependency.getActualFile(); +160 final String name = actualFile.getName(); +161 if (name.startsWith(CONFIGURE)) { +162 final File parent = actualFile.getParentFile(); +163 final String parentName = parent.getName(); +164 dependency.setDisplayFileName(parentName + "/" + name); +165 final boolean isOutputScript = CONFIGURE.equals(name); +166 if (isOutputScript || CONFIGURE_AC.equals(name) +167 || CONFIGURE_IN.equals(name)) { +168 final String contents = getFileContents(actualFile); +169 if (!contents.isEmpty()) { +170 if (isOutputScript) { +171 extractConfigureScriptEvidence(dependency, name, +172 contents); +173 } else { +174 gatherEvidence(dependency, name, contents); +175 } +176 } +177 } +178 } else { +179 engine.getDependencies().remove(dependency); +180 } +181 } +182 +183 /** +184 * Extracts evidence from the configuration. +185 * +186 * @param dependency the dependency being analyzed +187 * @param name the name of the source of evidence +188 * @param contents the contents to analyze for evidence +189 */ +190 private void extractConfigureScriptEvidence(Dependency dependency, +191 final String name, final String contents) { +192 final Matcher matcher = PACKAGE_VAR.matcher(contents); +193 while (matcher.find()) { +194 final String variable = matcher.group(1); +195 final String value = matcher.group(2); +196 if (!value.isEmpty()) { +197 if (variable.endsWith("NAME")) { +198 dependency.getProductEvidence().addEvidence(name, variable, +199 value, Confidence.HIGHEST); +200 } else if ("VERSION".equals(variable)) { +201 dependency.getVersionEvidence().addEvidence(name, variable, +202 value, Confidence.HIGHEST); +203 } else if ("BUGREPORT".equals(variable)) { +204 dependency.getVendorEvidence().addEvidence(name, variable, +205 value, Confidence.HIGH); +206 } else if ("URL".equals(variable)) { +207 dependency.getVendorEvidence().addEvidence(name, variable, +208 value, Confidence.HIGH); +209 } +210 } +211 } +212 } +213 +214 /** +215 * Retrieves the contents of a given file. +216 * +217 * @param actualFile the file to read +218 * @return the contents of the file +219 * @throws AnalysisException thrown if there is an IO Exception +220 */ +221 private String getFileContents(final File actualFile) +222 throws AnalysisException { +223 try { +224 return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim(); +225 } catch (IOException e) { +226 throw new AnalysisException( +227 "Problem occurred while reading dependency file.", e); +228 } +229 } +230 +231 /** +232 * Gathers evidence from a given file +233 * +234 * @param dependency the dependency to add evidence to +235 * @param name the source of the evidence +236 * @param contents the evidence to analyze +237 */ +238 private void gatherEvidence(Dependency dependency, final String name, +239 String contents) { +240 final Matcher matcher = AC_INIT_PATTERN.matcher(contents); +241 if (matcher.find()) { +242 final EvidenceCollection productEvidence = dependency +243 .getProductEvidence(); +244 productEvidence.addEvidence(name, "Package", matcher.group(1), +245 Confidence.HIGHEST); +246 dependency.getVersionEvidence().addEvidence(name, +247 "Package Version", matcher.group(2), Confidence.HIGHEST); +248 final EvidenceCollection vendorEvidence = dependency +249 .getVendorEvidence(); +250 if (null != matcher.group(3)) { +251 vendorEvidence.addEvidence(name, "Bug report address", +252 matcher.group(4), Confidence.HIGH); +253 } +254 if (null != matcher.group(5)) { +255 productEvidence.addEvidence(name, "Tarname", matcher.group(6), +256 Confidence.HIGH); +257 } +258 if (null != matcher.group(7)) { +259 final String url = matcher.group(8); +260 if (UrlStringUtils.isUrl(url)) { +261 vendorEvidence.addEvidence(name, "URL", url, +262 Confidence.HIGH); +263 } +264 } +265 } +266 } +267 +268 /** +269 * Initializes the file type analyzer. +270 * +271 * @throws InitializationException thrown if there is an exception during +272 * initialization +273 */ +274 @Override +275 protected void initializeFileTypeAnalyzer() throws InitializationException { +276 // No initialization needed. +277 } +278 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html index d9f5e97dd..008432ef0 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html @@ -101,159 +101,166 @@ 93 .addFilenames("CMakeLists.txt").build(); 94 95 /** -96 * A reference to SHA1 message digest. -97 */ -98 private static MessageDigest sha1 = null; -99 -100 static { -101 try { -102 sha1 = MessageDigest.getInstance("SHA1"); -103 } catch (NoSuchAlgorithmException e) { -104 LOGGER.error(e.getMessage()); -105 } -106 } -107 -108 /** -109 * Returns the name of the CMake analyzer. -110 * -111 * @return the name of the analyzer -112 * -113 */ -114 @Override -115 public String getName() { -116 return "CMake Analyzer"; -117 } -118 -119 /** -120 * Tell that we are used for information collection. -121 * -122 * @return INFORMATION_COLLECTION -123 */ -124 @Override -125 public AnalysisPhase getAnalysisPhase() { -126 return AnalysisPhase.INFORMATION_COLLECTION; -127 } -128 -129 /** -130 * Returns the set of supported file extensions. -131 * -132 * @return the set of supported file extensions -133 */ -134 @Override -135 protected FileFilter getFileFilter() { -136 return FILTER; -137 } -138 -139 /** -140 * No-op initializer implementation. -141 * -142 * @throws InitializationException never thrown -143 */ -144 @Override -145 protected void initializeFileTypeAnalyzer() throws InitializationException { -146 // Nothing to do here. -147 } -148 -149 /** -150 * Analyzes python packages and adds evidence to the dependency. -151 * -152 * @param dependency the dependency being analyzed -153 * @param engine the engine being used to perform the scan -154 * @throws AnalysisException thrown if there is an unrecoverable error -155 * analyzing the dependency -156 */ -157 @Override -158 protected void analyzeFileType(Dependency dependency, Engine engine) -159 throws AnalysisException { -160 final File file = dependency.getActualFile(); -161 final String parentName = file.getParentFile().getName(); -162 final String name = file.getName(); -163 dependency.setDisplayFileName(String.format("%s%c%s", parentName, File.separatorChar, name)); -164 String contents; -165 try { -166 contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); -167 } catch (IOException e) { -168 throw new AnalysisException( -169 "Problem occurred while reading dependency file.", e); -170 } -171 -172 if (StringUtils.isNotBlank(contents)) { -173 final Matcher m = PROJECT.matcher(contents); -174 int count = 0; -175 while (m.find()) { -176 count++; -177 LOGGER.debug(String.format( -178 "Found project command match with %d groups: %s", -179 m.groupCount(), m.group(0))); -180 final String group = m.group(1); -181 LOGGER.debug("Group 1: " + group); -182 dependency.getProductEvidence().addEvidence(name, "Project", -183 group, Confidence.HIGH); -184 } -185 LOGGER.debug("Found {} matches.", count); -186 analyzeSetVersionCommand(dependency, engine, contents); -187 } -188 } -189 -190 /** -191 * Extracts the version information from the contents. If more then one -192 * version is found additional dependencies are added to the dependency -193 * list. -194 * -195 * @param dependency the dependency being analyzed -196 * @param engine the dependency-check engine -197 * @param contents the version information -198 */ -199 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( -200 value = "DM_DEFAULT_ENCODING", -201 justification = "Default encoding is only used if UTF-8 is not available") -202 private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) { -203 Dependency currentDep = dependency; -204 -205 final Matcher m = SET_VERSION.matcher(contents); -206 int count = 0; -207 while (m.find()) { -208 count++; -209 LOGGER.debug("Found project command match with {} groups: {}", -210 m.groupCount(), m.group(0)); -211 String product = m.group(1); -212 final String version = m.group(2); -213 LOGGER.debug("Group 1: " + product); -214 LOGGER.debug("Group 2: " + version); -215 final String aliasPrefix = "ALIASOF_"; -216 if (product.startsWith(aliasPrefix)) { -217 product = product.replaceFirst(aliasPrefix, ""); -218 } -219 if (count > 1) { -220 //TODO - refactor so we do not assign to the parameter (checkstyle) -221 currentDep = new Dependency(dependency.getActualFile()); -222 currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product)); -223 final String filePath = String.format("%s:%s", dependency.getFilePath(), product); -224 currentDep.setFilePath(filePath); -225 -226 byte[] path; -227 try { -228 path = filePath.getBytes("UTF-8"); -229 } catch (UnsupportedEncodingException ex) { -230 path = filePath.getBytes(); -231 } -232 currentDep.setSha1sum(Checksum.getHex(sha1.digest(path))); -233 engine.getDependencies().add(currentDep); -234 } -235 final String source = currentDep.getDisplayFileName(); -236 currentDep.getProductEvidence().addEvidence(source, "Product", -237 product, Confidence.MEDIUM); -238 currentDep.getVersionEvidence().addEvidence(source, "Version", -239 version, Confidence.MEDIUM); -240 } -241 LOGGER.debug(String.format("Found %d matches.", count)); -242 } -243 -244 @Override -245 protected String getAnalyzerEnabledSettingKey() { -246 return Settings.KEYS.ANALYZER_CMAKE_ENABLED; -247 } -248 } +96 * Returns the name of the CMake analyzer. +97 * +98 * @return the name of the analyzer +99 */ +100 @Override +101 public String getName() { +102 return "CMake Analyzer"; +103 } +104 +105 /** +106 * Tell that we are used for information collection. +107 * +108 * @return INFORMATION_COLLECTION +109 */ +110 @Override +111 public AnalysisPhase getAnalysisPhase() { +112 return AnalysisPhase.INFORMATION_COLLECTION; +113 } +114 +115 /** +116 * Returns the set of supported file extensions. +117 * +118 * @return the set of supported file extensions +119 */ +120 @Override +121 protected FileFilter getFileFilter() { +122 return FILTER; +123 } +124 +125 /** +126 * Initializes the analyzer. +127 * +128 * @throws InitializationException thrown if an exception occurs getting an +129 * instance of SHA1 +130 */ +131 @Override +132 protected void initializeFileTypeAnalyzer() throws InitializationException { +133 try { +134 getSha1MessageDigest(); +135 } catch (IllegalStateException ex) { +136 setEnabled(false); +137 throw new InitializationException("Unable to create SHA1 MessageDigest", ex); +138 } +139 } +140 +141 /** +142 * Analyzes python packages and adds evidence to the dependency. +143 * +144 * @param dependency the dependency being analyzed +145 * @param engine the engine being used to perform the scan +146 * @throws AnalysisException thrown if there is an unrecoverable error +147 * analyzing the dependency +148 */ +149 @Override +150 protected void analyzeFileType(Dependency dependency, Engine engine) +151 throws AnalysisException { +152 final File file = dependency.getActualFile(); +153 final String parentName = file.getParentFile().getName(); +154 final String name = file.getName(); +155 dependency.setDisplayFileName(String.format("%s%c%s", parentName, File.separatorChar, name)); +156 String contents; +157 try { +158 contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); +159 } catch (IOException e) { +160 throw new AnalysisException( +161 "Problem occurred while reading dependency file.", e); +162 } +163 +164 if (StringUtils.isNotBlank(contents)) { +165 final Matcher m = PROJECT.matcher(contents); +166 int count = 0; +167 while (m.find()) { +168 count++; +169 LOGGER.debug(String.format( +170 "Found project command match with %d groups: %s", +171 m.groupCount(), m.group(0))); +172 final String group = m.group(1); +173 LOGGER.debug("Group 1: " + group); +174 dependency.getProductEvidence().addEvidence(name, "Project", +175 group, Confidence.HIGH); +176 } +177 LOGGER.debug("Found {} matches.", count); +178 analyzeSetVersionCommand(dependency, engine, contents); +179 } +180 } +181 +182 /** +183 * Extracts the version information from the contents. If more then one +184 * version is found additional dependencies are added to the dependency +185 * list. +186 * +187 * @param dependency the dependency being analyzed +188 * @param engine the dependency-check engine +189 * @param contents the version information +190 */ +191 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( +192 value = "DM_DEFAULT_ENCODING", +193 justification = "Default encoding is only used if UTF-8 is not available") +194 private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) { +195 Dependency currentDep = dependency; +196 +197 final Matcher m = SET_VERSION.matcher(contents); +198 int count = 0; +199 while (m.find()) { +200 count++; +201 LOGGER.debug("Found project command match with {} groups: {}", +202 m.groupCount(), m.group(0)); +203 String product = m.group(1); +204 final String version = m.group(2); +205 LOGGER.debug("Group 1: " + product); +206 LOGGER.debug("Group 2: " + version); +207 final String aliasPrefix = "ALIASOF_"; +208 if (product.startsWith(aliasPrefix)) { +209 product = product.replaceFirst(aliasPrefix, ""); +210 } +211 if (count > 1) { +212 //TODO - refactor so we do not assign to the parameter (checkstyle) +213 currentDep = new Dependency(dependency.getActualFile()); +214 currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product)); +215 final String filePath = String.format("%s:%s", dependency.getFilePath(), product); +216 currentDep.setFilePath(filePath); +217 +218 byte[] path; +219 try { +220 path = filePath.getBytes("UTF-8"); +221 } catch (UnsupportedEncodingException ex) { +222 path = filePath.getBytes(); +223 } +224 final MessageDigest sha1 = getSha1MessageDigest(); +225 currentDep.setSha1sum(Checksum.getHex(sha1.digest(path))); +226 engine.getDependencies().add(currentDep); +227 } +228 final String source = currentDep.getDisplayFileName(); +229 currentDep.getProductEvidence().addEvidence(source, "Product", +230 product, Confidence.MEDIUM); +231 currentDep.getVersionEvidence().addEvidence(source, "Version", +232 version, Confidence.MEDIUM); +233 } +234 LOGGER.debug(String.format("Found %d matches.", count)); +235 } +236 +237 @Override +238 protected String getAnalyzerEnabledSettingKey() { +239 return Settings.KEYS.ANALYZER_CMAKE_ENABLED; +240 } +241 +242 /** +243 * Returns the sha1 message digest. +244 * +245 * @return the sha1 message digest +246 */ +247 private MessageDigest getSha1MessageDigest() { +248 try { +249 return MessageDigest.getInstance("SHA1"); +250 } catch (NoSuchAlgorithmException e) { +251 LOGGER.error(e.getMessage()); +252 throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e); +253 } +254 } +255 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html index 1cd289873..96a8dd3f8 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html @@ -33,801 +33,802 @@ 25 import java.util.List; 26 import java.util.Set; 27 import java.util.StringTokenizer; -28 import org.apache.commons.lang3.builder.CompareToBuilder; -29 import org.apache.lucene.document.Document; -30 import org.apache.lucene.index.CorruptIndexException; -31 import org.apache.lucene.queryparser.classic.ParseException; -32 import org.apache.lucene.search.ScoreDoc; -33 import org.apache.lucene.search.TopDocs; -34 import org.owasp.dependencycheck.Engine; -35 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -36 import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex; -37 import org.owasp.dependencycheck.data.cpe.Fields; -38 import org.owasp.dependencycheck.data.cpe.IndexEntry; -39 import org.owasp.dependencycheck.data.cpe.IndexException; -40 import org.owasp.dependencycheck.data.lucene.LuceneUtils; -41 import org.owasp.dependencycheck.data.nvdcve.CveDB; -42 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -43 import org.owasp.dependencycheck.dependency.Confidence; -44 import org.owasp.dependencycheck.dependency.Dependency; -45 import org.owasp.dependencycheck.dependency.Evidence; -46 import org.owasp.dependencycheck.dependency.EvidenceCollection; -47 import org.owasp.dependencycheck.dependency.Identifier; -48 import org.owasp.dependencycheck.dependency.VulnerableSoftware; -49 import org.owasp.dependencycheck.exception.InitializationException; -50 import org.owasp.dependencycheck.utils.DependencyVersion; -51 import org.owasp.dependencycheck.utils.DependencyVersionUtil; -52 import org.slf4j.Logger; -53 import org.slf4j.LoggerFactory; -54 -55 /** -56 * CPEAnalyzer is a utility class that takes a project dependency and attempts -57 * to discern if there is an associated CPE. It uses the evidence contained -58 * within the dependency to search the Lucene index. -59 * -60 * @author Jeremy Long -61 */ -62 public class CPEAnalyzer implements Analyzer { -63 -64 /** -65 * The Logger. -66 */ -67 private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class); -68 /** -69 * The maximum number of query results to return. -70 */ -71 static final int MAX_QUERY_RESULTS = 25; -72 /** -73 * The weighting boost to give terms when constructing the Lucene query. -74 */ -75 static final String WEIGHTING_BOOST = "^5"; -76 /** -77 * A string representation of a regular expression defining characters -78 * utilized within the CPE Names. -79 */ -80 static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]"; -81 /** -82 * A string representation of a regular expression used to remove all but -83 * alpha characters. -84 */ -85 static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*"; -86 /** -87 * The additional size to add to a new StringBuilder to account for extra -88 * data that will be written into the string. -89 */ -90 static final int STRING_BUILDER_BUFFER = 20; -91 /** -92 * The CPE in memory index. -93 */ -94 private CpeMemoryIndex cpe; -95 /** -96 * The CVE Database. -97 */ -98 private CveDB cve; -99 -100 /** -101 * The URL to perform a search of the NVD CVE data at NIST. -102 */ -103 public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s"; -104 -105 /** -106 * Returns the name of this analyzer. -107 * -108 * @return the name of this analyzer. -109 */ -110 @Override -111 public String getName() { -112 return "CPE Analyzer"; -113 } -114 -115 /** -116 * Returns the analysis phase that this analyzer should run in. -117 * -118 * @return the analysis phase that this analyzer should run in. -119 */ -120 @Override -121 public AnalysisPhase getAnalysisPhase() { -122 return AnalysisPhase.IDENTIFIER_ANALYSIS; -123 } -124 -125 /** -126 * Creates the CPE Lucene Index. -127 * -128 * @throws InitializationException is thrown if there is an issue opening -129 * the index. -130 */ -131 @Override -132 public void initialize() throws InitializationException { -133 try { -134 this.open(); -135 } catch (IOException ex) { -136 LOGGER.debug("Exception initializing the Lucene Index", ex); -137 throw new InitializationException("An exception occurred initializing the Lucene Index", ex); -138 } catch (DatabaseException ex) { -139 LOGGER.debug("Exception accessing the database", ex); -140 throw new InitializationException("An exception occurred accessing the database", ex); -141 } -142 } -143 -144 /** -145 * Opens the data source. -146 * -147 * @throws IOException when the Lucene directory to be queried does not -148 * exist or is corrupt. -149 * @throws DatabaseException when the database throws an exception. This -150 * usually occurs when the database is in use by another process. -151 */ -152 public void open() throws IOException, DatabaseException { -153 if (!isOpen()) { -154 cve = new CveDB(); -155 cve.open(); -156 cpe = CpeMemoryIndex.getInstance(); -157 try { -158 LOGGER.info("Creating the CPE Index"); +28 import java.util.concurrent.TimeUnit; +29 import org.apache.commons.lang3.builder.CompareToBuilder; +30 import org.apache.lucene.document.Document; +31 import org.apache.lucene.index.CorruptIndexException; +32 import org.apache.lucene.queryparser.classic.ParseException; +33 import org.apache.lucene.search.ScoreDoc; +34 import org.apache.lucene.search.TopDocs; +35 import org.owasp.dependencycheck.Engine; +36 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +37 import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex; +38 import org.owasp.dependencycheck.data.cpe.Fields; +39 import org.owasp.dependencycheck.data.cpe.IndexEntry; +40 import org.owasp.dependencycheck.data.cpe.IndexException; +41 import org.owasp.dependencycheck.data.lucene.LuceneUtils; +42 import org.owasp.dependencycheck.data.nvdcve.CveDB; +43 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +44 import org.owasp.dependencycheck.dependency.Confidence; +45 import org.owasp.dependencycheck.dependency.Dependency; +46 import org.owasp.dependencycheck.dependency.Evidence; +47 import org.owasp.dependencycheck.dependency.EvidenceCollection; +48 import org.owasp.dependencycheck.dependency.Identifier; +49 import org.owasp.dependencycheck.dependency.VulnerableSoftware; +50 import org.owasp.dependencycheck.exception.InitializationException; +51 import org.owasp.dependencycheck.utils.DependencyVersion; +52 import org.owasp.dependencycheck.utils.DependencyVersionUtil; +53 import org.slf4j.Logger; +54 import org.slf4j.LoggerFactory; +55 +56 /** +57 * CPEAnalyzer is a utility class that takes a project dependency and attempts +58 * to discern if there is an associated CPE. It uses the evidence contained +59 * within the dependency to search the Lucene index. +60 * +61 * @author Jeremy Long +62 */ +63 public class CPEAnalyzer extends AbstractAnalyzer { +64 +65 /** +66 * The Logger. +67 */ +68 private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class); +69 /** +70 * The maximum number of query results to return. +71 */ +72 static final int MAX_QUERY_RESULTS = 25; +73 /** +74 * The weighting boost to give terms when constructing the Lucene query. +75 */ +76 static final String WEIGHTING_BOOST = "^5"; +77 /** +78 * A string representation of a regular expression defining characters +79 * utilized within the CPE Names. +80 */ +81 static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]"; +82 /** +83 * A string representation of a regular expression used to remove all but +84 * alpha characters. +85 */ +86 static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*"; +87 /** +88 * The additional size to add to a new StringBuilder to account for extra +89 * data that will be written into the string. +90 */ +91 static final int STRING_BUILDER_BUFFER = 20; +92 /** +93 * The CPE in memory index. +94 */ +95 private CpeMemoryIndex cpe; +96 /** +97 * The CVE Database. +98 */ +99 private CveDB cve; +100 +101 /** +102 * The URL to perform a search of the NVD CVE data at NIST. +103 */ +104 public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s"; +105 +106 /** +107 * Returns the name of this analyzer. +108 * +109 * @return the name of this analyzer. +110 */ +111 @Override +112 public String getName() { +113 return "CPE Analyzer"; +114 } +115 +116 /** +117 * Returns the analysis phase that this analyzer should run in. +118 * +119 * @return the analysis phase that this analyzer should run in. +120 */ +121 @Override +122 public AnalysisPhase getAnalysisPhase() { +123 return AnalysisPhase.IDENTIFIER_ANALYSIS; +124 } +125 +126 /** +127 * Creates the CPE Lucene Index. +128 * +129 * @throws InitializationException is thrown if there is an issue opening +130 * the index. +131 */ +132 @Override +133 public void initialize() throws InitializationException { +134 try { +135 this.open(); +136 } catch (IOException ex) { +137 LOGGER.debug("Exception initializing the Lucene Index", ex); +138 throw new InitializationException("An exception occurred initializing the Lucene Index", ex); +139 } catch (DatabaseException ex) { +140 LOGGER.debug("Exception accessing the database", ex); +141 throw new InitializationException("An exception occurred accessing the database", ex); +142 } +143 } +144 +145 /** +146 * Opens the data source. +147 * +148 * @throws IOException when the Lucene directory to be queried does not +149 * exist or is corrupt. +150 * @throws DatabaseException when the database throws an exception. This +151 * usually occurs when the database is in use by another process. +152 */ +153 public void open() throws IOException, DatabaseException { +154 if (!isOpen()) { +155 cve = new CveDB(); +156 cve.open(); +157 cpe = CpeMemoryIndex.getInstance(); +158 try { 159 final long creationStart = System.currentTimeMillis(); 160 cpe.open(cve); -161 LOGGER.info("CPE Index Created ({} ms)", System.currentTimeMillis() - creationStart); -162 } catch (IndexException ex) { -163 LOGGER.debug("IndexException", ex); -164 throw new DatabaseException(ex); -165 } -166 } -167 } -168 -169 /** -170 * Closes the data sources. -171 */ -172 @Override -173 public void close() { -174 if (cpe != null) { -175 cpe.close(); -176 cpe = null; -177 } -178 if (cve != null) { -179 cve.close(); -180 cve = null; -181 } -182 } -183 -184 public boolean isOpen() { -185 return cpe != null && cpe.isOpen(); -186 } -187 -188 /** -189 * Searches the data store of CPE entries, trying to identify the CPE for -190 * the given dependency based on the evidence contained within. The -191 * dependency passed in is updated with any identified CPE values. -192 * -193 * @param dependency the dependency to search for CPE entries on. -194 * @throws CorruptIndexException is thrown when the Lucene index is corrupt. -195 * @throws IOException is thrown when an IOException occurs. -196 * @throws ParseException is thrown when the Lucene query cannot be parsed. -197 */ -198 protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException { -199 //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit -200 String vendors = ""; -201 String products = ""; -202 for (Confidence confidence : Confidence.values()) { -203 if (dependency.getVendorEvidence().contains(confidence)) { -204 vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence); -205 LOGGER.debug("vendor search: {}", vendors); -206 } -207 if (dependency.getProductEvidence().contains(confidence)) { -208 products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence); -209 LOGGER.debug("product search: {}", products); -210 } -211 if (!vendors.isEmpty() && !products.isEmpty()) { -212 final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(), -213 dependency.getProductEvidence().getWeighting()); -214 if (entries == null) { -215 continue; -216 } -217 boolean identifierAdded = false; -218 for (IndexEntry e : entries) { -219 LOGGER.debug("Verifying entry: {}", e); -220 if (verifyEntry(e, dependency)) { -221 final String vendor = e.getVendor(); -222 final String product = e.getProduct(); -223 LOGGER.debug("identified vendor/product: {}/{}", vendor, product); -224 identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence); -225 } -226 } -227 if (identifierAdded) { -228 break; -229 } -230 } -231 } -232 } -233 -234 /** -235 * Returns the text created by concatenating the text and the values from -236 * the EvidenceCollection (filtered for a specific confidence). This -237 * attempts to prevent duplicate terms from being added.<br/<br/> Note, if -238 * the evidence is longer then 200 characters it will be truncated. -239 * -240 * @param text the base text. -241 * @param ec an EvidenceCollection -242 * @param confidenceFilter a Confidence level to filter the evidence by. -243 * @return the new evidence text -244 */ -245 private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) { -246 final String txt = (text == null) ? "" : text; -247 final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size())); -248 sb.append(' ').append(txt).append(' '); -249 for (Evidence e : ec.iterator(confidenceFilter)) { -250 String value = e.getValue(); -251 -252 //hack to get around the fact that lucene does a really good job of recognizing domains and not -253 // splitting them. TODO - put together a better lucene analyzer specific to the domain. -254 if (value.startsWith("http://")) { -255 value = value.substring(7).replaceAll("\\.", " "); -256 } -257 if (value.startsWith("https://")) { -258 value = value.substring(8).replaceAll("\\.", " "); -259 } -260 if (sb.indexOf(" " + value + " ") < 0) { -261 sb.append(value).append(' '); -262 } -263 } -264 return sb.toString().trim(); -265 } -266 -267 /** -268 * <p> -269 * Searches the Lucene CPE index to identify possible CPE entries associated -270 * with the supplied vendor, product, and version.</p> -271 * -272 * <p> -273 * If either the vendorWeightings or productWeightings lists have been -274 * populated this data is used to add weighting factors to the search.</p> -275 * -276 * @param vendor the text used to search the vendor field -277 * @param product the text used to search the product field -278 * @param vendorWeightings a list of strings to use to add weighting factors -279 * to the vendor field -280 * @param productWeightings Adds a list of strings that will be used to add -281 * weighting factors to the product search -282 * @return a list of possible CPE values -283 */ -284 protected List<IndexEntry> searchCPE(String vendor, String product, -285 Set<String> vendorWeightings, Set<String> productWeightings) { -286 -287 final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS); -288 -289 final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings); -290 if (searchString == null) { -291 return ret; -292 } -293 try { -294 final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS); -295 for (ScoreDoc d : docs.scoreDocs) { -296 if (d.score >= 0.08) { -297 final Document doc = cpe.getDocument(d.doc); -298 final IndexEntry entry = new IndexEntry(); -299 entry.setVendor(doc.get(Fields.VENDOR)); -300 entry.setProduct(doc.get(Fields.PRODUCT)); -301 entry.setSearchScore(d.score); -302 if (!ret.contains(entry)) { -303 ret.add(entry); -304 } -305 } -306 } -307 return ret; -308 } catch (ParseException ex) { -309 LOGGER.warn("An error occurred querying the CPE data. See the log for more details."); -310 LOGGER.info("Unable to parse: {}", searchString, ex); -311 } catch (IOException ex) { -312 LOGGER.warn("An error occurred reading CPE data. See the log for more details."); -313 LOGGER.info("IO Error with search string: {}", searchString, ex); -314 } -315 return null; -316 } -317 -318 /** -319 * <p> -320 * Builds a Lucene search string by properly escaping data and constructing -321 * a valid search query.</p> -322 * -323 * <p> -324 * If either the possibleVendor or possibleProducts lists have been -325 * populated this data is used to add weighting factors to the search string -326 * generated.</p> -327 * -328 * @param vendor text to search the vendor field -329 * @param product text to search the product field -330 * @param vendorWeighting a list of strings to apply to the vendor to boost -331 * the terms weight -332 * @param productWeightings a list of strings to apply to the product to -333 * boost the terms weight -334 * @return the Lucene query -335 */ -336 protected String buildSearch(String vendor, String product, -337 Set<String> vendorWeighting, Set<String> productWeightings) { -338 final String v = vendor; //.replaceAll("[^\\w\\d]", " "); -339 final String p = product; //.replaceAll("[^\\w\\d]", " "); -340 final StringBuilder sb = new StringBuilder(v.length() + p.length() -341 + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER); -342 -343 if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) { -344 return null; -345 } -346 sb.append(" AND "); -347 if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) { -348 return null; -349 } -350 return sb.toString(); -351 } -352 -353 /** -354 * This method constructs a Lucene query for a given field. The searchText -355 * is split into separate words and if the word is within the list of -356 * weighted words then an additional weighting is applied to the term as it -357 * is appended into the query. -358 * -359 * @param sb a StringBuilder that the query text will be appended to. -360 * @param field the field within the Lucene index that the query is -361 * searching. -362 * @param searchText text used to construct the query. -363 * @param weightedText a list of terms that will be considered higher -364 * importance when searching. -365 * @return if the append was successful. -366 */ -367 private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) { -368 sb.append(' ').append(field).append(":( "); -369 -370 final String cleanText = cleanseText(searchText); -371 -372 if (cleanText.isEmpty()) { -373 return false; -374 } -375 -376 if (weightedText == null || weightedText.isEmpty()) { -377 LuceneUtils.appendEscapedLuceneQuery(sb, cleanText); -378 } else { -379 final StringTokenizer tokens = new StringTokenizer(cleanText); -380 while (tokens.hasMoreElements()) { -381 final String word = tokens.nextToken(); -382 StringBuilder temp = null; -383 for (String weighted : weightedText) { -384 final String weightedStr = cleanseText(weighted); -385 if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) { -386 temp = new StringBuilder(word.length() + 2); -387 LuceneUtils.appendEscapedLuceneQuery(temp, word); -388 temp.append(WEIGHTING_BOOST); -389 if (!word.equalsIgnoreCase(weightedStr)) { -390 temp.append(' '); -391 LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr); -392 temp.append(WEIGHTING_BOOST); -393 } -394 break; -395 } -396 } -397 sb.append(' '); -398 if (temp == null) { -399 LuceneUtils.appendEscapedLuceneQuery(sb, word); -400 } else { -401 sb.append(temp); -402 } -403 } -404 } -405 sb.append(" ) "); -406 return true; -407 } -408 -409 /** -410 * Removes characters from the input text that are not used within the CPE -411 * index. -412 * -413 * @param text is the text to remove the characters from. -414 * @return the text having removed some characters. -415 */ -416 private String cleanseText(String text) { -417 return text.replaceAll(CLEANSE_CHARACTER_RX, " "); -418 } -419 -420 /** -421 * Compares two strings after lower casing them and removing the non-alpha -422 * characters. -423 * -424 * @param l string one to compare. -425 * @param r string two to compare. -426 * @return whether or not the two strings are similar. -427 */ -428 private boolean equalsIgnoreCaseAndNonAlpha(String l, String r) { -429 if (l == null || r == null) { -430 return false; -431 } -432 -433 final String left = l.replaceAll(CLEANSE_NONALPHA_RX, ""); -434 final String right = r.replaceAll(CLEANSE_NONALPHA_RX, ""); -435 return left.equalsIgnoreCase(right); -436 } -437 -438 /** -439 * Ensures that the CPE Identified matches the dependency. This validates -440 * that the product, vendor, and version information for the CPE are -441 * contained within the dependencies evidence. -442 * -443 * @param entry a CPE entry. -444 * @param dependency the dependency that the CPE entries could be for. -445 * @return whether or not the entry is valid. -446 */ -447 private boolean verifyEntry(final IndexEntry entry, final Dependency dependency) { -448 boolean isValid = false; -449 -450 //TODO - does this nullify some of the fuzzy matching that happens in the lucene search? -451 // for instance CPE some-component and in the evidence we have SomeComponent. -452 if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct()) -453 && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) { -454 //&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion()) -455 isValid = true; -456 } -457 return isValid; -458 } -459 -460 /** -461 * Used to determine if the EvidenceCollection contains a specific string. -462 * -463 * @param ec an EvidenceCollection -464 * @param text the text to search for -465 * @return whether or not the EvidenceCollection contains the string -466 */ -467 private boolean collectionContainsString(EvidenceCollection ec, String text) { -468 //TODO - likely need to change the split... not sure if this will work for CPE with special chars -469 if (text == null) { -470 return false; -471 } -472 final String[] words = text.split("[\\s_-]"); -473 final List<String> list = new ArrayList<String>(); -474 String tempWord = null; -475 for (String word : words) { -476 /* -477 single letter words should be concatenated with the next word. -478 so { "m", "core", "sample" } -> { "mcore", "sample" } -479 */ -480 if (tempWord != null) { -481 list.add(tempWord + word); -482 tempWord = null; -483 } else if (word.length() <= 2) { -484 tempWord = word; -485 } else { -486 list.add(word); -487 } -488 } -489 if (tempWord != null) { -490 if (!list.isEmpty()) { -491 final String tmp = list.get(list.size() - 1) + tempWord; -492 list.add(tmp); -493 } else { -494 list.add(tempWord); -495 } -496 } -497 if (list.isEmpty()) { -498 return false; -499 } -500 boolean contains = true; -501 for (String word : list) { -502 contains &= ec.containsUsedString(word); -503 } -504 return contains; -505 } -506 -507 /** -508 * Analyzes a dependency and attempts to determine if there are any CPE -509 * identifiers for this dependency. -510 * -511 * @param dependency The Dependency to analyze. -512 * @param engine The analysis engine -513 * @throws AnalysisException is thrown if there is an issue analyzing the -514 * dependency. -515 */ -516 @Override -517 public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException { -518 try { -519 determineCPE(dependency); -520 } catch (CorruptIndexException ex) { -521 throw new AnalysisException("CPE Index is corrupt.", ex); -522 } catch (IOException ex) { -523 throw new AnalysisException("Failure opening the CPE Index.", ex); -524 } catch (ParseException ex) { -525 throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex); -526 } -527 } -528 -529 /** -530 * Retrieves a list of CPE values from the CveDB based on the vendor and -531 * product passed in. The list is then validated to find only CPEs that are -532 * valid for the given dependency. It is possible that the CPE identified is -533 * a best effort "guess" based on the vendor, product, and version -534 * information. -535 * -536 * @param dependency the Dependency being analyzed -537 * @param vendor the vendor for the CPE being analyzed -538 * @param product the product for the CPE being analyzed -539 * @param currentConfidence the current confidence being used during -540 * analysis -541 * @return <code>true</code> if an identifier was added to the dependency; -542 * otherwise <code>false</code> -543 * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported -544 */ -545 protected boolean determineIdentifiers(Dependency dependency, String vendor, String product, -546 Confidence currentConfidence) throws UnsupportedEncodingException { -547 final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product); -548 DependencyVersion bestGuess = new DependencyVersion("-"); -549 Confidence bestGuessConf = null; -550 boolean hasBroadMatch = false; -551 final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>(); -552 -553 //TODO the following algorithm incorrectly identifies things as a lower version -554 // if there lower confidence evidence when the current (highest) version number -555 // is newer then anything in the NVD. -556 for (Confidence conf : Confidence.values()) { -557 for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) { -558 final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue()); -559 if (evVer == null) { -560 continue; -561 } -562 for (VulnerableSoftware vs : cpes) { -563 DependencyVersion dbVer; -564 if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) { -565 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate()); -566 } else { -567 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion()); -568 } -569 if (dbVer == null) { //special case, no version specified - everything is vulnerable -570 hasBroadMatch = true; -571 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); -572 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf); -573 collected.add(match); -574 } else if (evVer.equals(dbVer)) { //yeah! exact match -575 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); -576 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf); -577 collected.add(match); -578 -579 //TODO the following isn't quite right is it? need to think about this guessing game a bit more. -580 } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() -581 && evVer.matchesAtLeastThreeLevels(dbVer)) { -582 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { -583 if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) { -584 bestGuess = dbVer; -585 bestGuessConf = conf; -586 } -587 } -588 } -589 } -590 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { -591 if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) { -592 bestGuess = evVer; -593 bestGuessConf = conf; -594 } -595 } -596 } -597 } -598 final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString()); -599 String url = null; -600 if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess. -601 final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product); -602 url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8")); -603 } -604 if (bestGuessConf == null) { -605 bestGuessConf = Confidence.LOW; -606 } -607 final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf); -608 collected.add(match); -609 -610 Collections.sort(collected); -611 final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence(); -612 final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence(); -613 boolean identifierAdded = false; -614 for (IdentifierMatch m : collected) { -615 if (bestIdentifierQuality.equals(m.getConfidence()) -616 && bestEvidenceQuality.equals(m.getEvidenceConfidence())) { -617 final Identifier i = m.getIdentifier(); -618 if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) { -619 i.setConfidence(Confidence.LOW); -620 } else { -621 i.setConfidence(bestEvidenceQuality); -622 } -623 dependency.addIdentifier(i); -624 identifierAdded = true; -625 } -626 } -627 return identifierAdded; -628 } -629 -630 /** -631 * The confidence whether the identifier is an exact match, or a best guess. -632 */ -633 private enum IdentifierConfidence { -634 -635 /** -636 * An exact match for the CPE. -637 */ -638 EXACT_MATCH, -639 /** -640 * A best guess for the CPE. -641 */ -642 BEST_GUESS, -643 /** -644 * The entire vendor/product group must be added (without a guess at -645 * version) because there is a CVE with a VS that only specifies -646 * vendor/product. -647 */ -648 BROAD_MATCH -649 } -650 -651 /** -652 * A simple object to hold an identifier and carry information about the -653 * confidence in the identifier. -654 */ -655 private static class IdentifierMatch implements Comparable<IdentifierMatch> { -656 -657 /** -658 * Constructs an IdentifierMatch. -659 * -660 * @param type the type of identifier (such as CPE) -661 * @param value the value of the identifier -662 * @param url the URL of the identifier -663 * @param identifierConfidence the confidence in the identifier: best -664 * guess or exact match -665 * @param evidenceConfidence the confidence of the evidence used to find -666 * the identifier -667 */ -668 IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) { -669 this.identifier = new Identifier(type, value, url); -670 this.confidence = identifierConfidence; -671 this.evidenceConfidence = evidenceConfidence; -672 } -673 //<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier"> -674 /** -675 * The confidence in the evidence used to identify this match. -676 */ -677 private Confidence evidenceConfidence; -678 -679 /** -680 * Get the value of evidenceConfidence -681 * -682 * @return the value of evidenceConfidence -683 */ -684 public Confidence getEvidenceConfidence() { -685 return evidenceConfidence; -686 } -687 -688 /** -689 * Set the value of evidenceConfidence -690 * -691 * @param evidenceConfidence new value of evidenceConfidence -692 */ -693 public void setEvidenceConfidence(Confidence evidenceConfidence) { -694 this.evidenceConfidence = evidenceConfidence; -695 } -696 /** -697 * The confidence whether this is an exact match, or a best guess. -698 */ -699 private IdentifierConfidence confidence; -700 -701 /** -702 * Get the value of confidence. -703 * -704 * @return the value of confidence -705 */ -706 public IdentifierConfidence getConfidence() { -707 return confidence; -708 } -709 -710 /** -711 * Set the value of confidence. -712 * -713 * @param confidence new value of confidence -714 */ -715 public void setConfidence(IdentifierConfidence confidence) { -716 this.confidence = confidence; -717 } -718 /** -719 * The CPE identifier. -720 */ -721 private Identifier identifier; -722 -723 /** -724 * Get the value of identifier. -725 * -726 * @return the value of identifier -727 */ -728 public Identifier getIdentifier() { -729 return identifier; -730 } -731 -732 /** -733 * Set the value of identifier. -734 * -735 * @param identifier new value of identifier -736 */ -737 public void setIdentifier(Identifier identifier) { -738 this.identifier = identifier; -739 } -740 //</editor-fold> -741 //<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals"> -742 -743 /** -744 * Standard toString() implementation. -745 * -746 * @return the string representation of the object -747 */ -748 @Override -749 public String toString() { -750 return "IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence -751 + ", confidence=" + confidence + ", identifier=" + identifier + '}'; -752 } -753 -754 /** -755 * Standard hashCode() implementation. -756 * -757 * @return the hashCode -758 */ -759 @Override -760 public int hashCode() { -761 int hash = 5; -762 hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0); -763 hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0); -764 hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0); -765 return hash; -766 } -767 -768 /** -769 * Standard equals implementation. -770 * -771 * @param obj the object to compare -772 * @return true if the objects are equal, otherwise false -773 */ -774 @Override -775 public boolean equals(Object obj) { -776 if (obj == null) { -777 return false; -778 } -779 if (getClass() != obj.getClass()) { -780 return false; -781 } -782 final IdentifierMatch other = (IdentifierMatch) obj; -783 if (this.evidenceConfidence != other.evidenceConfidence) { -784 return false; -785 } -786 if (this.confidence != other.confidence) { -787 return false; -788 } -789 if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) { -790 return false; -791 } -792 return true; -793 } -794 //</editor-fold> -795 -796 /** -797 * Standard implementation of compareTo that compares identifier -798 * confidence, evidence confidence, and then the identifier. -799 * -800 * @param o the IdentifierMatch to compare to -801 * @return the natural ordering of IdentifierMatch -802 */ -803 @Override -804 public int compareTo(IdentifierMatch o) { -805 return new CompareToBuilder() -806 .append(confidence, o.confidence) -807 .append(evidenceConfidence, o.evidenceConfidence) -808 .append(identifier, o.identifier) -809 .toComparison(); -810 /* -811 int conf = this.confidence.compareTo(o.confidence); -812 if (conf == 0) { -813 conf = this.evidenceConfidence.compareTo(o.evidenceConfidence); -814 if (conf == 0) { -815 conf = identifier.compareTo(o.identifier); -816 } -817 } -818 return conf; -819 */ -820 } -821 } -822 } +161 final long creationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - creationStart); +162 LOGGER.info("Created CPE Index ({} seconds)", creationSeconds); +163 } catch (IndexException ex) { +164 LOGGER.debug("IndexException", ex); +165 throw new DatabaseException(ex); +166 } +167 } +168 } +169 +170 /** +171 * Closes the data sources. +172 */ +173 @Override +174 public void close() { +175 if (cpe != null) { +176 cpe.close(); +177 cpe = null; +178 } +179 if (cve != null) { +180 cve.close(); +181 cve = null; +182 } +183 } +184 +185 public boolean isOpen() { +186 return cpe != null && cpe.isOpen(); +187 } +188 +189 /** +190 * Searches the data store of CPE entries, trying to identify the CPE for +191 * the given dependency based on the evidence contained within. The +192 * dependency passed in is updated with any identified CPE values. +193 * +194 * @param dependency the dependency to search for CPE entries on. +195 * @throws CorruptIndexException is thrown when the Lucene index is corrupt. +196 * @throws IOException is thrown when an IOException occurs. +197 * @throws ParseException is thrown when the Lucene query cannot be parsed. +198 */ +199 protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException { +200 //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit +201 String vendors = ""; +202 String products = ""; +203 for (Confidence confidence : Confidence.values()) { +204 if (dependency.getVendorEvidence().contains(confidence)) { +205 vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence); +206 LOGGER.debug("vendor search: {}", vendors); +207 } +208 if (dependency.getProductEvidence().contains(confidence)) { +209 products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence); +210 LOGGER.debug("product search: {}", products); +211 } +212 if (!vendors.isEmpty() && !products.isEmpty()) { +213 final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(), +214 dependency.getProductEvidence().getWeighting()); +215 if (entries == null) { +216 continue; +217 } +218 boolean identifierAdded = false; +219 for (IndexEntry e : entries) { +220 LOGGER.debug("Verifying entry: {}", e); +221 if (verifyEntry(e, dependency)) { +222 final String vendor = e.getVendor(); +223 final String product = e.getProduct(); +224 LOGGER.debug("identified vendor/product: {}/{}", vendor, product); +225 identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence); +226 } +227 } +228 if (identifierAdded) { +229 break; +230 } +231 } +232 } +233 } +234 +235 /** +236 * Returns the text created by concatenating the text and the values from +237 * the EvidenceCollection (filtered for a specific confidence). This +238 * attempts to prevent duplicate terms from being added.<br/<br/> Note, if +239 * the evidence is longer then 200 characters it will be truncated. +240 * +241 * @param text the base text. +242 * @param ec an EvidenceCollection +243 * @param confidenceFilter a Confidence level to filter the evidence by. +244 * @return the new evidence text +245 */ +246 private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) { +247 final String txt = (text == null) ? "" : text; +248 final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size())); +249 sb.append(' ').append(txt).append(' '); +250 for (Evidence e : ec.iterator(confidenceFilter)) { +251 String value = e.getValue(); +252 +253 //hack to get around the fact that lucene does a really good job of recognizing domains and not +254 // splitting them. TODO - put together a better lucene analyzer specific to the domain. +255 if (value.startsWith("http://")) { +256 value = value.substring(7).replaceAll("\\.", " "); +257 } +258 if (value.startsWith("https://")) { +259 value = value.substring(8).replaceAll("\\.", " "); +260 } +261 if (sb.indexOf(" " + value + " ") < 0) { +262 sb.append(value).append(' '); +263 } +264 } +265 return sb.toString().trim(); +266 } +267 +268 /** +269 * <p> +270 * Searches the Lucene CPE index to identify possible CPE entries associated +271 * with the supplied vendor, product, and version.</p> +272 * +273 * <p> +274 * If either the vendorWeightings or productWeightings lists have been +275 * populated this data is used to add weighting factors to the search.</p> +276 * +277 * @param vendor the text used to search the vendor field +278 * @param product the text used to search the product field +279 * @param vendorWeightings a list of strings to use to add weighting factors +280 * to the vendor field +281 * @param productWeightings Adds a list of strings that will be used to add +282 * weighting factors to the product search +283 * @return a list of possible CPE values +284 */ +285 protected List<IndexEntry> searchCPE(String vendor, String product, +286 Set<String> vendorWeightings, Set<String> productWeightings) { +287 +288 final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS); +289 +290 final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings); +291 if (searchString == null) { +292 return ret; +293 } +294 try { +295 final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS); +296 for (ScoreDoc d : docs.scoreDocs) { +297 if (d.score >= 0.08) { +298 final Document doc = cpe.getDocument(d.doc); +299 final IndexEntry entry = new IndexEntry(); +300 entry.setVendor(doc.get(Fields.VENDOR)); +301 entry.setProduct(doc.get(Fields.PRODUCT)); +302 entry.setSearchScore(d.score); +303 if (!ret.contains(entry)) { +304 ret.add(entry); +305 } +306 } +307 } +308 return ret; +309 } catch (ParseException ex) { +310 LOGGER.warn("An error occurred querying the CPE data. See the log for more details."); +311 LOGGER.info("Unable to parse: {}", searchString, ex); +312 } catch (IOException ex) { +313 LOGGER.warn("An error occurred reading CPE data. See the log for more details."); +314 LOGGER.info("IO Error with search string: {}", searchString, ex); +315 } +316 return null; +317 } +318 +319 /** +320 * <p> +321 * Builds a Lucene search string by properly escaping data and constructing +322 * a valid search query.</p> +323 * +324 * <p> +325 * If either the possibleVendor or possibleProducts lists have been +326 * populated this data is used to add weighting factors to the search string +327 * generated.</p> +328 * +329 * @param vendor text to search the vendor field +330 * @param product text to search the product field +331 * @param vendorWeighting a list of strings to apply to the vendor to boost +332 * the terms weight +333 * @param productWeightings a list of strings to apply to the product to +334 * boost the terms weight +335 * @return the Lucene query +336 */ +337 protected String buildSearch(String vendor, String product, +338 Set<String> vendorWeighting, Set<String> productWeightings) { +339 final String v = vendor; //.replaceAll("[^\\w\\d]", " "); +340 final String p = product; //.replaceAll("[^\\w\\d]", " "); +341 final StringBuilder sb = new StringBuilder(v.length() + p.length() +342 + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER); +343 +344 if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) { +345 return null; +346 } +347 sb.append(" AND "); +348 if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) { +349 return null; +350 } +351 return sb.toString(); +352 } +353 +354 /** +355 * This method constructs a Lucene query for a given field. The searchText +356 * is split into separate words and if the word is within the list of +357 * weighted words then an additional weighting is applied to the term as it +358 * is appended into the query. +359 * +360 * @param sb a StringBuilder that the query text will be appended to. +361 * @param field the field within the Lucene index that the query is +362 * searching. +363 * @param searchText text used to construct the query. +364 * @param weightedText a list of terms that will be considered higher +365 * importance when searching. +366 * @return if the append was successful. +367 */ +368 private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) { +369 sb.append(' ').append(field).append(":( "); +370 +371 final String cleanText = cleanseText(searchText); +372 +373 if (cleanText.isEmpty()) { +374 return false; +375 } +376 +377 if (weightedText == null || weightedText.isEmpty()) { +378 LuceneUtils.appendEscapedLuceneQuery(sb, cleanText); +379 } else { +380 final StringTokenizer tokens = new StringTokenizer(cleanText); +381 while (tokens.hasMoreElements()) { +382 final String word = tokens.nextToken(); +383 StringBuilder temp = null; +384 for (String weighted : weightedText) { +385 final String weightedStr = cleanseText(weighted); +386 if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) { +387 temp = new StringBuilder(word.length() + 2); +388 LuceneUtils.appendEscapedLuceneQuery(temp, word); +389 temp.append(WEIGHTING_BOOST); +390 if (!word.equalsIgnoreCase(weightedStr)) { +391 temp.append(' '); +392 LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr); +393 temp.append(WEIGHTING_BOOST); +394 } +395 break; +396 } +397 } +398 sb.append(' '); +399 if (temp == null) { +400 LuceneUtils.appendEscapedLuceneQuery(sb, word); +401 } else { +402 sb.append(temp); +403 } +404 } +405 } +406 sb.append(" ) "); +407 return true; +408 } +409 +410 /** +411 * Removes characters from the input text that are not used within the CPE +412 * index. +413 * +414 * @param text is the text to remove the characters from. +415 * @return the text having removed some characters. +416 */ +417 private String cleanseText(String text) { +418 return text.replaceAll(CLEANSE_CHARACTER_RX, " "); +419 } +420 +421 /** +422 * Compares two strings after lower casing them and removing the non-alpha +423 * characters. +424 * +425 * @param l string one to compare. +426 * @param r string two to compare. +427 * @return whether or not the two strings are similar. +428 */ +429 private boolean equalsIgnoreCaseAndNonAlpha(String l, String r) { +430 if (l == null || r == null) { +431 return false; +432 } +433 +434 final String left = l.replaceAll(CLEANSE_NONALPHA_RX, ""); +435 final String right = r.replaceAll(CLEANSE_NONALPHA_RX, ""); +436 return left.equalsIgnoreCase(right); +437 } +438 +439 /** +440 * Ensures that the CPE Identified matches the dependency. This validates +441 * that the product, vendor, and version information for the CPE are +442 * contained within the dependencies evidence. +443 * +444 * @param entry a CPE entry. +445 * @param dependency the dependency that the CPE entries could be for. +446 * @return whether or not the entry is valid. +447 */ +448 private boolean verifyEntry(final IndexEntry entry, final Dependency dependency) { +449 boolean isValid = false; +450 +451 //TODO - does this nullify some of the fuzzy matching that happens in the lucene search? +452 // for instance CPE some-component and in the evidence we have SomeComponent. +453 if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct()) +454 && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) { +455 //&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion()) +456 isValid = true; +457 } +458 return isValid; +459 } +460 +461 /** +462 * Used to determine if the EvidenceCollection contains a specific string. +463 * +464 * @param ec an EvidenceCollection +465 * @param text the text to search for +466 * @return whether or not the EvidenceCollection contains the string +467 */ +468 private boolean collectionContainsString(EvidenceCollection ec, String text) { +469 //TODO - likely need to change the split... not sure if this will work for CPE with special chars +470 if (text == null) { +471 return false; +472 } +473 final String[] words = text.split("[\\s_-]"); +474 final List<String> list = new ArrayList<String>(); +475 String tempWord = null; +476 for (String word : words) { +477 /* +478 single letter words should be concatenated with the next word. +479 so { "m", "core", "sample" } -> { "mcore", "sample" } +480 */ +481 if (tempWord != null) { +482 list.add(tempWord + word); +483 tempWord = null; +484 } else if (word.length() <= 2) { +485 tempWord = word; +486 } else { +487 list.add(word); +488 } +489 } +490 if (tempWord != null) { +491 if (!list.isEmpty()) { +492 final String tmp = list.get(list.size() - 1) + tempWord; +493 list.add(tmp); +494 } else { +495 list.add(tempWord); +496 } +497 } +498 if (list.isEmpty()) { +499 return false; +500 } +501 boolean contains = true; +502 for (String word : list) { +503 contains &= ec.containsUsedString(word); +504 } +505 return contains; +506 } +507 +508 /** +509 * Analyzes a dependency and attempts to determine if there are any CPE +510 * identifiers for this dependency. +511 * +512 * @param dependency The Dependency to analyze. +513 * @param engine The analysis engine +514 * @throws AnalysisException is thrown if there is an issue analyzing the +515 * dependency. +516 */ +517 @Override +518 public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException { +519 try { +520 determineCPE(dependency); +521 } catch (CorruptIndexException ex) { +522 throw new AnalysisException("CPE Index is corrupt.", ex); +523 } catch (IOException ex) { +524 throw new AnalysisException("Failure opening the CPE Index.", ex); +525 } catch (ParseException ex) { +526 throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex); +527 } +528 } +529 +530 /** +531 * Retrieves a list of CPE values from the CveDB based on the vendor and +532 * product passed in. The list is then validated to find only CPEs that are +533 * valid for the given dependency. It is possible that the CPE identified is +534 * a best effort "guess" based on the vendor, product, and version +535 * information. +536 * +537 * @param dependency the Dependency being analyzed +538 * @param vendor the vendor for the CPE being analyzed +539 * @param product the product for the CPE being analyzed +540 * @param currentConfidence the current confidence being used during +541 * analysis +542 * @return <code>true</code> if an identifier was added to the dependency; +543 * otherwise <code>false</code> +544 * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported +545 */ +546 protected boolean determineIdentifiers(Dependency dependency, String vendor, String product, +547 Confidence currentConfidence) throws UnsupportedEncodingException { +548 final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product); +549 DependencyVersion bestGuess = new DependencyVersion("-"); +550 Confidence bestGuessConf = null; +551 boolean hasBroadMatch = false; +552 final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>(); +553 +554 //TODO the following algorithm incorrectly identifies things as a lower version +555 // if there lower confidence evidence when the current (highest) version number +556 // is newer then anything in the NVD. +557 for (Confidence conf : Confidence.values()) { +558 for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) { +559 final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue()); +560 if (evVer == null) { +561 continue; +562 } +563 for (VulnerableSoftware vs : cpes) { +564 DependencyVersion dbVer; +565 if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) { +566 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate()); +567 } else { +568 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion()); +569 } +570 if (dbVer == null) { //special case, no version specified - everything is vulnerable +571 hasBroadMatch = true; +572 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); +573 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf); +574 collected.add(match); +575 } else if (evVer.equals(dbVer)) { //yeah! exact match +576 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); +577 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf); +578 collected.add(match); +579 +580 //TODO the following isn't quite right is it? need to think about this guessing game a bit more. +581 } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() +582 && evVer.matchesAtLeastThreeLevels(dbVer)) { +583 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { +584 if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) { +585 bestGuess = dbVer; +586 bestGuessConf = conf; +587 } +588 } +589 } +590 } +591 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { +592 if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) { +593 bestGuess = evVer; +594 bestGuessConf = conf; +595 } +596 } +597 } +598 } +599 final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString()); +600 String url = null; +601 if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess. +602 final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product); +603 url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8")); +604 } +605 if (bestGuessConf == null) { +606 bestGuessConf = Confidence.LOW; +607 } +608 final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf); +609 collected.add(match); +610 +611 Collections.sort(collected); +612 final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence(); +613 final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence(); +614 boolean identifierAdded = false; +615 for (IdentifierMatch m : collected) { +616 if (bestIdentifierQuality.equals(m.getConfidence()) +617 && bestEvidenceQuality.equals(m.getEvidenceConfidence())) { +618 final Identifier i = m.getIdentifier(); +619 if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) { +620 i.setConfidence(Confidence.LOW); +621 } else { +622 i.setConfidence(bestEvidenceQuality); +623 } +624 dependency.addIdentifier(i); +625 identifierAdded = true; +626 } +627 } +628 return identifierAdded; +629 } +630 +631 /** +632 * The confidence whether the identifier is an exact match, or a best guess. +633 */ +634 private enum IdentifierConfidence { +635 +636 /** +637 * An exact match for the CPE. +638 */ +639 EXACT_MATCH, +640 /** +641 * A best guess for the CPE. +642 */ +643 BEST_GUESS, +644 /** +645 * The entire vendor/product group must be added (without a guess at +646 * version) because there is a CVE with a VS that only specifies +647 * vendor/product. +648 */ +649 BROAD_MATCH +650 } +651 +652 /** +653 * A simple object to hold an identifier and carry information about the +654 * confidence in the identifier. +655 */ +656 private static class IdentifierMatch implements Comparable<IdentifierMatch> { +657 +658 /** +659 * Constructs an IdentifierMatch. +660 * +661 * @param type the type of identifier (such as CPE) +662 * @param value the value of the identifier +663 * @param url the URL of the identifier +664 * @param identifierConfidence the confidence in the identifier: best +665 * guess or exact match +666 * @param evidenceConfidence the confidence of the evidence used to find +667 * the identifier +668 */ +669 IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) { +670 this.identifier = new Identifier(type, value, url); +671 this.confidence = identifierConfidence; +672 this.evidenceConfidence = evidenceConfidence; +673 } +674 //<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier"> +675 /** +676 * The confidence in the evidence used to identify this match. +677 */ +678 private Confidence evidenceConfidence; +679 +680 /** +681 * Get the value of evidenceConfidence +682 * +683 * @return the value of evidenceConfidence +684 */ +685 public Confidence getEvidenceConfidence() { +686 return evidenceConfidence; +687 } +688 +689 /** +690 * Set the value of evidenceConfidence +691 * +692 * @param evidenceConfidence new value of evidenceConfidence +693 */ +694 public void setEvidenceConfidence(Confidence evidenceConfidence) { +695 this.evidenceConfidence = evidenceConfidence; +696 } +697 /** +698 * The confidence whether this is an exact match, or a best guess. +699 */ +700 private IdentifierConfidence confidence; +701 +702 /** +703 * Get the value of confidence. +704 * +705 * @return the value of confidence +706 */ +707 public IdentifierConfidence getConfidence() { +708 return confidence; +709 } +710 +711 /** +712 * Set the value of confidence. +713 * +714 * @param confidence new value of confidence +715 */ +716 public void setConfidence(IdentifierConfidence confidence) { +717 this.confidence = confidence; +718 } +719 /** +720 * The CPE identifier. +721 */ +722 private Identifier identifier; +723 +724 /** +725 * Get the value of identifier. +726 * +727 * @return the value of identifier +728 */ +729 public Identifier getIdentifier() { +730 return identifier; +731 } +732 +733 /** +734 * Set the value of identifier. +735 * +736 * @param identifier new value of identifier +737 */ +738 public void setIdentifier(Identifier identifier) { +739 this.identifier = identifier; +740 } +741 //</editor-fold> +742 //<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals"> +743 +744 /** +745 * Standard toString() implementation. +746 * +747 * @return the string representation of the object +748 */ +749 @Override +750 public String toString() { +751 return "IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence +752 + ", confidence=" + confidence + ", identifier=" + identifier + '}'; +753 } +754 +755 /** +756 * Standard hashCode() implementation. +757 * +758 * @return the hashCode +759 */ +760 @Override +761 public int hashCode() { +762 int hash = 5; +763 hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0); +764 hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0); +765 hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0); +766 return hash; +767 } +768 +769 /** +770 * Standard equals implementation. +771 * +772 * @param obj the object to compare +773 * @return true if the objects are equal, otherwise false +774 */ +775 @Override +776 public boolean equals(Object obj) { +777 if (obj == null) { +778 return false; +779 } +780 if (getClass() != obj.getClass()) { +781 return false; +782 } +783 final IdentifierMatch other = (IdentifierMatch) obj; +784 if (this.evidenceConfidence != other.evidenceConfidence) { +785 return false; +786 } +787 if (this.confidence != other.confidence) { +788 return false; +789 } +790 if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) { +791 return false; +792 } +793 return true; +794 } +795 //</editor-fold> +796 +797 /** +798 * Standard implementation of compareTo that compares identifier +799 * confidence, evidence confidence, and then the identifier. +800 * +801 * @param o the IdentifierMatch to compare to +802 * @return the natural ordering of IdentifierMatch +803 */ +804 @Override +805 public int compareTo(IdentifierMatch o) { +806 return new CompareToBuilder() +807 .append(confidence, o.confidence) +808 .append(evidenceConfidence, o.evidenceConfidence) +809 .append(identifier, o.identifier) +810 .toComparison(); +811 /* +812 int conf = this.confidence.compareTo(o.confidence); +813 if (conf == 0) { +814 conf = this.evidenceConfidence.compareTo(o.evidenceConfidence); +815 if (conf == 0) { +816 conf = identifier.compareTo(o.identifier); +817 } +818 } +819 return conf; +820 */ +821 } +822 } +823 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html index 886f0d5d1..03f83c6ff 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html @@ -83,7 +83,7 @@ 75 * The analyzer should be disabled if there are errors, so this is a flag to 76 * determine if such an error has occurred. 77 */ -78 private boolean errorFlag = false; +78 private volatile boolean errorFlag = false; 79 80 /** 81 * The searcher itself. diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html index 4fd93c80a..6c4cc84dd 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html @@ -32,19 +32,19 @@ 24 import org.owasp.dependencycheck.data.composer.ComposerLockParser; 25 import org.owasp.dependencycheck.dependency.Confidence; 26 import org.owasp.dependencycheck.dependency.Dependency; -27 import org.owasp.dependencycheck.utils.Checksum; -28 import org.owasp.dependencycheck.utils.FileFilterBuilder; -29 import org.owasp.dependencycheck.utils.Settings; -30 import org.slf4j.Logger; -31 import org.slf4j.LoggerFactory; -32 -33 import java.io.FileFilter; -34 import java.io.FileInputStream; -35 import java.io.FileNotFoundException; -36 import java.nio.charset.Charset; -37 import java.security.MessageDigest; -38 import java.security.NoSuchAlgorithmException; -39 import org.owasp.dependencycheck.exception.InitializationException; +27 import org.owasp.dependencycheck.exception.InitializationException; +28 import org.owasp.dependencycheck.utils.Checksum; +29 import org.owasp.dependencycheck.utils.FileFilterBuilder; +30 import org.owasp.dependencycheck.utils.Settings; +31 import org.slf4j.Logger; +32 import org.slf4j.LoggerFactory; +33 +34 import java.io.FileFilter; +35 import java.io.FileInputStream; +36 import java.io.FileNotFoundException; +37 import java.nio.charset.Charset; +38 import java.security.MessageDigest; +39 import java.security.NoSuchAlgorithmException; 40 41 /** 42 * Used to analyze a composer.lock file for a composer PHP app. @@ -93,91 +93,100 @@ 85 @Override 86 protected void initializeFileTypeAnalyzer() throws InitializationException { 87 try { -88 sha1 = MessageDigest.getInstance("SHA1"); -89 } catch (NoSuchAlgorithmException ex) { +88 getSha1MessageDigest(); +89 } catch (IllegalStateException ex) { 90 setEnabled(false); -91 throw new InitializationException("Unable to create SHA1 MmessageDigest", ex); +91 throw new InitializationException("Unable to create SHA1 MessageDigest", ex); 92 } 93 } 94 95 /** -96 * The MessageDigest for calculating a new digest for the new dependencies -97 * added. -98 */ -99 private MessageDigest sha1 = null; -100 -101 /** -102 * Entry point for the analyzer. -103 * -104 * @param dependency the dependency to analyze -105 * @param engine the engine scanning -106 * @throws AnalysisException if there's a failure during analysis -107 */ -108 @Override -109 protected void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { -110 FileInputStream fis = null; -111 try { -112 fis = new FileInputStream(dependency.getActualFile()); -113 final ComposerLockParser clp = new ComposerLockParser(fis); -114 LOGGER.info("Checking composer.lock file {}", dependency.getActualFilePath()); -115 clp.process(); -116 for (ComposerDependency dep : clp.getDependencies()) { -117 final Dependency d = new Dependency(dependency.getActualFile()); -118 d.setDisplayFileName(String.format("%s:%s/%s", dependency.getDisplayFileName(), dep.getGroup(), dep.getProject())); -119 final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject()); -120 d.setFilePath(filePath); -121 d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset())))); -122 d.getVendorEvidence().addEvidence(COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST); -123 d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST); -124 d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST); -125 LOGGER.info("Adding dependency {}", d); -126 engine.getDependencies().add(d); -127 } -128 } catch (FileNotFoundException fnfe) { -129 LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath()); -130 } catch (ComposerException ce) { -131 LOGGER.warn("Error parsing composer.json {}", dependency.getActualFilePath(), ce); -132 } finally { -133 if (fis != null) { -134 try { -135 fis.close(); -136 } catch (Exception e) { -137 LOGGER.debug("Unable to close file", e); -138 } -139 } -140 } -141 } -142 -143 /** -144 * Gets the key to determine whether the analyzer is enabled. -145 * -146 * @return the key specifying whether the analyzer is enabled -147 */ -148 @Override -149 protected String getAnalyzerEnabledSettingKey() { -150 return Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED; -151 } -152 -153 /** -154 * Returns the analyzer's name. -155 * -156 * @return the analyzer's name -157 */ -158 @Override -159 public String getName() { -160 return ANALYZER_NAME; -161 } -162 -163 /** -164 * Returns the phase this analyzer should run under. -165 * -166 * @return the analysis phase -167 */ -168 @Override -169 public AnalysisPhase getAnalysisPhase() { -170 return AnalysisPhase.INFORMATION_COLLECTION; -171 } -172 } +96 * Entry point for the analyzer. +97 * +98 * @param dependency the dependency to analyze +99 * @param engine the engine scanning +100 * @throws AnalysisException if there's a failure during analysis +101 */ +102 @Override +103 protected void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { +104 FileInputStream fis = null; +105 try { +106 fis = new FileInputStream(dependency.getActualFile()); +107 final ComposerLockParser clp = new ComposerLockParser(fis); +108 LOGGER.info("Checking composer.lock file {}", dependency.getActualFilePath()); +109 clp.process(); +110 for (ComposerDependency dep : clp.getDependencies()) { +111 final Dependency d = new Dependency(dependency.getActualFile()); +112 d.setDisplayFileName(String.format("%s:%s/%s", dependency.getDisplayFileName(), dep.getGroup(), dep.getProject())); +113 final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject()); +114 final MessageDigest sha1 = getSha1MessageDigest(); +115 d.setFilePath(filePath); +116 d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset())))); +117 d.getVendorEvidence().addEvidence(COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST); +118 d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST); +119 d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST); +120 LOGGER.info("Adding dependency {}", d); +121 engine.getDependencies().add(d); +122 } +123 } catch (FileNotFoundException fnfe) { +124 LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath()); +125 } catch (ComposerException ce) { +126 LOGGER.warn("Error parsing composer.json {}", dependency.getActualFilePath(), ce); +127 } finally { +128 if (fis != null) { +129 try { +130 fis.close(); +131 } catch (Exception e) { +132 LOGGER.debug("Unable to close file", e); +133 } +134 } +135 } +136 } +137 +138 /** +139 * Gets the key to determine whether the analyzer is enabled. +140 * +141 * @return the key specifying whether the analyzer is enabled +142 */ +143 @Override +144 protected String getAnalyzerEnabledSettingKey() { +145 return Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED; +146 } +147 +148 /** +149 * Returns the analyzer's name. +150 * +151 * @return the analyzer's name +152 */ +153 @Override +154 public String getName() { +155 return ANALYZER_NAME; +156 } +157 +158 /** +159 * Returns the phase this analyzer should run under. +160 * +161 * @return the analysis phase +162 */ +163 @Override +164 public AnalysisPhase getAnalysisPhase() { +165 return AnalysisPhase.INFORMATION_COLLECTION; +166 } +167 +168 /** +169 * Returns the sha1 message digest. +170 * +171 * @return the sha1 message digest +172 */ +173 private MessageDigest getSha1MessageDigest() { +174 try { +175 return MessageDigest.getInstance("SHA1"); +176 } catch (NoSuchAlgorithmException e) { +177 LOGGER.error(e.getMessage()); +178 throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e); +179 } +180 } +181 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html index 0ab088c9a..a319654cc 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html @@ -54,7 +54,7 @@ 46 * 47 * @author Jeremy Long 48 */ -49 public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Analyzer { +49 public class DependencyBundlingAnalyzer extends AbstractAnalyzer { 50 51 /** 52 * The Logger. @@ -66,505 +66,526 @@ 58 * A pattern for obtaining the first part of a filename. 59 */ 60 private static final Pattern STARTING_TEXT_PATTERN = Pattern.compile("^[a-zA-Z0-9]*"); -61 /** -62 * a flag indicating if this analyzer has run. This analyzer only runs once. -63 */ -64 private boolean analyzed = false; -65 //</editor-fold> -66 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> +61 +62 /** +63 * a flag indicating if this analyzer has run. This analyzer only runs once. +64 */ +65 private boolean analyzed = false; +66 67 /** -68 * The name of the analyzer. -69 */ -70 private static final String ANALYZER_NAME = "Dependency Bundling Analyzer"; -71 /** -72 * The phase that this analyzer is intended to run in. +68 * Returns a flag indicating if this analyzer has run. This analyzer only +69 * runs once. Note this is currently only used in the unit tests. +70 * +71 * @return a flag indicating if this analyzer has run. This analyzer only +72 * runs once 73 */ -74 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS; -75 -76 /** -77 * Returns the name of the analyzer. -78 * -79 * @return the name of the analyzer. -80 */ -81 @Override -82 public String getName() { -83 return ANALYZER_NAME; -84 } -85 -86 /** -87 * Returns the phase that the analyzer is intended to run in. -88 * -89 * @return the phase that the analyzer is intended to run in. -90 */ -91 @Override -92 public AnalysisPhase getAnalysisPhase() { -93 return ANALYSIS_PHASE; -94 } -95 //</editor-fold> -96 -97 /** -98 * Analyzes a set of dependencies. If they have been found to have the same -99 * base path and the same set of identifiers they are likely related. The -100 * related dependencies are bundled into a single reportable item. +74 protected boolean getAnalyzed() { +75 return analyzed; +76 } +77 +78 //</editor-fold> +79 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> +80 /** +81 * The name of the analyzer. +82 */ +83 private static final String ANALYZER_NAME = "Dependency Bundling Analyzer"; +84 /** +85 * The phase that this analyzer is intended to run in. +86 */ +87 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS; +88 +89 /** +90 * Returns the name of the analyzer. +91 * +92 * @return the name of the analyzer. +93 */ +94 @Override +95 public String getName() { +96 return ANALYZER_NAME; +97 } +98 +99 /** +100 * Returns the phase that the analyzer is intended to run in. 101 * -102 * @param ignore this analyzer ignores the dependency being analyzed -103 * @param engine the engine that is scanning the dependencies -104 * @throws AnalysisException is thrown if there is an error reading the JAR -105 * file. -106 */ -107 @Override -108 public void analyze(Dependency ignore, Engine engine) throws AnalysisException { -109 if (!analyzed) { -110 analyzed = true; -111 final Set<Dependency> dependenciesToRemove = new HashSet<Dependency>(); -112 final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator(); -113 //for (Dependency nextDependency : engine.getDependencies()) { -114 while (mainIterator.hasNext()) { -115 final Dependency dependency = mainIterator.next(); -116 if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) { -117 final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex()); -118 while (subIterator.hasNext()) { -119 final Dependency nextDependency = subIterator.next(); -120 Dependency main = null; -121 if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath()) -122 && !containedInWar(nextDependency.getFilePath())) { -123 if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) { -124 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -125 } else { -126 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -127 break; //since we merged into the next dependency - skip forward to the next in mainIterator -128 } -129 } else if (isShadedJar(dependency, nextDependency)) { -130 if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) { -131 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -132 nextDependency.getRelatedDependencies().remove(dependency); -133 break; -134 } else { -135 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -136 dependency.getRelatedDependencies().remove(nextDependency); -137 } -138 } else if (cpeIdentifiersMatch(dependency, nextDependency) -139 && hasSameBasePath(dependency, nextDependency) -140 && fileNameMatch(dependency, nextDependency)) { -141 if (isCore(dependency, nextDependency)) { -142 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -143 } else { -144 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -145 break; //since we merged into the next dependency - skip forward to the next in mainIterator -146 } -147 } else if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) { -148 if (main == dependency) { +102 * @return the phase that the analyzer is intended to run in. +103 */ +104 @Override +105 public AnalysisPhase getAnalysisPhase() { +106 return ANALYSIS_PHASE; +107 } +108 //</editor-fold> +109 +110 /** +111 * Does not support parallel processing as it only runs once and then +112 * operates on <em>all</em> dependencies. +113 * +114 * @return whether or not parallel processing is enabled +115 * @see #analyze(Dependency, Engine) +116 */ +117 @Override +118 public boolean supportsParallelProcessing() { +119 return false; +120 } +121 +122 /** +123 * Analyzes a set of dependencies. If they have been found to have the same +124 * base path and the same set of identifiers they are likely related. The +125 * related dependencies are bundled into a single reportable item. +126 * +127 * @param ignore this analyzer ignores the dependency being analyzed +128 * @param engine the engine that is scanning the dependencies +129 * @throws AnalysisException is thrown if there is an error reading the JAR +130 * file. +131 */ +132 @Override +133 public void analyze(Dependency ignore, Engine engine) throws AnalysisException { +134 if (!analyzed) { +135 analyzed = true; +136 final Set<Dependency> dependenciesToRemove = new HashSet<Dependency>(); +137 final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator(); +138 //for (Dependency nextDependency : engine.getDependencies()) { +139 while (mainIterator.hasNext()) { +140 final Dependency dependency = mainIterator.next(); +141 if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) { +142 final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex()); +143 while (subIterator.hasNext()) { +144 final Dependency nextDependency = subIterator.next(); +145 Dependency main = null; +146 if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath()) +147 && !containedInWar(nextDependency.getFilePath())) { +148 if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) { 149 mergeDependencies(dependency, nextDependency, dependenciesToRemove); 150 } else { 151 mergeDependencies(nextDependency, dependency, dependenciesToRemove); 152 break; //since we merged into the next dependency - skip forward to the next in mainIterator 153 } -154 } else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) { -155 if (main == dependency) { -156 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -157 } else { -158 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -159 break; //since we merged into the next dependency - skip forward to the next in mainIterator -160 } -161 } -162 } -163 } -164 } -165 //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions -166 // was difficult because of the inner iterator. -167 engine.getDependencies().removeAll(dependenciesToRemove); -168 } -169 } -170 -171 /** -172 * Adds the relatedDependency to the dependency's related dependencies. -173 * -174 * @param dependency the main dependency -175 * @param relatedDependency a collection of dependencies to be removed from -176 * the main analysis loop, this is the source of dependencies to remove -177 * @param dependenciesToRemove a collection of dependencies that will be -178 * removed from the main analysis loop, this function adds to this -179 * collection -180 */ -181 private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) { -182 dependency.addRelatedDependency(relatedDependency); -183 final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator(); -184 while (i.hasNext()) { -185 dependency.addRelatedDependency(i.next()); -186 i.remove(); -187 } -188 if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) { -189 dependency.addAllProjectReferences(relatedDependency.getProjectReferences()); -190 } -191 dependenciesToRemove.add(relatedDependency); -192 } -193 -194 /** -195 * Attempts to trim a maven repo to a common base path. This is typically -196 * [drive]\[repo_location]\repository\[path1]\[path2]. -197 * -198 * @param path the path to trim -199 * @return a string representing the base path. -200 */ -201 private String getBaseRepoPath(final String path) { -202 int pos = path.indexOf("repository" + File.separator) + 11; -203 if (pos < 0) { -204 return path; -205 } -206 int tmp = path.indexOf(File.separator, pos); -207 if (tmp <= 0) { -208 return path; -209 } -210 if (tmp > 0) { -211 pos = tmp + 1; +154 } else if (isShadedJar(dependency, nextDependency)) { +155 if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) { +156 mergeDependencies(nextDependency, dependency, dependenciesToRemove); +157 nextDependency.getRelatedDependencies().remove(dependency); +158 break; +159 } else { +160 mergeDependencies(dependency, nextDependency, dependenciesToRemove); +161 dependency.getRelatedDependencies().remove(nextDependency); +162 } +163 } else if (cpeIdentifiersMatch(dependency, nextDependency) +164 && hasSameBasePath(dependency, nextDependency) +165 && fileNameMatch(dependency, nextDependency)) { +166 if (isCore(dependency, nextDependency)) { +167 mergeDependencies(dependency, nextDependency, dependenciesToRemove); +168 } else { +169 mergeDependencies(nextDependency, dependency, dependenciesToRemove); +170 break; //since we merged into the next dependency - skip forward to the next in mainIterator +171 } +172 } else if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) { +173 if (main == dependency) { +174 mergeDependencies(dependency, nextDependency, dependenciesToRemove); +175 } else { +176 mergeDependencies(nextDependency, dependency, dependenciesToRemove); +177 break; //since we merged into the next dependency - skip forward to the next in mainIterator +178 } +179 } else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) { +180 if (main == dependency) { +181 mergeDependencies(dependency, nextDependency, dependenciesToRemove); +182 } else { +183 mergeDependencies(nextDependency, dependency, dependenciesToRemove); +184 break; //since we merged into the next dependency - skip forward to the next in mainIterator +185 } +186 } +187 } +188 } +189 } +190 //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions +191 // was difficult because of the inner iterator. +192 engine.getDependencies().removeAll(dependenciesToRemove); +193 } +194 } +195 +196 /** +197 * Adds the relatedDependency to the dependency's related dependencies. +198 * +199 * @param dependency the main dependency +200 * @param relatedDependency a collection of dependencies to be removed from +201 * the main analysis loop, this is the source of dependencies to remove +202 * @param dependenciesToRemove a collection of dependencies that will be +203 * removed from the main analysis loop, this function adds to this +204 * collection +205 */ +206 private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) { +207 dependency.addRelatedDependency(relatedDependency); +208 final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator(); +209 while (i.hasNext()) { +210 dependency.addRelatedDependency(i.next()); +211 i.remove(); 212 } -213 tmp = path.indexOf(File.separator, pos); -214 if (tmp > 0) { -215 pos = tmp + 1; -216 } -217 return path.substring(0, pos); -218 } -219 -220 /** -221 * Returns true if the file names (and version if it exists) of the two -222 * dependencies are sufficiently similar. -223 * -224 * @param dependency1 a dependency2 to compare -225 * @param dependency2 a dependency2 to compare -226 * @return true if the identifiers in the two supplied dependencies are -227 * equal -228 */ -229 private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) { -230 if (dependency1 == null || dependency1.getFileName() == null -231 || dependency2 == null || dependency2.getFileName() == null) { -232 return false; -233 } -234 final String fileName1 = dependency1.getActualFile().getName(); -235 final String fileName2 = dependency2.getActualFile().getName(); -236 -237 //version check -238 final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1); -239 final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2); -240 if (version1 != null && version2 != null && !version1.equals(version2)) { -241 return false; -242 } -243 -244 //filename check -245 final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1); -246 final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2); -247 if (match1.find() && match2.find()) { -248 return match1.group().equals(match2.group()); -249 } -250 -251 return false; -252 } -253 -254 /** -255 * Returns true if the CPE identifiers in the two supplied dependencies are -256 * equal. -257 * -258 * @param dependency1 a dependency2 to compare -259 * @param dependency2 a dependency2 to compare -260 * @return true if the identifiers in the two supplied dependencies are -261 * equal -262 */ -263 private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) { -264 if (dependency1 == null || dependency1.getIdentifiers() == null -265 || dependency2 == null || dependency2.getIdentifiers() == null) { +213 if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) { +214 dependency.addAllProjectReferences(relatedDependency.getProjectReferences()); +215 } +216 dependenciesToRemove.add(relatedDependency); +217 } +218 +219 /** +220 * Attempts to trim a maven repo to a common base path. This is typically +221 * [drive]\[repo_location]\repository\[path1]\[path2]. +222 * +223 * @param path the path to trim +224 * @return a string representing the base path. +225 */ +226 private String getBaseRepoPath(final String path) { +227 int pos = path.indexOf("repository" + File.separator) + 11; +228 if (pos < 0) { +229 return path; +230 } +231 int tmp = path.indexOf(File.separator, pos); +232 if (tmp <= 0) { +233 return path; +234 } +235 if (tmp > 0) { +236 pos = tmp + 1; +237 } +238 tmp = path.indexOf(File.separator, pos); +239 if (tmp > 0) { +240 pos = tmp + 1; +241 } +242 return path.substring(0, pos); +243 } +244 +245 /** +246 * Returns true if the file names (and version if it exists) of the two +247 * dependencies are sufficiently similar. +248 * +249 * @param dependency1 a dependency2 to compare +250 * @param dependency2 a dependency2 to compare +251 * @return true if the identifiers in the two supplied dependencies are +252 * equal +253 */ +254 private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) { +255 if (dependency1 == null || dependency1.getFileName() == null +256 || dependency2 == null || dependency2.getFileName() == null) { +257 return false; +258 } +259 final String fileName1 = dependency1.getActualFile().getName(); +260 final String fileName2 = dependency2.getActualFile().getName(); +261 +262 //version check +263 final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1); +264 final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2); +265 if (version1 != null && version2 != null && !version1.equals(version2)) { 266 return false; 267 } -268 boolean matches = false; -269 int cpeCount1 = 0; -270 int cpeCount2 = 0; -271 for (Identifier i : dependency1.getIdentifiers()) { -272 if ("cpe".equals(i.getType())) { -273 cpeCount1 += 1; -274 } -275 } -276 for (Identifier i : dependency2.getIdentifiers()) { -277 if ("cpe".equals(i.getType())) { -278 cpeCount2 += 1; -279 } -280 } -281 if (cpeCount1 > 0 && cpeCount1 == cpeCount2) { -282 for (Identifier i : dependency1.getIdentifiers()) { -283 if ("cpe".equals(i.getType())) { -284 matches |= dependency2.getIdentifiers().contains(i); -285 if (!matches) { -286 break; -287 } -288 } -289 } -290 } -291 LOGGER.debug("IdentifiersMatch={} ({}, {})", matches, dependency1.getFileName(), dependency2.getFileName()); -292 return matches; -293 } -294 -295 /** -296 * Determines if the two dependencies have the same base path. -297 * -298 * @param dependency1 a Dependency object -299 * @param dependency2 a Dependency object -300 * @return true if the base paths of the dependencies are identical -301 */ -302 private boolean hasSameBasePath(Dependency dependency1, Dependency dependency2) { -303 if (dependency1 == null || dependency2 == null) { -304 return false; +268 +269 //filename check +270 final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1); +271 final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2); +272 if (match1.find() && match2.find()) { +273 return match1.group().equals(match2.group()); +274 } +275 +276 return false; +277 } +278 +279 /** +280 * Returns true if the CPE identifiers in the two supplied dependencies are +281 * equal. +282 * +283 * @param dependency1 a dependency2 to compare +284 * @param dependency2 a dependency2 to compare +285 * @return true if the identifiers in the two supplied dependencies are +286 * equal +287 */ +288 private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) { +289 if (dependency1 == null || dependency1.getIdentifiers() == null +290 || dependency2 == null || dependency2.getIdentifiers() == null) { +291 return false; +292 } +293 boolean matches = false; +294 int cpeCount1 = 0; +295 int cpeCount2 = 0; +296 for (Identifier i : dependency1.getIdentifiers()) { +297 if ("cpe".equals(i.getType())) { +298 cpeCount1 += 1; +299 } +300 } +301 for (Identifier i : dependency2.getIdentifiers()) { +302 if ("cpe".equals(i.getType())) { +303 cpeCount2 += 1; +304 } 305 } -306 final File lFile = new File(dependency1.getFilePath()); -307 String left = lFile.getParent(); -308 final File rFile = new File(dependency2.getFilePath()); -309 String right = rFile.getParent(); -310 if (left == null) { -311 return right == null; -312 } else if (right == null) { -313 return false; -314 } -315 if (left.equalsIgnoreCase(right)) { -316 return true; -317 } -318 -319 if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) { -320 left = getBaseRepoPath(left); -321 right = getBaseRepoPath(right); -322 } -323 if (left.equalsIgnoreCase(right)) { -324 return true; -325 } -326 //new code -327 for (Dependency child : dependency2.getRelatedDependencies()) { -328 if (hasSameBasePath(dependency1, child)) { -329 return true; -330 } -331 } -332 return false; -333 } -334 -335 /** -336 * Bundling Ruby gems that are identified from different .gemspec files but -337 * denote the same package path. This happens when Ruby bundler installs an -338 * application's dependencies by running "bundle install". -339 * -340 * @param dependency1 dependency to compare -341 * @param dependency2 dependency to compare -342 * @return true if the the dependencies being analyzed appear to be the -343 * same; otherwise false -344 */ -345 private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) { -346 if (dependency1 == null || dependency2 == null -347 || !dependency1.getFileName().endsWith(".gemspec") -348 || !dependency2.getFileName().endsWith(".gemspec") -349 || dependency1.getPackagePath() == null -350 || dependency2.getPackagePath() == null) { -351 return false; -352 } -353 if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) { -354 return true; -355 } -356 +306 if (cpeCount1 > 0 && cpeCount1 == cpeCount2) { +307 for (Identifier i : dependency1.getIdentifiers()) { +308 if ("cpe".equals(i.getType())) { +309 matches |= dependency2.getIdentifiers().contains(i); +310 if (!matches) { +311 break; +312 } +313 } +314 } +315 } +316 LOGGER.debug("IdentifiersMatch={} ({}, {})", matches, dependency1.getFileName(), dependency2.getFileName()); +317 return matches; +318 } +319 +320 /** +321 * Determines if the two dependencies have the same base path. +322 * +323 * @param dependency1 a Dependency object +324 * @param dependency2 a Dependency object +325 * @return true if the base paths of the dependencies are identical +326 */ +327 private boolean hasSameBasePath(Dependency dependency1, Dependency dependency2) { +328 if (dependency1 == null || dependency2 == null) { +329 return false; +330 } +331 final File lFile = new File(dependency1.getFilePath()); +332 String left = lFile.getParent(); +333 final File rFile = new File(dependency2.getFilePath()); +334 String right = rFile.getParent(); +335 if (left == null) { +336 return right == null; +337 } else if (right == null) { +338 return false; +339 } +340 if (left.equalsIgnoreCase(right)) { +341 return true; +342 } +343 +344 if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) { +345 left = getBaseRepoPath(left); +346 right = getBaseRepoPath(right); +347 } +348 if (left.equalsIgnoreCase(right)) { +349 return true; +350 } +351 //new code +352 for (Dependency child : dependency2.getRelatedDependencies()) { +353 if (hasSameBasePath(dependency1, child)) { +354 return true; +355 } +356 } 357 return false; 358 } 359 360 /** -361 * Ruby gems installed by "bundle install" can have zero or more *.gemspec -362 * files, all of which have the same packagePath and should be grouped. If -363 * one of these gemspec is from <parent>/specifications/*.gemspec, because -364 * it is a stub with fully resolved gem meta-data created by Ruby bundler, -365 * this dependency should be the main one. Otherwise, use dependency2 as -366 * main. -367 * -368 * This method returns null if any dependency is not from *.gemspec, or the -369 * two do not have the same packagePath. In this case, they should not be -370 * grouped. -371 * -372 * @param dependency1 dependency to compare -373 * @param dependency2 dependency to compare -374 * @return the main dependency; or null if a gemspec is not included in the -375 * analysis -376 */ -377 private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) { -378 if (isSameRubyGem(dependency1, dependency2)) { -379 final File lFile = dependency1.getActualFile(); -380 final File left = lFile.getParentFile(); -381 if (left != null && left.getName().equalsIgnoreCase("specifications")) { -382 return dependency1; -383 } -384 return dependency2; -385 } -386 return null; -387 } -388 -389 /** -390 * Bundling same swift dependencies with the same packagePath but identified -391 * by different analyzers. +361 * Bundling Ruby gems that are identified from different .gemspec files but +362 * denote the same package path. This happens when Ruby bundler installs an +363 * application's dependencies by running "bundle install". +364 * +365 * @param dependency1 dependency to compare +366 * @param dependency2 dependency to compare +367 * @return true if the the dependencies being analyzed appear to be the +368 * same; otherwise false +369 */ +370 private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) { +371 if (dependency1 == null || dependency2 == null +372 || !dependency1.getFileName().endsWith(".gemspec") +373 || !dependency2.getFileName().endsWith(".gemspec") +374 || dependency1.getPackagePath() == null +375 || dependency2.getPackagePath() == null) { +376 return false; +377 } +378 return dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath()); +379 } +380 +381 /** +382 * Ruby gems installed by "bundle install" can have zero or more *.gemspec +383 * files, all of which have the same packagePath and should be grouped. If +384 * one of these gemspec is from <parent>/specifications/*.gemspec, because +385 * it is a stub with fully resolved gem meta-data created by Ruby bundler, +386 * this dependency should be the main one. Otherwise, use dependency2 as +387 * main. +388 * +389 * This method returns null if any dependency is not from *.gemspec, or the +390 * two do not have the same packagePath. In this case, they should not be +391 * grouped. 392 * -393 * @param dependency1 dependency to test -394 * @param dependency2 dependency to test -395 * @return <code>true</code> if the dependencies appear to be the same; -396 * otherwise <code>false</code> +393 * @param dependency1 dependency to compare +394 * @param dependency2 dependency to compare +395 * @return the main dependency; or null if a gemspec is not included in the +396 * analysis 397 */ -398 private boolean isSameSwiftPackage(Dependency dependency1, Dependency dependency2) { -399 if (dependency1 == null || dependency2 == null -400 || (!dependency1.getFileName().endsWith(".podspec") -401 && !dependency1.getFileName().equals("Package.swift")) -402 || (!dependency2.getFileName().endsWith(".podspec") -403 && !dependency2.getFileName().equals("Package.swift")) -404 || dependency1.getPackagePath() == null -405 || dependency2.getPackagePath() == null) { -406 return false; -407 } -408 if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) { -409 return true; -410 } -411 return false; -412 } -413 -414 /** -415 * Determines which of the swift dependencies should be considered the -416 * primary. -417 * -418 * @param dependency1 the first swift dependency to compare -419 * @param dependency2 the second swift dependency to compare -420 * @return the primary swift dependency -421 */ -422 private Dependency getMainSwiftDependency(Dependency dependency1, Dependency dependency2) { -423 if (isSameSwiftPackage(dependency1, dependency2)) { -424 if (dependency1.getFileName().endsWith(".podspec")) { -425 return dependency1; -426 } -427 return dependency2; +398 private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) { +399 if (isSameRubyGem(dependency1, dependency2)) { +400 final File lFile = dependency1.getActualFile(); +401 final File left = lFile.getParentFile(); +402 if (left != null && left.getName().equalsIgnoreCase("specifications")) { +403 return dependency1; +404 } +405 return dependency2; +406 } +407 return null; +408 } +409 +410 /** +411 * Bundling same swift dependencies with the same packagePath but identified +412 * by different analyzers. +413 * +414 * @param dependency1 dependency to test +415 * @param dependency2 dependency to test +416 * @return <code>true</code> if the dependencies appear to be the same; +417 * otherwise <code>false</code> +418 */ +419 private boolean isSameSwiftPackage(Dependency dependency1, Dependency dependency2) { +420 if (dependency1 == null || dependency2 == null +421 || (!dependency1.getFileName().endsWith(".podspec") +422 && !dependency1.getFileName().equals("Package.swift")) +423 || (!dependency2.getFileName().endsWith(".podspec") +424 && !dependency2.getFileName().equals("Package.swift")) +425 || dependency1.getPackagePath() == null +426 || dependency2.getPackagePath() == null) { +427 return false; 428 } -429 return null; +429 return dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath()); 430 } 431 432 /** -433 * This is likely a very broken attempt at determining if the 'left' -434 * dependency is the 'core' library in comparison to the 'right' library. +433 * Determines which of the swift dependencies should be considered the +434 * primary. 435 * -436 * @param left the dependency to test -437 * @param right the dependency to test against -438 * @return a boolean indicating whether or not the left dependency should be -439 * considered the "core" version. -440 */ -441 boolean isCore(Dependency left, Dependency right) { -442 final String leftName = left.getFileName().toLowerCase(); -443 final String rightName = right.getFileName().toLowerCase(); -444 -445 final boolean returnVal; -446 if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") -447 || rightName.contains("core") && !leftName.contains("core") -448 || rightName.contains("kernel") && !leftName.contains("kernel")) { -449 returnVal = false; -450 } else if (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") -451 || !rightName.contains("core") && leftName.contains("core") -452 || !rightName.contains("kernel") && leftName.contains("kernel")) { -453 returnVal = true; -454 // } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) { -455 // returnVal = true; -456 // } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) { -457 // returnVal = false; -458 } else { -459 /* -460 * considered splitting the names up and comparing the components, -461 * but decided that the file name length should be sufficient as the -462 * "core" component, if this follows a normal naming protocol should -463 * be shorter: -464 * axis2-saaj-1.4.1.jar -465 * axis2-1.4.1.jar <----- -466 * axis2-kernel-1.4.1.jar -467 */ -468 returnVal = leftName.length() <= rightName.length(); -469 } -470 LOGGER.debug("IsCore={} ({}, {})", returnVal, left.getFileName(), right.getFileName()); -471 return returnVal; -472 } -473 -474 /** -475 * Compares the SHA1 hashes of two dependencies to determine if they are -476 * equal. -477 * -478 * @param dependency1 a dependency object to compare -479 * @param dependency2 a dependency object to compare -480 * @return true if the sha1 hashes of the two dependencies match; otherwise -481 * false -482 */ -483 private boolean hashesMatch(Dependency dependency1, Dependency dependency2) { -484 if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) { -485 return false; -486 } -487 return dependency1.getSha1sum().equals(dependency2.getSha1sum()); -488 } -489 -490 /** -491 * Determines if the jar is shaded and the created pom.xml identified the -492 * same CPE as the jar - if so, the pom.xml dependency should be removed. -493 * -494 * @param dependency a dependency to check -495 * @param nextDependency another dependency to check -496 * @return true if on of the dependencies is a pom.xml and the identifiers -497 * between the two collections match; otherwise false -498 */ -499 private boolean isShadedJar(Dependency dependency, Dependency nextDependency) { -500 final String mainName = dependency.getFileName().toLowerCase(); -501 final String nextName = nextDependency.getFileName().toLowerCase(); -502 if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) { -503 return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers()); -504 } else if (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) { -505 return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers()); -506 } -507 return false; -508 } -509 -510 /** -511 * Determines which path is shortest; if path lengths are equal then we use -512 * compareTo of the string method to determine if the first path is smaller. -513 * -514 * @param left the first path to compare -515 * @param right the second path to compare -516 * @return <code>true</code> if the leftPath is the shortest; otherwise -517 * <code>false</code> -518 */ -519 protected boolean firstPathIsShortest(String left, String right) { -520 final String leftPath = left.replace('\\', '/'); -521 final String rightPath = right.replace('\\', '/'); -522 -523 final int leftCount = countChar(leftPath, '/'); -524 final int rightCount = countChar(rightPath, '/'); -525 if (leftCount == rightCount) { -526 return leftPath.compareTo(rightPath) <= 0; -527 } else { -528 return leftCount < rightCount; -529 } -530 } -531 -532 /** -533 * Counts the number of times the character is present in the string. -534 * -535 * @param string the string to count the characters in -536 * @param c the character to count -537 * @return the number of times the character is present in the string -538 */ -539 private int countChar(String string, char c) { -540 int count = 0; -541 final int max = string.length(); -542 for (int i = 0; i < max; i++) { -543 if (c == string.charAt(i)) { -544 count++; -545 } -546 } -547 return count; -548 } -549 -550 /** -551 * Checks if the given file path is contained within a war or ear file. -552 * -553 * @param filePath the file path to check -554 * @return true if the path contains '.war\' or '.ear\'. -555 */ -556 private boolean containedInWar(String filePath) { -557 return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*"); -558 } -559 } +436 * @param dependency1 the first swift dependency to compare +437 * @param dependency2 the second swift dependency to compare +438 * @return the primary swift dependency +439 */ +440 private Dependency getMainSwiftDependency(Dependency dependency1, Dependency dependency2) { +441 if (isSameSwiftPackage(dependency1, dependency2)) { +442 if (dependency1.getFileName().endsWith(".podspec")) { +443 return dependency1; +444 } +445 return dependency2; +446 } +447 return null; +448 } +449 +450 /** +451 * This is likely a very broken attempt at determining if the 'left' +452 * dependency is the 'core' library in comparison to the 'right' library. +453 * +454 * @param left the dependency to test +455 * @param right the dependency to test against +456 * @return a boolean indicating whether or not the left dependency should be +457 * considered the "core" version. +458 */ +459 boolean isCore(Dependency left, Dependency right) { +460 final String leftName = left.getFileName().toLowerCase(); +461 final String rightName = right.getFileName().toLowerCase(); +462 +463 final boolean returnVal; +464 if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") +465 || rightName.contains("core") && !leftName.contains("core") +466 || rightName.contains("kernel") && !leftName.contains("kernel")) { +467 returnVal = false; +468 } else if (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") +469 || !rightName.contains("core") && leftName.contains("core") +470 || !rightName.contains("kernel") && leftName.contains("kernel")) { +471 returnVal = true; +472 // } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) { +473 // returnVal = true; +474 // } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) { +475 // returnVal = false; +476 } else { +477 /* +478 * considered splitting the names up and comparing the components, +479 * but decided that the file name length should be sufficient as the +480 * "core" component, if this follows a normal naming protocol should +481 * be shorter: +482 * axis2-saaj-1.4.1.jar +483 * axis2-1.4.1.jar <----- +484 * axis2-kernel-1.4.1.jar +485 */ +486 returnVal = leftName.length() <= rightName.length(); +487 } +488 LOGGER.debug("IsCore={} ({}, {})", returnVal, left.getFileName(), right.getFileName()); +489 return returnVal; +490 } +491 +492 /** +493 * Compares the SHA1 hashes of two dependencies to determine if they are +494 * equal. +495 * +496 * @param dependency1 a dependency object to compare +497 * @param dependency2 a dependency object to compare +498 * @return true if the sha1 hashes of the two dependencies match; otherwise +499 * false +500 */ +501 private boolean hashesMatch(Dependency dependency1, Dependency dependency2) { +502 if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) { +503 return false; +504 } +505 return dependency1.getSha1sum().equals(dependency2.getSha1sum()); +506 } +507 +508 /** +509 * Determines if the jar is shaded and the created pom.xml identified the +510 * same CPE as the jar - if so, the pom.xml dependency should be removed. +511 * +512 * @param dependency a dependency to check +513 * @param nextDependency another dependency to check +514 * @return true if on of the dependencies is a pom.xml and the identifiers +515 * between the two collections match; otherwise false +516 */ +517 private boolean isShadedJar(Dependency dependency, Dependency nextDependency) { +518 final String mainName = dependency.getFileName().toLowerCase(); +519 final String nextName = nextDependency.getFileName().toLowerCase(); +520 if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) { +521 return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers()); +522 } else if (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) { +523 return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers()); +524 } +525 return false; +526 } +527 +528 /** +529 * Determines which path is shortest; if path lengths are equal then we use +530 * compareTo of the string method to determine if the first path is smaller. +531 * +532 * @param left the first path to compare +533 * @param right the second path to compare +534 * @return <code>true</code> if the leftPath is the shortest; otherwise +535 * <code>false</code> +536 */ +537 protected boolean firstPathIsShortest(String left, String right) { +538 if (left.contains("dctemp")) { +539 return false; +540 } +541 final String leftPath = left.replace('\\', '/'); +542 final String rightPath = right.replace('\\', '/'); +543 +544 final int leftCount = countChar(leftPath, '/'); +545 final int rightCount = countChar(rightPath, '/'); +546 if (leftCount == rightCount) { +547 return leftPath.compareTo(rightPath) <= 0; +548 } else { +549 return leftCount < rightCount; +550 } +551 } +552 +553 /** +554 * Counts the number of times the character is present in the string. +555 * +556 * @param string the string to count the characters in +557 * @param c the character to count +558 * @return the number of times the character is present in the string +559 */ +560 private int countChar(String string, char c) { +561 int count = 0; +562 final int max = string.length(); +563 for (int i = 0; i < max; i++) { +564 if (c == string.charAt(i)) { +565 count++; +566 } +567 } +568 return count; +569 } +570 +571 /** +572 * Checks if the given file path is contained within a war or ear file. +573 * +574 * @param filePath the file path to check +575 * @return true if the path contains '.war\' or '.ear\'. +576 */ +577 private boolean containedInWar(String filePath) { +578 return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*"); +579 } +580 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html index 5638da2e4..008e9935e 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html @@ -431,64 +431,66 @@ 423 String parentPath = dependency.getFilePath().toLowerCase(); 424 if (parentPath.contains(".jar")) { 425 parentPath = parentPath.substring(0, parentPath.indexOf(".jar") + 4); -426 final Dependency parent = findDependency(parentPath, engine.getDependencies()); -427 if (parent != null) { -428 boolean remove = false; -429 for (Identifier i : dependency.getIdentifiers()) { -430 if ("cpe".equals(i.getType())) { -431 final String trimmedCPE = trimCpeToVendor(i.getValue()); -432 for (Identifier parentId : parent.getIdentifiers()) { -433 if ("cpe".equals(parentId.getType()) && parentId.getValue().startsWith(trimmedCPE)) { -434 remove |= true; -435 } -436 } -437 } -438 if (!remove) { //we can escape early -439 return; -440 } -441 } -442 if (remove) { -443 engine.getDependencies().remove(dependency); -444 } -445 } -446 } -447 -448 } -449 } -450 -451 /** -452 * Retrieves a given dependency, based on a given path, from a list of dependencies. -453 * -454 * @param dependencyPath the path of the dependency to return -455 * @param dependencies the collection of dependencies to search -456 * @return the dependency object for the given path, otherwise null -457 */ -458 private Dependency findDependency(String dependencyPath, List<Dependency> dependencies) { -459 for (Dependency d : dependencies) { -460 if (d.getFilePath().equalsIgnoreCase(dependencyPath)) { -461 return d; -462 } -463 } -464 return null; -465 } -466 -467 /** -468 * Takes a full CPE and returns the CPE trimmed to include only vendor and product. -469 * -470 * @param value the CPE value to trim -471 * @return a CPE value that only includes the vendor and product -472 */ -473 private String trimCpeToVendor(String value) { -474 //cpe:/a:jruby:jruby:1.0.8 -475 final int pos1 = value.indexOf(':', 7); //right of vendor -476 final int pos2 = value.indexOf(':', pos1 + 1); //right of product -477 if (pos2 < 0) { -478 return value; -479 } else { -480 return value.substring(0, pos2); -481 } -482 } -483 } +426 final List<Dependency> dependencies = engine.getDependencies(); +427 synchronized (dependencies) { +428 final Dependency parent = findDependency(parentPath, dependencies); +429 if (parent != null) { +430 boolean remove = false; +431 for (Identifier i : dependency.getIdentifiers()) { +432 if ("cpe".equals(i.getType())) { +433 final String trimmedCPE = trimCpeToVendor(i.getValue()); +434 for (Identifier parentId : parent.getIdentifiers()) { +435 if ("cpe".equals(parentId.getType()) && parentId.getValue().startsWith(trimmedCPE)) { +436 remove |= true; +437 } +438 } +439 } +440 if (!remove) { //we can escape early +441 return; +442 } +443 } +444 if (remove) { +445 dependencies.remove(dependency); +446 } +447 } +448 } +449 } +450 } +451 } +452 +453 /** +454 * Retrieves a given dependency, based on a given path, from a list of dependencies. +455 * +456 * @param dependencyPath the path of the dependency to return +457 * @param dependencies the collection of dependencies to search +458 * @return the dependency object for the given path, otherwise null +459 */ +460 private Dependency findDependency(String dependencyPath, List<Dependency> dependencies) { +461 for (Dependency d : dependencies) { +462 if (d.getFilePath().equalsIgnoreCase(dependencyPath)) { +463 return d; +464 } +465 } +466 return null; +467 } +468 +469 /** +470 * Takes a full CPE and returns the CPE trimmed to include only vendor and product. +471 * +472 * @param value the CPE value to trim +473 * @return a CPE value that only includes the vendor and product +474 */ +475 private String trimCpeToVendor(String value) { +476 //cpe:/a:jruby:jruby:1.0.8 +477 final int pos1 = value.indexOf(':', 7); //right of vendor +478 final int pos2 = value.indexOf(':', pos1 + 1); //right of product +479 if (pos2 < 0) { +480 return value; +481 } else { +482 return value.substring(0, pos2); +483 } +484 } +485 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html index 026d40df0..75221ae85 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html @@ -42,7 +42,7 @@ 34 * 35 * @author Jeremy Long 36 */ -37 public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer { +37 public class FileNameAnalyzer extends AbstractAnalyzer { 38 39 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> 40 /** diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html index 0871b68a1..a9cf03d96 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html @@ -59,7 +59,7 @@ 51 * 52 * @author Jeremy Long 53 */ -54 public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { +54 public class HintAnalyzer extends AbstractAnalyzer { 55 56 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> 57 /** @@ -331,7 +331,7 @@ 323 try { 324 org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file); 325 } catch (IOException ex) { -326 throw new HintParseException("Unable to locate suppressions file in classpath", ex); +326 throw new HintParseException("Unable to locate hints file in classpath", ex); 327 } 328 } 329 } finally { diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html index 21f77be2a..206409b8c 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html @@ -34,15 +34,15 @@ 26 import java.io.OutputStream; 27 import java.io.Reader; 28 import java.util.ArrayList; -29 import java.util.Collections; -30 import java.util.Enumeration; -31 import java.util.HashMap; -32 import java.util.List; -33 import java.util.Map; -34 import java.util.Map.Entry; -35 import java.util.Properties; -36 import java.util.Set; -37 import java.util.StringTokenizer; +29 import java.util.Enumeration; +30 import java.util.HashMap; +31 import java.util.List; +32 import java.util.Map; +33 import java.util.Map.Entry; +34 import java.util.Properties; +35 import java.util.Set; +36 import java.util.StringTokenizer; +37 import java.util.concurrent.atomic.AtomicInteger; 38 import java.util.jar.Attributes; 39 import java.util.jar.JarEntry; 40 import java.util.jar.JarFile; @@ -84,7 +84,7 @@ 76 * The count of directories created during analysis. This is used for 77 * creating temporary directories. 78 */ -79 private static int dirCount = 0; +79 private static final AtomicInteger DIR_COUNT = new AtomicInteger(0); 80 /** 81 * The system independent newline character. 82 */ @@ -326,919 +326,921 @@ 318 pom.processProperties(pomProperties); 319 setPomEvidence(newDependency, pom, null); 320 engine.getDependencies().add(newDependency); -321 Collections.sort(engine.getDependencies()); -322 } else { -323 if (externalPom == null) { -324 pom = PomUtils.readPom(path, jar); -325 } else { -326 pom = PomUtils.readPom(externalPom); -327 } -328 if (pom != null) { -329 pom.processProperties(pomProperties); -330 foundSomething |= setPomEvidence(dependency, pom, classes); -331 } -332 } -333 } catch (AnalysisException ex) { -334 LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath()); -335 LOGGER.trace("", ex); -336 } -337 } -338 return foundSomething; -339 } -340 -341 /** -342 * Given a path to a pom.xml within a JarFile, this method attempts to load -343 * a sibling pom.properties if one exists. -344 * -345 * @param path the path to the pom.xml within the JarFile -346 * @param jar the JarFile to load the pom.properties from -347 * @return a Properties object or null if no pom.properties was found -348 * @throws IOException thrown if there is an exception reading the -349 * pom.properties -350 */ -351 private Properties retrievePomProperties(String path, final JarFile jar) throws IOException { -352 Properties pomProperties = null; -353 final String propPath = path.substring(0, path.length() - 7) + "pom.properies"; -354 final ZipEntry propEntry = jar.getEntry(propPath); -355 if (propEntry != null) { -356 Reader reader = null; -357 try { -358 reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8"); -359 pomProperties = new Properties(); -360 pomProperties.load(reader); -361 LOGGER.debug("Read pom.properties: {}", propPath); -362 } finally { -363 if (reader != null) { -364 try { -365 reader.close(); -366 } catch (IOException ex) { -367 LOGGER.trace("close error", ex); -368 } -369 } -370 } -371 } -372 return pomProperties; -373 } -374 -375 /** -376 * Searches a JarFile for pom.xml entries and returns a listing of these -377 * entries. -378 * -379 * @param jar the JarFile to search -380 * @return a list of pom.xml entries -381 * @throws IOException thrown if there is an exception reading a JarEntry -382 */ -383 private List<String> retrievePomListing(final JarFile jar) throws IOException { -384 final List<String> pomEntries = new ArrayList<String>(); -385 final Enumeration<JarEntry> entries = jar.entries(); -386 while (entries.hasMoreElements()) { -387 final JarEntry entry = entries.nextElement(); -388 final String entryName = (new File(entry.getName())).getName().toLowerCase(); -389 if (!entry.isDirectory() && "pom.xml".equals(entryName)) { -390 LOGGER.trace("POM Entry found: {}", entry.getName()); -391 pomEntries.add(entry.getName()); -392 } -393 } -394 return pomEntries; -395 } -396 -397 /** -398 * Retrieves the specified POM from a jar file and converts it to a Model. -399 * -400 * @param path the path to the pom.xml file within the jar file -401 * @param jar the jar file to extract the pom from -402 * @param dependency the dependency being analyzed -403 * @return returns the POM object -404 * @throws AnalysisException is thrown if there is an exception extracting -405 * or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object -406 */ -407 private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException { -408 InputStream input = null; -409 FileOutputStream fos = null; -410 final File tmpDir = getNextTempDirectory(); -411 final File file = new File(tmpDir, "pom.xml"); -412 try { -413 final ZipEntry entry = jar.getEntry(path); -414 if (entry == null) { -415 throw new AnalysisException(String.format("Pom (%s)does not exist in %s", path, jar.getName())); -416 } -417 input = jar.getInputStream(entry); -418 fos = new FileOutputStream(file); -419 IOUtils.copy(input, fos); -420 dependency.setActualFilePath(file.getAbsolutePath()); -421 } catch (IOException ex) { -422 LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath()); -423 LOGGER.error("", ex); -424 } finally { -425 closeStream(fos); -426 closeStream(input); -427 } -428 return PomUtils.readPom(file); -429 } -430 -431 /** -432 * Silently closes an input stream ignoring errors. -433 * -434 * @param stream an input stream to close -435 */ -436 private void closeStream(InputStream stream) { -437 if (stream != null) { -438 try { -439 stream.close(); -440 } catch (IOException ex) { -441 LOGGER.trace("", ex); -442 } -443 } -444 } -445 -446 /** -447 * Silently closes an output stream ignoring errors. -448 * -449 * @param stream an output stream to close -450 */ -451 private void closeStream(OutputStream stream) { -452 if (stream != null) { -453 try { -454 stream.close(); -455 } catch (IOException ex) { -456 LOGGER.trace("", ex); -457 } -458 } -459 } -460 -461 /** -462 * Sets evidence from the pom on the supplied dependency. -463 * -464 * @param dependency the dependency to set data on -465 * @param pom the information from the pom -466 * @param classes a collection of ClassNameInformation - containing data -467 * about the fully qualified class names within the JAR file being analyzed -468 * @return true if there was evidence within the pom that we could use; -469 * otherwise false -470 */ -471 public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) { -472 boolean foundSomething = false; -473 boolean addAsIdentifier = true; -474 if (pom == null) { -475 return foundSomething; -476 } -477 String groupid = pom.getGroupId(); -478 String parentGroupId = pom.getParentGroupId(); -479 String artifactid = pom.getArtifactId(); -480 String parentArtifactId = pom.getParentArtifactId(); -481 String version = pom.getVersion(); -482 String parentVersion = pom.getParentVersion(); -483 -484 if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) { -485 parentGroupId = null; -486 parentArtifactId = null; -487 parentVersion = null; -488 } -489 -490 if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) { -491 groupid = parentGroupId; -492 } -493 -494 final String originalGroupID = groupid; -495 if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) { -496 groupid = groupid.substring(4); -497 } -498 -499 if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) { -500 artifactid = parentArtifactId; -501 } -502 -503 final String originalArtifactID = artifactid; -504 if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) { -505 artifactid = artifactid.substring(4); -506 } -507 -508 if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) { -509 version = parentVersion; -510 } -511 -512 if (groupid != null && !groupid.isEmpty()) { -513 foundSomething = true; -514 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST); -515 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW); -516 addMatchingValues(classes, groupid, dependency.getVendorEvidence()); -517 addMatchingValues(classes, groupid, dependency.getProductEvidence()); -518 if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) { -519 dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM); -520 dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW); -521 addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence()); -522 addMatchingValues(classes, parentGroupId, dependency.getProductEvidence()); -523 } -524 } else { -525 addAsIdentifier = false; -526 } -527 -528 if (artifactid != null && !artifactid.isEmpty()) { -529 foundSomething = true; -530 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST); -531 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW); -532 addMatchingValues(classes, artifactid, dependency.getVendorEvidence()); -533 addMatchingValues(classes, artifactid, dependency.getProductEvidence()); -534 if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) { -535 dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM); -536 dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW); -537 addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence()); -538 addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence()); -539 } -540 } else { -541 addAsIdentifier = false; -542 } -543 -544 if (version != null && !version.isEmpty()) { -545 foundSomething = true; -546 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST); -547 if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) { -548 dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW); -549 } -550 } else { -551 addAsIdentifier = false; -552 } -553 -554 if (addAsIdentifier) { -555 dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH); -556 } -557 -558 // org name -559 final String org = pom.getOrganization(); -560 if (org != null && !org.isEmpty()) { -561 dependency.getVendorEvidence().addEvidence("pom", "organization name", org, Confidence.HIGH); -562 dependency.getProductEvidence().addEvidence("pom", "organization name", org, Confidence.LOW); -563 addMatchingValues(classes, org, dependency.getVendorEvidence()); -564 addMatchingValues(classes, org, dependency.getProductEvidence()); -565 } -566 //pom name -567 final String pomName = pom.getName(); -568 if (pomName -569 != null && !pomName.isEmpty()) { -570 foundSomething = true; -571 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); -572 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); -573 addMatchingValues(classes, pomName, dependency.getVendorEvidence()); -574 addMatchingValues(classes, pomName, dependency.getProductEvidence()); -575 } -576 -577 //Description -578 final String description = pom.getDescription(); -579 if (description != null && !description.isEmpty() && !description.startsWith("POM was created by")) { -580 foundSomething = true; -581 final String trimmedDescription = addDescription(dependency, description, "pom", "description"); -582 addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence()); -583 addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence()); -584 } -585 -586 final String projectURL = pom.getProjectURL(); -587 if (projectURL != null && !projectURL.trim().isEmpty()) { -588 dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST); -589 } -590 -591 extractLicense(pom, dependency); -592 return foundSomething; -593 } -594 -595 /** -596 * Analyzes the path information of the classes contained within the -597 * JarAnalyzer to try and determine possible vendor or product names. If any -598 * are found they are stored in the packageVendor and packageProduct -599 * hashSets. -600 * -601 * @param classNames a list of class names -602 * @param dependency a dependency to analyze -603 * @param addPackagesAsEvidence a flag indicating whether or not package -604 * names should be added as evidence. -605 */ -606 protected void analyzePackageNames(List<ClassNameInformation> classNames, -607 Dependency dependency, boolean addPackagesAsEvidence) { -608 final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>(); -609 final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>(); -610 analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers); -611 -612 final int classCount = classNames.size(); -613 final EvidenceCollection vendor = dependency.getVendorEvidence(); -614 final EvidenceCollection product = dependency.getProductEvidence(); -615 -616 for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) { -617 final float ratio = entry.getValue() / (float) classCount; -618 if (ratio > 0.5) { -619 //TODO remove weighting -620 vendor.addWeighting(entry.getKey()); -621 if (addPackagesAsEvidence && entry.getKey().length() > 1) { -622 vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); -623 } -624 } -625 } -626 for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) { -627 final float ratio = entry.getValue() / (float) classCount; -628 if (ratio > 0.5) { -629 product.addWeighting(entry.getKey()); -630 if (addPackagesAsEvidence && entry.getKey().length() > 1) { -631 product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); -632 } -633 } -634 } -635 } -636 -637 /** -638 * <p> -639 * Reads the manifest from the JAR file and collects the entries. Some -640 * vendorKey entries are:</p> -641 * <ul><li>Implementation Title</li> -642 * <li>Implementation Version</li> <li>Implementation Vendor</li> -643 * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle -644 * Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main -645 * Class</li> </ul> -646 * However, all but a handful of specific entries are read in. -647 * -648 * @param dependency A reference to the dependency -649 * @param classInformation a collection of class information -650 * @return whether evidence was identified parsing the manifest -651 * @throws IOException if there is an issue reading the JAR file -652 */ -653 protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException { -654 boolean foundSomething = false; -655 JarFile jar = null; -656 try { -657 jar = new JarFile(dependency.getActualFilePath()); -658 final Manifest manifest = jar.getManifest(); -659 if (manifest == null) { -660 if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar") -661 && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar") -662 && !dependency.getFileName().toLowerCase().endsWith("-src.jar") -663 && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) { -664 LOGGER.debug("Jar file '{}' does not contain a manifest.", -665 dependency.getFileName()); -666 } -667 return false; -668 } -669 final EvidenceCollection vendorEvidence = dependency.getVendorEvidence(); -670 final EvidenceCollection productEvidence = dependency.getProductEvidence(); -671 final EvidenceCollection versionEvidence = dependency.getVersionEvidence(); -672 String source = "Manifest"; -673 String specificationVersion = null; -674 boolean hasImplementationVersion = false; -675 Attributes atts = manifest.getMainAttributes(); -676 for (Entry<Object, Object> entry : atts.entrySet()) { -677 String key = entry.getKey().toString(); -678 String value = atts.getValue(key); -679 if (HTML_DETECTION_PATTERN.matcher(value).find()) { -680 value = Jsoup.parse(value).text(); -681 } -682 if (IGNORE_VALUES.contains(value)) { -683 continue; -684 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { -685 foundSomething = true; -686 productEvidence.addEvidence(source, key, value, Confidence.HIGH); -687 addMatchingValues(classInformation, value, productEvidence); -688 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { -689 hasImplementationVersion = true; -690 foundSomething = true; -691 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); -692 } else if ("specification-version".equalsIgnoreCase(key)) { -693 specificationVersion = value; -694 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { -695 foundSomething = true; -696 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH); -697 addMatchingValues(classInformation, value, vendorEvidence); -698 } else if (key.equalsIgnoreCase(IMPLEMENTATION_VENDOR_ID)) { -699 foundSomething = true; -700 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -701 addMatchingValues(classInformation, value, vendorEvidence); -702 } else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) { -703 foundSomething = true; -704 addDescription(dependency, value, "manifest", key); -705 addMatchingValues(classInformation, value, productEvidence); -706 } else if (key.equalsIgnoreCase(BUNDLE_NAME)) { -707 foundSomething = true; -708 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -709 addMatchingValues(classInformation, value, productEvidence); -710 // //the following caused false positives. -711 // } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) { -712 } else if (key.equalsIgnoreCase(BUNDLE_VERSION)) { -713 foundSomething = true; -714 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); -715 } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) { -716 continue; -717 //skipping main class as if this has important information to add it will be added during class name analysis... -718 } else { -719 key = key.toLowerCase(); -720 if (!IGNORE_KEYS.contains(key) -721 && !key.endsWith("jdk") -722 && !key.contains("lastmodified") -723 && !key.endsWith("package") -724 && !key.endsWith("classpath") -725 && !key.endsWith("class-path") -726 && !key.endsWith("-scm") //todo change this to a regex? -727 && !key.startsWith("scm-") -728 && !value.trim().startsWith("scm:") -729 && !isImportPackage(key, value) -730 && !isPackage(key, value)) { -731 foundSomething = true; -732 if (key.contains("version")) { -733 if (!key.contains("specification")) { -734 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -735 } -736 } else if ("build-id".equals(key)) { -737 int pos = value.indexOf('('); -738 if (pos >= 0) { -739 value = value.substring(0, pos - 1); -740 } -741 pos = value.indexOf('['); -742 if (pos >= 0) { -743 value = value.substring(0, pos - 1); -744 } -745 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -746 } else if (key.contains("title")) { -747 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -748 addMatchingValues(classInformation, value, productEvidence); -749 } else if (key.contains("vendor")) { -750 if (key.contains("specification")) { -751 vendorEvidence.addEvidence(source, key, value, Confidence.LOW); -752 } else { -753 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -754 addMatchingValues(classInformation, value, vendorEvidence); -755 } -756 } else if (key.contains("name")) { -757 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -758 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -759 addMatchingValues(classInformation, value, vendorEvidence); -760 addMatchingValues(classInformation, value, productEvidence); -761 } else if (key.contains("license")) { -762 addLicense(dependency, value); -763 } else if (key.contains("description")) { -764 addDescription(dependency, value, "manifest", key); -765 } else { -766 productEvidence.addEvidence(source, key, value, Confidence.LOW); -767 vendorEvidence.addEvidence(source, key, value, Confidence.LOW); -768 addMatchingValues(classInformation, value, vendorEvidence); -769 addMatchingValues(classInformation, value, productEvidence); -770 if (value.matches(".*\\d.*")) { -771 final StringTokenizer tokenizer = new StringTokenizer(value, " "); -772 while (tokenizer.hasMoreElements()) { -773 final String s = tokenizer.nextToken(); -774 if (s.matches("^[0-9.]+$")) { -775 versionEvidence.addEvidence(source, key, s, Confidence.LOW); -776 } -777 } -778 } -779 } -780 } -781 } -782 } -783 for (Map.Entry<String, Attributes> item : manifest.getEntries().entrySet()) { -784 final String name = item.getKey(); -785 source = "manifest: " + name; -786 atts = item.getValue(); -787 for (Entry<Object, Object> entry : atts.entrySet()) { -788 final String key = entry.getKey().toString(); -789 final String value = atts.getValue(key); -790 if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { -791 foundSomething = true; -792 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -793 addMatchingValues(classInformation, value, productEvidence); -794 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { -795 foundSomething = true; -796 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -797 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { -798 foundSomething = true; -799 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -800 addMatchingValues(classInformation, value, vendorEvidence); -801 } else if (key.equalsIgnoreCase(Attributes.Name.SPECIFICATION_TITLE.toString())) { -802 foundSomething = true; -803 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -804 addMatchingValues(classInformation, value, productEvidence); -805 } -806 } -807 } -808 if (specificationVersion != null && !hasImplementationVersion) { -809 foundSomething = true; -810 versionEvidence.addEvidence(source, "specification-version", specificationVersion, Confidence.HIGH); -811 } -812 } finally { -813 if (jar != null) { -814 jar.close(); -815 } -816 } -817 return foundSomething; -818 } -819 -820 /** -821 * Adds a description to the given dependency. If the description contains -822 * one of the following strings beyond 100 characters, then the description -823 * used will be trimmed to that position: -824 * <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses -825 * "</li></ul> -826 * -827 * @param dependency a dependency -828 * @param description the description -829 * @param source the source of the evidence -830 * @param key the "name" of the evidence -831 * @return if the description is trimmed, the trimmed version is returned; -832 * otherwise the original description is returned -833 */ -834 public static String addDescription(Dependency dependency, String description, String source, String key) { -835 if (dependency.getDescription() == null) { -836 dependency.setDescription(description); -837 } -838 String desc; -839 if (HTML_DETECTION_PATTERN.matcher(description).find()) { -840 desc = Jsoup.parse(description).text(); -841 } else { -842 desc = description; -843 } -844 dependency.setDescription(desc); -845 if (desc.length() > 100) { -846 desc = desc.replaceAll("\\s\\s+", " "); -847 final int posSuchAs = desc.toLowerCase().indexOf("such as ", 100); -848 final int posLike = desc.toLowerCase().indexOf("like ", 100); -849 final int posWillUse = desc.toLowerCase().indexOf("will use ", 100); -850 final int posUses = desc.toLowerCase().indexOf(" uses ", 100); -851 int pos = -1; -852 pos = Math.max(pos, posSuchAs); -853 if (pos >= 0 && posLike >= 0) { -854 pos = Math.min(pos, posLike); -855 } else { -856 pos = Math.max(pos, posLike); -857 } -858 if (pos >= 0 && posWillUse >= 0) { -859 pos = Math.min(pos, posWillUse); -860 } else { -861 pos = Math.max(pos, posWillUse); -862 } -863 if (pos >= 0 && posUses >= 0) { -864 pos = Math.min(pos, posUses); -865 } else { -866 pos = Math.max(pos, posUses); -867 } -868 -869 if (pos > 0) { -870 desc = desc.substring(0, pos) + "..."; -871 } -872 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW); -873 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW); -874 } else { -875 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.MEDIUM); -876 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.MEDIUM); -877 } -878 return desc; -879 } -880 -881 /** -882 * Adds a license to the given dependency. -883 * -884 * @param d a dependency -885 * @param license the license -886 */ -887 private void addLicense(Dependency d, String license) { -888 if (d.getLicense() == null) { -889 d.setLicense(license); -890 } else if (!d.getLicense().contains(license)) { -891 d.setLicense(d.getLicense() + NEWLINE + license); -892 } -893 } -894 -895 /** -896 * The parent directory for the individual directories per archive. -897 */ -898 private File tempFileLocation = null; -899 -900 /** -901 * Initializes the JarAnalyzer. -902 * -903 * @throws InitializationException is thrown if there is an exception -904 * creating a temporary directory -905 */ -906 @Override -907 public void initializeFileTypeAnalyzer() throws InitializationException { -908 try { -909 final File baseDir = Settings.getTempDirectory(); -910 tempFileLocation = File.createTempFile("check", "tmp", baseDir); -911 if (!tempFileLocation.delete()) { -912 final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath()); -913 setEnabled(false); -914 throw new InitializationException(msg); -915 } -916 if (!tempFileLocation.mkdirs()) { -917 final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath()); -918 setEnabled(false); -919 throw new InitializationException(msg); -920 } -921 } catch (IOException ex) { -922 setEnabled(false); -923 throw new InitializationException("Unable to create a temporary file", ex); -924 } -925 } -926 -927 /** -928 * Deletes any files extracted from the JAR during analysis. -929 */ -930 @Override -931 public void close() { -932 if (tempFileLocation != null && tempFileLocation.exists()) { -933 LOGGER.debug("Attempting to delete temporary files"); -934 final boolean success = FileUtils.delete(tempFileLocation); -935 if (!success) { -936 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); -937 } -938 } -939 } -940 -941 /** -942 * Determines if the key value pair from the manifest is for an "import" -943 * type entry for package names. -944 * -945 * @param key the key from the manifest -946 * @param value the value from the manifest -947 * @return true or false depending on if it is believed the entry is an -948 * "import" entry -949 */ -950 private boolean isImportPackage(String key, String value) { -951 final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$"); -952 final boolean matches = packageRx.matcher(value).matches(); -953 return matches && (key.contains("import") || key.contains("include") || value.length() > 10); -954 } -955 -956 /** -957 * Cycles through an enumeration of JarEntries, contained within the -958 * dependency, and returns a list of the class names. This does not include -959 * core Java package names (i.e. java.* or javax.*). -960 * -961 * @param dependency the dependency being analyzed -962 * @return an list of fully qualified class names -963 */ -964 private List<ClassNameInformation> collectClassNames(Dependency dependency) { -965 final List<ClassNameInformation> classNames = new ArrayList<ClassNameInformation>(); -966 JarFile jar = null; -967 try { -968 jar = new JarFile(dependency.getActualFilePath()); -969 final Enumeration<JarEntry> entries = jar.entries(); -970 while (entries.hasMoreElements()) { -971 final JarEntry entry = entries.nextElement(); -972 final String name = entry.getName().toLowerCase(); -973 //no longer stripping "|com\\.sun" - there are some com.sun jar files with CVEs. -974 if (name.endsWith(".class") && !name.matches("^javax?\\..*$")) { -975 final ClassNameInformation className = new ClassNameInformation(name.substring(0, name.length() - 6)); -976 classNames.add(className); -977 } -978 } -979 } catch (IOException ex) { -980 LOGGER.warn("Unable to open jar file '{}'.", dependency.getFileName()); -981 LOGGER.debug("", ex); -982 } finally { -983 if (jar != null) { -984 try { -985 jar.close(); -986 } catch (IOException ex) { -987 LOGGER.trace("", ex); -988 } -989 } -990 } -991 return classNames; -992 } -993 -994 /** -995 * Cycles through the list of class names and places the package levels 0-3 -996 * into the provided maps for vendor and product. This is helpful when -997 * analyzing vendor/product as many times this is included in the package -998 * name. -999 * -1000 * @param classNames a list of class names -1001 * @param vendor HashMap of possible vendor names from package names (e.g. -1002 * owasp) -1003 * @param product HashMap of possible product names from package names (e.g. -1004 * dependencycheck) -1005 */ -1006 private void analyzeFullyQualifiedClassNames(List<ClassNameInformation> classNames, -1007 Map<String, Integer> vendor, Map<String, Integer> product) { -1008 for (ClassNameInformation entry : classNames) { -1009 final List<String> list = entry.getPackageStructure(); -1010 addEntry(vendor, list.get(0)); -1011 -1012 if (list.size() == 2) { -1013 addEntry(product, list.get(1)); -1014 } -1015 if (list.size() == 3) { -1016 addEntry(vendor, list.get(1)); -1017 addEntry(product, list.get(1)); -1018 addEntry(product, list.get(2)); -1019 } -1020 if (list.size() >= 4) { -1021 addEntry(vendor, list.get(1)); -1022 addEntry(vendor, list.get(2)); -1023 addEntry(product, list.get(1)); -1024 addEntry(product, list.get(2)); -1025 addEntry(product, list.get(3)); -1026 } -1027 } -1028 } -1029 -1030 /** -1031 * Adds an entry to the specified collection and sets the Integer (e.g. the -1032 * count) to 1. If the entry already exists in the collection then the -1033 * Integer is incremented by 1. -1034 * -1035 * @param collection a collection of strings and their occurrence count -1036 * @param key the key to add to the collection -1037 */ -1038 private void addEntry(Map<String, Integer> collection, String key) { -1039 if (collection.containsKey(key)) { -1040 collection.put(key, collection.get(key) + 1); -1041 } else { -1042 collection.put(key, 1); -1043 } -1044 } -1045 -1046 /** -1047 * Cycles through the collection of class name information to see if parts -1048 * of the package names are contained in the provided value. If found, it -1049 * will be added as the HIGHEST confidence evidence because we have more -1050 * then one source corroborating the value. -1051 * -1052 * @param classes a collection of class name information -1053 * @param value the value to check to see if it contains a package name -1054 * @param evidence the evidence collection to add new entries too -1055 */ -1056 private static void addMatchingValues(List<ClassNameInformation> classes, String value, EvidenceCollection evidence) { -1057 if (value == null || value.isEmpty() || classes == null || classes.isEmpty()) { -1058 return; -1059 } -1060 final String text = value.toLowerCase(); -1061 for (ClassNameInformation cni : classes) { -1062 for (String key : cni.getPackageStructure()) { -1063 final Pattern p = Pattern.compile("\b" + key + "\b"); -1064 if (p.matcher(text).find()) { -1065 //if (text.contains(key)) { //note, package structure elements are already lowercase. -1066 evidence.addEvidence("jar", "package name", key, Confidence.HIGHEST); -1067 } -1068 } -1069 } -1070 } -1071 -1072 /** -1073 * Simple check to see if the attribute from a manifest is just a package -1074 * name. -1075 * -1076 * @param key the key of the value to check -1077 * @param value the value to check -1078 * @return true if the value looks like a java package name, otherwise false -1079 */ -1080 private boolean isPackage(String key, String value) { -1081 -1082 return !key.matches(".*(version|title|vendor|name|license|description).*") -1083 && value.matches("^([a-zA-Z_][a-zA-Z0-9_\\$]*(\\.[a-zA-Z_][a-zA-Z0-9_\\$]*)*)?$"); -1084 -1085 } +321 } else { +322 if (externalPom == null) { +323 pom = PomUtils.readPom(path, jar); +324 } else { +325 pom = PomUtils.readPom(externalPom); +326 } +327 if (pom != null) { +328 pom.processProperties(pomProperties); +329 foundSomething |= setPomEvidence(dependency, pom, classes); +330 } +331 } +332 } catch (AnalysisException ex) { +333 LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath()); +334 LOGGER.trace("", ex); +335 } +336 } +337 return foundSomething; +338 } +339 +340 /** +341 * Given a path to a pom.xml within a JarFile, this method attempts to load +342 * a sibling pom.properties if one exists. +343 * +344 * @param path the path to the pom.xml within the JarFile +345 * @param jar the JarFile to load the pom.properties from +346 * @return a Properties object or null if no pom.properties was found +347 * @throws IOException thrown if there is an exception reading the +348 * pom.properties +349 */ +350 private Properties retrievePomProperties(String path, final JarFile jar) throws IOException { +351 Properties pomProperties = null; +352 final String propPath = path.substring(0, path.length() - 7) + "pom.properies"; +353 final ZipEntry propEntry = jar.getEntry(propPath); +354 if (propEntry != null) { +355 Reader reader = null; +356 try { +357 reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8"); +358 pomProperties = new Properties(); +359 pomProperties.load(reader); +360 LOGGER.debug("Read pom.properties: {}", propPath); +361 } finally { +362 if (reader != null) { +363 try { +364 reader.close(); +365 } catch (IOException ex) { +366 LOGGER.trace("close error", ex); +367 } +368 } +369 } +370 } +371 return pomProperties; +372 } +373 +374 /** +375 * Searches a JarFile for pom.xml entries and returns a listing of these +376 * entries. +377 * +378 * @param jar the JarFile to search +379 * @return a list of pom.xml entries +380 * @throws IOException thrown if there is an exception reading a JarEntry +381 */ +382 private List<String> retrievePomListing(final JarFile jar) throws IOException { +383 final List<String> pomEntries = new ArrayList<String>(); +384 final Enumeration<JarEntry> entries = jar.entries(); +385 while (entries.hasMoreElements()) { +386 final JarEntry entry = entries.nextElement(); +387 final String entryName = (new File(entry.getName())).getName().toLowerCase(); +388 if (!entry.isDirectory() && "pom.xml".equals(entryName)) { +389 LOGGER.trace("POM Entry found: {}", entry.getName()); +390 pomEntries.add(entry.getName()); +391 } +392 } +393 return pomEntries; +394 } +395 +396 /** +397 * Retrieves the specified POM from a jar file and converts it to a Model. +398 * +399 * @param path the path to the pom.xml file within the jar file +400 * @param jar the jar file to extract the pom from +401 * @param dependency the dependency being analyzed +402 * @return returns the POM object +403 * @throws AnalysisException is thrown if there is an exception extracting +404 * or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object +405 */ +406 private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException { +407 InputStream input = null; +408 FileOutputStream fos = null; +409 final File tmpDir = getNextTempDirectory(); +410 final File file = new File(tmpDir, "pom.xml"); +411 try { +412 final ZipEntry entry = jar.getEntry(path); +413 if (entry == null) { +414 throw new AnalysisException(String.format("Pom (%s)does not exist in %s", path, jar.getName())); +415 } +416 input = jar.getInputStream(entry); +417 fos = new FileOutputStream(file); +418 IOUtils.copy(input, fos); +419 dependency.setActualFilePath(file.getAbsolutePath()); +420 } catch (IOException ex) { +421 LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath()); +422 LOGGER.error("", ex); +423 } finally { +424 closeStream(fos); +425 closeStream(input); +426 } +427 return PomUtils.readPom(file); +428 } +429 +430 /** +431 * Silently closes an input stream ignoring errors. +432 * +433 * @param stream an input stream to close +434 */ +435 private void closeStream(InputStream stream) { +436 if (stream != null) { +437 try { +438 stream.close(); +439 } catch (IOException ex) { +440 LOGGER.trace("", ex); +441 } +442 } +443 } +444 +445 /** +446 * Silently closes an output stream ignoring errors. +447 * +448 * @param stream an output stream to close +449 */ +450 private void closeStream(OutputStream stream) { +451 if (stream != null) { +452 try { +453 stream.close(); +454 } catch (IOException ex) { +455 LOGGER.trace("", ex); +456 } +457 } +458 } +459 +460 /** +461 * Sets evidence from the pom on the supplied dependency. +462 * +463 * @param dependency the dependency to set data on +464 * @param pom the information from the pom +465 * @param classes a collection of ClassNameInformation - containing data +466 * about the fully qualified class names within the JAR file being analyzed +467 * @return true if there was evidence within the pom that we could use; +468 * otherwise false +469 */ +470 public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) { +471 boolean foundSomething = false; +472 boolean addAsIdentifier = true; +473 if (pom == null) { +474 return foundSomething; +475 } +476 String groupid = pom.getGroupId(); +477 String parentGroupId = pom.getParentGroupId(); +478 String artifactid = pom.getArtifactId(); +479 String parentArtifactId = pom.getParentArtifactId(); +480 String version = pom.getVersion(); +481 String parentVersion = pom.getParentVersion(); +482 +483 if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) { +484 parentGroupId = null; +485 parentArtifactId = null; +486 parentVersion = null; +487 } +488 +489 if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) { +490 groupid = parentGroupId; +491 } +492 +493 final String originalGroupID = groupid; +494 if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) { +495 groupid = groupid.substring(4); +496 } +497 +498 if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) { +499 artifactid = parentArtifactId; +500 } +501 +502 final String originalArtifactID = artifactid; +503 if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) { +504 artifactid = artifactid.substring(4); +505 } +506 +507 if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) { +508 version = parentVersion; +509 } +510 +511 if (groupid != null && !groupid.isEmpty()) { +512 foundSomething = true; +513 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST); +514 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW); +515 addMatchingValues(classes, groupid, dependency.getVendorEvidence()); +516 addMatchingValues(classes, groupid, dependency.getProductEvidence()); +517 if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) { +518 dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM); +519 dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW); +520 addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence()); +521 addMatchingValues(classes, parentGroupId, dependency.getProductEvidence()); +522 } +523 } else { +524 addAsIdentifier = false; +525 } +526 +527 if (artifactid != null && !artifactid.isEmpty()) { +528 foundSomething = true; +529 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST); +530 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW); +531 addMatchingValues(classes, artifactid, dependency.getVendorEvidence()); +532 addMatchingValues(classes, artifactid, dependency.getProductEvidence()); +533 if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) { +534 dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM); +535 dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW); +536 addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence()); +537 addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence()); +538 } +539 } else { +540 addAsIdentifier = false; +541 } +542 +543 if (version != null && !version.isEmpty()) { +544 foundSomething = true; +545 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST); +546 if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) { +547 dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW); +548 } +549 } else { +550 addAsIdentifier = false; +551 } +552 +553 if (addAsIdentifier) { +554 dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH); +555 } +556 +557 // org name +558 final String org = pom.getOrganization(); +559 if (org != null && !org.isEmpty()) { +560 dependency.getVendorEvidence().addEvidence("pom", "organization name", org, Confidence.HIGH); +561 dependency.getProductEvidence().addEvidence("pom", "organization name", org, Confidence.LOW); +562 addMatchingValues(classes, org, dependency.getVendorEvidence()); +563 addMatchingValues(classes, org, dependency.getProductEvidence()); +564 } +565 //pom name +566 final String pomName = pom.getName(); +567 if (pomName +568 != null && !pomName.isEmpty()) { +569 foundSomething = true; +570 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); +571 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); +572 addMatchingValues(classes, pomName, dependency.getVendorEvidence()); +573 addMatchingValues(classes, pomName, dependency.getProductEvidence()); +574 } +575 +576 //Description +577 final String description = pom.getDescription(); +578 if (description != null && !description.isEmpty() && !description.startsWith("POM was created by")) { +579 foundSomething = true; +580 final String trimmedDescription = addDescription(dependency, description, "pom", "description"); +581 addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence()); +582 addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence()); +583 } +584 +585 final String projectURL = pom.getProjectURL(); +586 if (projectURL != null && !projectURL.trim().isEmpty()) { +587 dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST); +588 } +589 +590 extractLicense(pom, dependency); +591 return foundSomething; +592 } +593 +594 /** +595 * Analyzes the path information of the classes contained within the +596 * JarAnalyzer to try and determine possible vendor or product names. If any +597 * are found they are stored in the packageVendor and packageProduct +598 * hashSets. +599 * +600 * @param classNames a list of class names +601 * @param dependency a dependency to analyze +602 * @param addPackagesAsEvidence a flag indicating whether or not package +603 * names should be added as evidence. +604 */ +605 protected void analyzePackageNames(List<ClassNameInformation> classNames, +606 Dependency dependency, boolean addPackagesAsEvidence) { +607 final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>(); +608 final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>(); +609 analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers); +610 +611 final int classCount = classNames.size(); +612 final EvidenceCollection vendor = dependency.getVendorEvidence(); +613 final EvidenceCollection product = dependency.getProductEvidence(); +614 +615 for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) { +616 final float ratio = entry.getValue() / (float) classCount; +617 if (ratio > 0.5) { +618 //TODO remove weighting +619 vendor.addWeighting(entry.getKey()); +620 if (addPackagesAsEvidence && entry.getKey().length() > 1) { +621 vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); +622 } +623 } +624 } +625 for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) { +626 final float ratio = entry.getValue() / (float) classCount; +627 if (ratio > 0.5) { +628 product.addWeighting(entry.getKey()); +629 if (addPackagesAsEvidence && entry.getKey().length() > 1) { +630 product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); +631 } +632 } +633 } +634 } +635 +636 /** +637 * <p> +638 * Reads the manifest from the JAR file and collects the entries. Some +639 * vendorKey entries are:</p> +640 * <ul><li>Implementation Title</li> +641 * <li>Implementation Version</li> <li>Implementation Vendor</li> +642 * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle +643 * Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main +644 * Class</li> </ul> +645 * However, all but a handful of specific entries are read in. +646 * +647 * @param dependency A reference to the dependency +648 * @param classInformation a collection of class information +649 * @return whether evidence was identified parsing the manifest +650 * @throws IOException if there is an issue reading the JAR file +651 */ +652 protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException { +653 boolean foundSomething = false; +654 JarFile jar = null; +655 try { +656 jar = new JarFile(dependency.getActualFilePath()); +657 final Manifest manifest = jar.getManifest(); +658 if (manifest == null) { +659 if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar") +660 && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar") +661 && !dependency.getFileName().toLowerCase().endsWith("-src.jar") +662 && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) { +663 LOGGER.debug("Jar file '{}' does not contain a manifest.", +664 dependency.getFileName()); +665 } +666 return false; +667 } +668 final EvidenceCollection vendorEvidence = dependency.getVendorEvidence(); +669 final EvidenceCollection productEvidence = dependency.getProductEvidence(); +670 final EvidenceCollection versionEvidence = dependency.getVersionEvidence(); +671 String source = "Manifest"; +672 String specificationVersion = null; +673 boolean hasImplementationVersion = false; +674 Attributes atts = manifest.getMainAttributes(); +675 for (Entry<Object, Object> entry : atts.entrySet()) { +676 String key = entry.getKey().toString(); +677 String value = atts.getValue(key); +678 if (HTML_DETECTION_PATTERN.matcher(value).find()) { +679 value = Jsoup.parse(value).text(); +680 } +681 if (IGNORE_VALUES.contains(value)) { +682 continue; +683 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { +684 foundSomething = true; +685 productEvidence.addEvidence(source, key, value, Confidence.HIGH); +686 addMatchingValues(classInformation, value, productEvidence); +687 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { +688 hasImplementationVersion = true; +689 foundSomething = true; +690 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); +691 } else if ("specification-version".equalsIgnoreCase(key)) { +692 specificationVersion = value; +693 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { +694 foundSomething = true; +695 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH); +696 addMatchingValues(classInformation, value, vendorEvidence); +697 } else if (key.equalsIgnoreCase(IMPLEMENTATION_VENDOR_ID)) { +698 foundSomething = true; +699 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +700 addMatchingValues(classInformation, value, vendorEvidence); +701 } else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) { +702 foundSomething = true; +703 addDescription(dependency, value, "manifest", key); +704 addMatchingValues(classInformation, value, productEvidence); +705 } else if (key.equalsIgnoreCase(BUNDLE_NAME)) { +706 foundSomething = true; +707 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +708 addMatchingValues(classInformation, value, productEvidence); +709 // //the following caused false positives. +710 // } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) { +711 } else if (key.equalsIgnoreCase(BUNDLE_VERSION)) { +712 foundSomething = true; +713 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); +714 } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) { +715 continue; +716 //skipping main class as if this has important information to add it will be added during class name analysis... +717 } else { +718 key = key.toLowerCase(); +719 if (!IGNORE_KEYS.contains(key) +720 && !key.endsWith("jdk") +721 && !key.contains("lastmodified") +722 && !key.endsWith("package") +723 && !key.endsWith("classpath") +724 && !key.endsWith("class-path") +725 && !key.endsWith("-scm") //todo change this to a regex? +726 && !key.startsWith("scm-") +727 && !value.trim().startsWith("scm:") +728 && !isImportPackage(key, value) +729 && !isPackage(key, value)) { +730 foundSomething = true; +731 if (key.contains("version")) { +732 if (!key.contains("specification")) { +733 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +734 } +735 } else if ("build-id".equals(key)) { +736 int pos = value.indexOf('('); +737 if (pos >= 0) { +738 value = value.substring(0, pos - 1); +739 } +740 pos = value.indexOf('['); +741 if (pos >= 0) { +742 value = value.substring(0, pos - 1); +743 } +744 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +745 } else if (key.contains("title")) { +746 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +747 addMatchingValues(classInformation, value, productEvidence); +748 } else if (key.contains("vendor")) { +749 if (key.contains("specification")) { +750 vendorEvidence.addEvidence(source, key, value, Confidence.LOW); +751 } else { +752 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +753 addMatchingValues(classInformation, value, vendorEvidence); +754 } +755 } else if (key.contains("name")) { +756 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +757 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +758 addMatchingValues(classInformation, value, vendorEvidence); +759 addMatchingValues(classInformation, value, productEvidence); +760 } else if (key.contains("license")) { +761 addLicense(dependency, value); +762 } else if (key.contains("description")) { +763 addDescription(dependency, value, "manifest", key); +764 } else { +765 productEvidence.addEvidence(source, key, value, Confidence.LOW); +766 vendorEvidence.addEvidence(source, key, value, Confidence.LOW); +767 addMatchingValues(classInformation, value, vendorEvidence); +768 addMatchingValues(classInformation, value, productEvidence); +769 if (value.matches(".*\\d.*")) { +770 final StringTokenizer tokenizer = new StringTokenizer(value, " "); +771 while (tokenizer.hasMoreElements()) { +772 final String s = tokenizer.nextToken(); +773 if (s.matches("^[0-9.]+$")) { +774 versionEvidence.addEvidence(source, key, s, Confidence.LOW); +775 } +776 } +777 } +778 } +779 } +780 } +781 } +782 for (Map.Entry<String, Attributes> item : manifest.getEntries().entrySet()) { +783 final String name = item.getKey(); +784 source = "manifest: " + name; +785 atts = item.getValue(); +786 for (Entry<Object, Object> entry : atts.entrySet()) { +787 final String key = entry.getKey().toString(); +788 final String value = atts.getValue(key); +789 if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { +790 foundSomething = true; +791 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +792 addMatchingValues(classInformation, value, productEvidence); +793 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { +794 foundSomething = true; +795 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +796 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { +797 foundSomething = true; +798 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +799 addMatchingValues(classInformation, value, vendorEvidence); +800 } else if (key.equalsIgnoreCase(Attributes.Name.SPECIFICATION_TITLE.toString())) { +801 foundSomething = true; +802 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +803 addMatchingValues(classInformation, value, productEvidence); +804 } +805 } +806 } +807 if (specificationVersion != null && !hasImplementationVersion) { +808 foundSomething = true; +809 versionEvidence.addEvidence(source, "specification-version", specificationVersion, Confidence.HIGH); +810 } +811 } finally { +812 if (jar != null) { +813 jar.close(); +814 } +815 } +816 return foundSomething; +817 } +818 +819 /** +820 * Adds a description to the given dependency. If the description contains +821 * one of the following strings beyond 100 characters, then the description +822 * used will be trimmed to that position: +823 * <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses +824 * "</li></ul> +825 * +826 * @param dependency a dependency +827 * @param description the description +828 * @param source the source of the evidence +829 * @param key the "name" of the evidence +830 * @return if the description is trimmed, the trimmed version is returned; +831 * otherwise the original description is returned +832 */ +833 public static String addDescription(Dependency dependency, String description, String source, String key) { +834 if (dependency.getDescription() == null) { +835 dependency.setDescription(description); +836 } +837 String desc; +838 if (HTML_DETECTION_PATTERN.matcher(description).find()) { +839 desc = Jsoup.parse(description).text(); +840 } else { +841 desc = description; +842 } +843 dependency.setDescription(desc); +844 if (desc.length() > 100) { +845 desc = desc.replaceAll("\\s\\s+", " "); +846 final int posSuchAs = desc.toLowerCase().indexOf("such as ", 100); +847 final int posLike = desc.toLowerCase().indexOf("like ", 100); +848 final int posWillUse = desc.toLowerCase().indexOf("will use ", 100); +849 final int posUses = desc.toLowerCase().indexOf(" uses ", 100); +850 int pos = -1; +851 pos = Math.max(pos, posSuchAs); +852 if (pos >= 0 && posLike >= 0) { +853 pos = Math.min(pos, posLike); +854 } else { +855 pos = Math.max(pos, posLike); +856 } +857 if (pos >= 0 && posWillUse >= 0) { +858 pos = Math.min(pos, posWillUse); +859 } else { +860 pos = Math.max(pos, posWillUse); +861 } +862 if (pos >= 0 && posUses >= 0) { +863 pos = Math.min(pos, posUses); +864 } else { +865 pos = Math.max(pos, posUses); +866 } +867 +868 if (pos > 0) { +869 desc = desc.substring(0, pos) + "..."; +870 } +871 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW); +872 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW); +873 } else { +874 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.MEDIUM); +875 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.MEDIUM); +876 } +877 return desc; +878 } +879 +880 /** +881 * Adds a license to the given dependency. +882 * +883 * @param d a dependency +884 * @param license the license +885 */ +886 private void addLicense(Dependency d, String license) { +887 if (d.getLicense() == null) { +888 d.setLicense(license); +889 } else if (!d.getLicense().contains(license)) { +890 d.setLicense(d.getLicense() + NEWLINE + license); +891 } +892 } +893 +894 /** +895 * The parent directory for the individual directories per archive. +896 */ +897 private File tempFileLocation = null; +898 +899 /** +900 * Initializes the JarAnalyzer. +901 * +902 * @throws InitializationException is thrown if there is an exception +903 * creating a temporary directory +904 */ +905 @Override +906 public void initializeFileTypeAnalyzer() throws InitializationException { +907 try { +908 final File baseDir = Settings.getTempDirectory(); +909 tempFileLocation = File.createTempFile("check", "tmp", baseDir); +910 if (!tempFileLocation.delete()) { +911 final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath()); +912 setEnabled(false); +913 throw new InitializationException(msg); +914 } +915 if (!tempFileLocation.mkdirs()) { +916 final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath()); +917 setEnabled(false); +918 throw new InitializationException(msg); +919 } +920 } catch (IOException ex) { +921 setEnabled(false); +922 throw new InitializationException("Unable to create a temporary file", ex); +923 } +924 } +925 +926 /** +927 * Deletes any files extracted from the JAR during analysis. +928 */ +929 @Override +930 public void close() { +931 if (tempFileLocation != null && tempFileLocation.exists()) { +932 LOGGER.debug("Attempting to delete temporary files"); +933 final boolean success = FileUtils.delete(tempFileLocation); +934 if (!success && tempFileLocation.exists()) { +935 final String[] l = tempFileLocation.list(); +936 if (l != null && l.length > 0) { +937 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); +938 } +939 } +940 } +941 } +942 +943 /** +944 * Determines if the key value pair from the manifest is for an "import" +945 * type entry for package names. +946 * +947 * @param key the key from the manifest +948 * @param value the value from the manifest +949 * @return true or false depending on if it is believed the entry is an +950 * "import" entry +951 */ +952 private boolean isImportPackage(String key, String value) { +953 final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$"); +954 final boolean matches = packageRx.matcher(value).matches(); +955 return matches && (key.contains("import") || key.contains("include") || value.length() > 10); +956 } +957 +958 /** +959 * Cycles through an enumeration of JarEntries, contained within the +960 * dependency, and returns a list of the class names. This does not include +961 * core Java package names (i.e. java.* or javax.*). +962 * +963 * @param dependency the dependency being analyzed +964 * @return an list of fully qualified class names +965 */ +966 private List<ClassNameInformation> collectClassNames(Dependency dependency) { +967 final List<ClassNameInformation> classNames = new ArrayList<ClassNameInformation>(); +968 JarFile jar = null; +969 try { +970 jar = new JarFile(dependency.getActualFilePath()); +971 final Enumeration<JarEntry> entries = jar.entries(); +972 while (entries.hasMoreElements()) { +973 final JarEntry entry = entries.nextElement(); +974 final String name = entry.getName().toLowerCase(); +975 //no longer stripping "|com\\.sun" - there are some com.sun jar files with CVEs. +976 if (name.endsWith(".class") && !name.matches("^javax?\\..*$")) { +977 final ClassNameInformation className = new ClassNameInformation(name.substring(0, name.length() - 6)); +978 classNames.add(className); +979 } +980 } +981 } catch (IOException ex) { +982 LOGGER.warn("Unable to open jar file '{}'.", dependency.getFileName()); +983 LOGGER.debug("", ex); +984 } finally { +985 if (jar != null) { +986 try { +987 jar.close(); +988 } catch (IOException ex) { +989 LOGGER.trace("", ex); +990 } +991 } +992 } +993 return classNames; +994 } +995 +996 /** +997 * Cycles through the list of class names and places the package levels 0-3 +998 * into the provided maps for vendor and product. This is helpful when +999 * analyzing vendor/product as many times this is included in the package +1000 * name. +1001 * +1002 * @param classNames a list of class names +1003 * @param vendor HashMap of possible vendor names from package names (e.g. +1004 * owasp) +1005 * @param product HashMap of possible product names from package names (e.g. +1006 * dependencycheck) +1007 */ +1008 private void analyzeFullyQualifiedClassNames(List<ClassNameInformation> classNames, +1009 Map<String, Integer> vendor, Map<String, Integer> product) { +1010 for (ClassNameInformation entry : classNames) { +1011 final List<String> list = entry.getPackageStructure(); +1012 addEntry(vendor, list.get(0)); +1013 +1014 if (list.size() == 2) { +1015 addEntry(product, list.get(1)); +1016 } +1017 if (list.size() == 3) { +1018 addEntry(vendor, list.get(1)); +1019 addEntry(product, list.get(1)); +1020 addEntry(product, list.get(2)); +1021 } +1022 if (list.size() >= 4) { +1023 addEntry(vendor, list.get(1)); +1024 addEntry(vendor, list.get(2)); +1025 addEntry(product, list.get(1)); +1026 addEntry(product, list.get(2)); +1027 addEntry(product, list.get(3)); +1028 } +1029 } +1030 } +1031 +1032 /** +1033 * Adds an entry to the specified collection and sets the Integer (e.g. the +1034 * count) to 1. If the entry already exists in the collection then the +1035 * Integer is incremented by 1. +1036 * +1037 * @param collection a collection of strings and their occurrence count +1038 * @param key the key to add to the collection +1039 */ +1040 private void addEntry(Map<String, Integer> collection, String key) { +1041 if (collection.containsKey(key)) { +1042 collection.put(key, collection.get(key) + 1); +1043 } else { +1044 collection.put(key, 1); +1045 } +1046 } +1047 +1048 /** +1049 * Cycles through the collection of class name information to see if parts +1050 * of the package names are contained in the provided value. If found, it +1051 * will be added as the HIGHEST confidence evidence because we have more +1052 * then one source corroborating the value. +1053 * +1054 * @param classes a collection of class name information +1055 * @param value the value to check to see if it contains a package name +1056 * @param evidence the evidence collection to add new entries too +1057 */ +1058 private static void addMatchingValues(List<ClassNameInformation> classes, String value, EvidenceCollection evidence) { +1059 if (value == null || value.isEmpty() || classes == null || classes.isEmpty()) { +1060 return; +1061 } +1062 final String text = value.toLowerCase(); +1063 for (ClassNameInformation cni : classes) { +1064 for (String key : cni.getPackageStructure()) { +1065 final Pattern p = Pattern.compile("\b" + key + "\b"); +1066 if (p.matcher(text).find()) { +1067 //if (text.contains(key)) { //note, package structure elements are already lowercase. +1068 evidence.addEvidence("jar", "package name", key, Confidence.HIGHEST); +1069 } +1070 } +1071 } +1072 } +1073 +1074 /** +1075 * Simple check to see if the attribute from a manifest is just a package +1076 * name. +1077 * +1078 * @param key the key of the value to check +1079 * @param value the value to check +1080 * @return true if the value looks like a java package name, otherwise false +1081 */ +1082 private boolean isPackage(String key, String value) { +1083 +1084 return !key.matches(".*(version|title|vendor|name|license|description).*") +1085 && value.matches("^([a-zA-Z_][a-zA-Z0-9_\\$]*(\\.[a-zA-Z_][a-zA-Z0-9_\\$]*)*)?$"); 1086 -1087 /** -1088 * Extracts the license information from the pom and adds it to the -1089 * dependency. -1090 * -1091 * @param pom the pom object -1092 * @param dependency the dependency to add license information too -1093 */ -1094 public static void extractLicense(Model pom, Dependency dependency) { -1095 //license -1096 if (pom.getLicenses() != null) { -1097 String license = null; -1098 for (License lic : pom.getLicenses()) { -1099 String tmp = null; -1100 if (lic.getName() != null) { -1101 tmp = lic.getName(); -1102 } -1103 if (lic.getUrl() != null) { -1104 if (tmp == null) { -1105 tmp = lic.getUrl(); -1106 } else { -1107 tmp += ": " + lic.getUrl(); -1108 } -1109 } -1110 if (tmp == null) { -1111 continue; -1112 } -1113 if (HTML_DETECTION_PATTERN.matcher(tmp).find()) { -1114 tmp = Jsoup.parse(tmp).text(); -1115 } -1116 if (license == null) { -1117 license = tmp; -1118 } else { -1119 license += "\n" + tmp; -1120 } -1121 } -1122 if (license != null) { -1123 dependency.setLicense(license); -1124 -1125 } -1126 } -1127 } -1128 -1129 /** -1130 * Stores information about a class name. -1131 */ -1132 protected static class ClassNameInformation { -1133 -1134 /** -1135 * <p> -1136 * Stores information about a given class name. This class will keep the -1137 * fully qualified class name and a list of the important parts of the -1138 * package structure. Up to the first four levels of the package -1139 * structure are stored, excluding a leading "org" or "com". -1140 * Example:</p> -1141 * <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer"); -1142 * System.out.println(obj.getName()); -1143 * for (String p : obj.getPackageStructure()) -1144 * System.out.println(p); -1145 * </code> -1146 * <p> -1147 * Would result in:</p> -1148 * <code>org.owasp.dependencycheck.analyzer.JarAnalyzer -1149 * owasp -1150 * dependencycheck -1151 * analyzer -1152 * jaranalyzer</code> -1153 * -1154 * @param className a fully qualified class name -1155 */ -1156 ClassNameInformation(String className) { -1157 name = className; -1158 if (name.contains("/")) { -1159 final String[] tmp = className.toLowerCase().split("/"); -1160 int start = 0; -1161 int end = 3; -1162 if ("com".equals(tmp[0]) || "org".equals(tmp[0])) { -1163 start = 1; -1164 end = 4; -1165 } -1166 if (tmp.length <= end) { -1167 end = tmp.length - 1; -1168 } -1169 for (int i = start; i <= end; i++) { -1170 packageStructure.add(tmp[i]); -1171 } -1172 } else { -1173 packageStructure.add(name); -1174 } -1175 } -1176 /** -1177 * The fully qualified class name. -1178 */ -1179 private String name; -1180 -1181 /** -1182 * Get the value of name -1183 * -1184 * @return the value of name -1185 */ -1186 public String getName() { -1187 return name; -1188 } -1189 -1190 /** -1191 * Set the value of name -1192 * -1193 * @param name new value of name -1194 */ -1195 public void setName(String name) { -1196 this.name = name; -1197 } -1198 /** -1199 * Up to the first four levels of the package structure, excluding a -1200 * leading "org" or "com". -1201 */ -1202 private final ArrayList<String> packageStructure = new ArrayList<String>(); -1203 -1204 /** -1205 * Get the value of packageStructure -1206 * -1207 * @return the value of packageStructure -1208 */ -1209 public ArrayList<String> getPackageStructure() { -1210 return packageStructure; -1211 } -1212 } -1213 -1214 /** -1215 * Retrieves the next temporary directory to extract an archive too. -1216 * -1217 * @return a directory -1218 * @throws AnalysisException thrown if unable to create temporary directory -1219 */ -1220 private File getNextTempDirectory() throws AnalysisException { -1221 dirCount += 1; -1222 final File directory = new File(tempFileLocation, String.valueOf(dirCount)); -1223 //getting an exception for some directories not being able to be created; might be because the directory already exists? -1224 if (directory.exists()) { -1225 return getNextTempDirectory(); -1226 } -1227 if (!directory.mkdirs()) { -1228 final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath()); -1229 throw new AnalysisException(msg); -1230 } -1231 return directory; -1232 } -1233 } +1087 } +1088 +1089 /** +1090 * Extracts the license information from the pom and adds it to the +1091 * dependency. +1092 * +1093 * @param pom the pom object +1094 * @param dependency the dependency to add license information too +1095 */ +1096 public static void extractLicense(Model pom, Dependency dependency) { +1097 //license +1098 if (pom.getLicenses() != null) { +1099 String license = null; +1100 for (License lic : pom.getLicenses()) { +1101 String tmp = null; +1102 if (lic.getName() != null) { +1103 tmp = lic.getName(); +1104 } +1105 if (lic.getUrl() != null) { +1106 if (tmp == null) { +1107 tmp = lic.getUrl(); +1108 } else { +1109 tmp += ": " + lic.getUrl(); +1110 } +1111 } +1112 if (tmp == null) { +1113 continue; +1114 } +1115 if (HTML_DETECTION_PATTERN.matcher(tmp).find()) { +1116 tmp = Jsoup.parse(tmp).text(); +1117 } +1118 if (license == null) { +1119 license = tmp; +1120 } else { +1121 license += "\n" + tmp; +1122 } +1123 } +1124 if (license != null) { +1125 dependency.setLicense(license); +1126 +1127 } +1128 } +1129 } +1130 +1131 /** +1132 * Stores information about a class name. +1133 */ +1134 protected static class ClassNameInformation { +1135 +1136 /** +1137 * <p> +1138 * Stores information about a given class name. This class will keep the +1139 * fully qualified class name and a list of the important parts of the +1140 * package structure. Up to the first four levels of the package +1141 * structure are stored, excluding a leading "org" or "com". +1142 * Example:</p> +1143 * <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer"); +1144 * System.out.println(obj.getName()); +1145 * for (String p : obj.getPackageStructure()) +1146 * System.out.println(p); +1147 * </code> +1148 * <p> +1149 * Would result in:</p> +1150 * <code>org.owasp.dependencycheck.analyzer.JarAnalyzer +1151 * owasp +1152 * dependencycheck +1153 * analyzer +1154 * jaranalyzer</code> +1155 * +1156 * @param className a fully qualified class name +1157 */ +1158 ClassNameInformation(String className) { +1159 name = className; +1160 if (name.contains("/")) { +1161 final String[] tmp = className.toLowerCase().split("/"); +1162 int start = 0; +1163 int end = 3; +1164 if ("com".equals(tmp[0]) || "org".equals(tmp[0])) { +1165 start = 1; +1166 end = 4; +1167 } +1168 if (tmp.length <= end) { +1169 end = tmp.length - 1; +1170 } +1171 for (int i = start; i <= end; i++) { +1172 packageStructure.add(tmp[i]); +1173 } +1174 } else { +1175 packageStructure.add(name); +1176 } +1177 } +1178 /** +1179 * The fully qualified class name. +1180 */ +1181 private String name; +1182 +1183 /** +1184 * Get the value of name +1185 * +1186 * @return the value of name +1187 */ +1188 public String getName() { +1189 return name; +1190 } +1191 +1192 /** +1193 * Set the value of name +1194 * +1195 * @param name new value of name +1196 */ +1197 public void setName(String name) { +1198 this.name = name; +1199 } +1200 /** +1201 * Up to the first four levels of the package structure, excluding a +1202 * leading "org" or "com". +1203 */ +1204 private final ArrayList<String> packageStructure = new ArrayList<String>(); +1205 +1206 /** +1207 * Get the value of packageStructure +1208 * +1209 * @return the value of packageStructure +1210 */ +1211 public ArrayList<String> getPackageStructure() { +1212 return packageStructure; +1213 } +1214 } +1215 +1216 /** +1217 * Retrieves the next temporary directory to extract an archive too. +1218 * +1219 * @return a directory +1220 * @throws AnalysisException thrown if unable to create temporary directory +1221 */ +1222 private File getNextTempDirectory() throws AnalysisException { +1223 final int dirCount = DIR_COUNT.incrementAndGet(); +1224 final File directory = new File(tempFileLocation, String.valueOf(dirCount)); +1225 //getting an exception for some directories not being able to be created; might be because the directory already exists? +1226 if (directory.exists()) { +1227 return getNextTempDirectory(); +1228 } +1229 if (!directory.mkdirs()) { +1230 final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath()); +1231 throw new AnalysisException(msg); +1232 } +1233 return directory; +1234 } +1235 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html index c2b44db91..3b6889c63 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html @@ -95,183 +95,200 @@ 87 */ 88 private static final String SUPPORTED_EXTENSIONS = "jar"; 89 -90 /** -91 * The Nexus Search to be set up for this analyzer. -92 */ -93 private NexusSearch searcher; -94 -95 /** -96 * Field indicating if the analyzer is enabled. -97 */ -98 private final boolean enabled = checkEnabled(); -99 -100 /** -101 * Determines if this analyzer is enabled -102 * -103 * @return <code>true</code> if the analyzer is enabled; otherwise -104 * <code>false</code> -105 */ -106 private boolean checkEnabled() { -107 /* Enable this analyzer ONLY if the Nexus URL has been set to something -108 other than the default one (if it's the default one, we'll use the -109 central one) and it's enabled by the user. -110 */ -111 boolean retval = false; -112 try { -113 if (!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL)) -114 && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) { -115 LOGGER.info("Enabling Nexus analyzer"); -116 retval = true; -117 } else { -118 LOGGER.debug("Nexus analyzer disabled, using Central instead"); -119 } -120 } catch (InvalidSettingException ise) { -121 LOGGER.warn("Invalid setting. Disabling Nexus analyzer"); -122 } -123 -124 return retval; -125 } -126 -127 /** -128 * Determine whether to enable this analyzer or not. -129 * -130 * @return whether the analyzer should be enabled -131 */ -132 @Override -133 public boolean isEnabled() { -134 return enabled; -135 } -136 -137 /** -138 * Initializes the analyzer once before any analysis is performed. -139 * -140 * @throws InitializationException if there's an error during initialization -141 */ -142 @Override -143 public void initializeFileTypeAnalyzer() throws InitializationException { -144 LOGGER.debug("Initializing Nexus Analyzer"); -145 LOGGER.debug("Nexus Analyzer enabled: {}", isEnabled()); -146 if (isEnabled()) { -147 final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL); -148 LOGGER.debug("Nexus Analyzer URL: {}", searchUrl); -149 try { -150 searcher = new NexusSearch(new URL(searchUrl)); -151 if (!searcher.preflightRequest()) { -152 setEnabled(false); -153 throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer."); -154 } -155 } catch (MalformedURLException mue) { -156 setEnabled(false); -157 throw new InitializationException("Malformed URL to Nexus: " + searchUrl, mue); -158 } -159 } -160 } -161 -162 /** -163 * Returns the analyzer's name. -164 * -165 * @return the name of the analyzer -166 */ -167 @Override -168 public String getName() { -169 return ANALYZER_NAME; -170 } -171 -172 /** -173 * Returns the key used in the properties file to reference the analyzer's -174 * enabled property. -175 * -176 * @return the analyzer's enabled property setting key -177 */ -178 @Override -179 protected String getAnalyzerEnabledSettingKey() { -180 return Settings.KEYS.ANALYZER_NEXUS_ENABLED; -181 } -182 -183 /** -184 * Returns the analysis phase under which the analyzer runs. -185 * -186 * @return the phase under which this analyzer runs -187 */ -188 @Override -189 public AnalysisPhase getAnalysisPhase() { -190 return ANALYSIS_PHASE; -191 } -192 -193 /** -194 * The file filter used to determine which files this analyzer supports. -195 */ -196 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(SUPPORTED_EXTENSIONS).build(); -197 -198 /** -199 * Returns the FileFilter -200 * -201 * @return the FileFilter -202 */ -203 @Override -204 protected FileFilter getFileFilter() { -205 return FILTER; -206 } -207 -208 /** -209 * Performs the analysis. -210 * -211 * @param dependency the dependency to analyze -212 * @param engine the engine -213 * @throws AnalysisException when there's an exception during analysis -214 */ -215 @Override -216 public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { -217 if (!isEnabled()) { -218 return; -219 } -220 try { -221 final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum()); -222 dependency.addAsEvidence("nexus", ma, Confidence.HIGH); -223 boolean pomAnalyzed = false; -224 LOGGER.debug("POM URL {}", ma.getPomUrl()); -225 for (Evidence e : dependency.getVendorEvidence()) { -226 if ("pom".equals(e.getSource())) { -227 pomAnalyzed = true; -228 break; -229 } -230 } -231 if (!pomAnalyzed && ma.getPomUrl() != null) { -232 File pomFile = null; -233 try { -234 final File baseDir = Settings.getTempDirectory(); -235 pomFile = File.createTempFile("pom", ".xml", baseDir); -236 if (!pomFile.delete()) { -237 LOGGER.warn("Unable to fetch pom.xml for {} from Nexus repository; " -238 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); -239 LOGGER.debug("Unable to delete temp file"); -240 } -241 LOGGER.debug("Downloading {}", ma.getPomUrl()); -242 Downloader.fetchFile(new URL(ma.getPomUrl()), pomFile); -243 PomUtils.analyzePOM(dependency, pomFile); -244 } catch (DownloadFailedException ex) { -245 LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; " -246 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); -247 } finally { -248 if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) { -249 LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString()); -250 pomFile.deleteOnExit(); -251 } -252 } -253 } -254 } catch (IllegalArgumentException iae) { -255 //dependency.addAnalysisException(new AnalysisException("Invalid SHA-1")); -256 LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName()); -257 } catch (FileNotFoundException fnfe) { -258 //dependency.addAnalysisException(new AnalysisException("Artifact not found on repository")); -259 LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName()); -260 LOGGER.debug(fnfe.getMessage(), fnfe); -261 } catch (IOException ioe) { -262 //dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe)); -263 LOGGER.debug("Could not connect to nexus repository", ioe); -264 } -265 } -266 } +90 private boolean useProxy; +91 /** +92 * The Nexus Search to be set up for this analyzer. +93 */ +94 private NexusSearch searcher; +95 +96 /** +97 * Field indicating if the analyzer is enabled. +98 */ +99 private final boolean enabled = checkEnabled(); +100 +101 /** +102 * Determines if this analyzer is enabled +103 * +104 * @return <code>true</code> if the analyzer is enabled; otherwise +105 * <code>false</code> +106 */ +107 private boolean checkEnabled() { +108 /* Enable this analyzer ONLY if the Nexus URL has been set to something +109 other than the default one (if it's the default one, we'll use the +110 central one) and it's enabled by the user. +111 */ +112 boolean retval = false; +113 try { +114 if (!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL)) +115 && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) { +116 LOGGER.info("Enabling Nexus analyzer"); +117 retval = true; +118 } else { +119 LOGGER.debug("Nexus analyzer disabled, using Central instead"); +120 } +121 } catch (InvalidSettingException ise) { +122 LOGGER.warn("Invalid setting. Disabling Nexus analyzer"); +123 } +124 +125 return retval; +126 } +127 +128 /** +129 * Determine whether to enable this analyzer or not. +130 * +131 * @return whether the analyzer should be enabled +132 */ +133 @Override +134 public boolean isEnabled() { +135 return enabled; +136 } +137 +138 /** +139 * Initializes the analyzer once before any analysis is performed. +140 * +141 * @throws InitializationException if there's an error during initialization +142 */ +143 @Override +144 public void initializeFileTypeAnalyzer() throws InitializationException { +145 LOGGER.debug("Initializing Nexus Analyzer"); +146 LOGGER.debug("Nexus Analyzer enabled: {}", isEnabled()); +147 if (isEnabled()) { +148 useProxy = useProxy(); +149 final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL); +150 LOGGER.debug("Nexus Analyzer URL: {}", searchUrl); +151 try { +152 searcher = new NexusSearch(new URL(searchUrl), useProxy); +153 if (!searcher.preflightRequest()) { +154 setEnabled(false); +155 throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer."); +156 } +157 } catch (MalformedURLException mue) { +158 setEnabled(false); +159 throw new InitializationException("Malformed URL to Nexus: " + searchUrl, mue); +160 } +161 } +162 } +163 +164 /** +165 * Returns the analyzer's name. +166 * +167 * @return the name of the analyzer +168 */ +169 @Override +170 public String getName() { +171 return ANALYZER_NAME; +172 } +173 +174 /** +175 * Returns the key used in the properties file to reference the analyzer's +176 * enabled property. +177 * +178 * @return the analyzer's enabled property setting key +179 */ +180 @Override +181 protected String getAnalyzerEnabledSettingKey() { +182 return Settings.KEYS.ANALYZER_NEXUS_ENABLED; +183 } +184 +185 /** +186 * Returns the analysis phase under which the analyzer runs. +187 * +188 * @return the phase under which this analyzer runs +189 */ +190 @Override +191 public AnalysisPhase getAnalysisPhase() { +192 return ANALYSIS_PHASE; +193 } +194 +195 /** +196 * The file filter used to determine which files this analyzer supports. +197 */ +198 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(SUPPORTED_EXTENSIONS).build(); +199 +200 /** +201 * Returns the FileFilter +202 * +203 * @return the FileFilter +204 */ +205 @Override +206 protected FileFilter getFileFilter() { +207 return FILTER; +208 } +209 +210 /** +211 * Performs the analysis. +212 * +213 * @param dependency the dependency to analyze +214 * @param engine the engine +215 * @throws AnalysisException when there's an exception during analysis +216 */ +217 @Override +218 public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { +219 if (!isEnabled()) { +220 return; +221 } +222 try { +223 final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum()); +224 dependency.addAsEvidence("nexus", ma, Confidence.HIGH); +225 boolean pomAnalyzed = false; +226 LOGGER.debug("POM URL {}", ma.getPomUrl()); +227 for (Evidence e : dependency.getVendorEvidence()) { +228 if ("pom".equals(e.getSource())) { +229 pomAnalyzed = true; +230 break; +231 } +232 } +233 if (!pomAnalyzed && ma.getPomUrl() != null) { +234 File pomFile = null; +235 try { +236 final File baseDir = Settings.getTempDirectory(); +237 pomFile = File.createTempFile("pom", ".xml", baseDir); +238 if (!pomFile.delete()) { +239 LOGGER.warn("Unable to fetch pom.xml for {} from Nexus repository; " +240 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); +241 LOGGER.debug("Unable to delete temp file"); +242 } +243 LOGGER.debug("Downloading {}", ma.getPomUrl()); +244 Downloader.fetchFile(new URL(ma.getPomUrl()), pomFile); +245 PomUtils.analyzePOM(dependency, pomFile); +246 } catch (DownloadFailedException ex) { +247 LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; " +248 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); +249 } finally { +250 if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) { +251 LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString()); +252 pomFile.deleteOnExit(); +253 } +254 } +255 } +256 } catch (IllegalArgumentException iae) { +257 //dependency.addAnalysisException(new AnalysisException("Invalid SHA-1")); +258 LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName()); +259 } catch (FileNotFoundException fnfe) { +260 //dependency.addAnalysisException(new AnalysisException("Artifact not found on repository")); +261 LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName()); +262 LOGGER.debug(fnfe.getMessage(), fnfe); +263 } catch (IOException ioe) { +264 //dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe)); +265 LOGGER.debug("Could not connect to nexus repository", ioe); +266 } +267 } +268 +269 /** +270 * Determine if a proxy should be used. +271 * +272 * @return {@code true} if a proxy should be used +273 */ +274 public static boolean useProxy() { +275 try { +276 return Settings.getString(Settings.KEYS.PROXY_SERVER) != null +277 && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY); +278 } catch (InvalidSettingException ise) { +279 LOGGER.warn("Failed to parse proxy settings.", ise); +280 return false; +281 } +282 } +283 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html index 75128b17b..22a63b4b3 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html @@ -44,7 +44,7 @@ 36 * 37 * @author Jeremy Long 38 */ -39 public class NvdCveAnalyzer implements Analyzer { +39 public class NvdCveAnalyzer extends AbstractAnalyzer { 40 /** 41 * The Logger for use throughout the class 42 */ diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html index 21cf96edf..32bdda90e 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html @@ -53,363 +53,366 @@ 45 import org.owasp.dependencycheck.utils.FileUtils; 46 import org.owasp.dependencycheck.utils.Settings; 47 import org.owasp.dependencycheck.utils.UrlStringUtils; -48 -49 /** -50 * Used to analyze a Wheel or egg distribution files, or their contents in -51 * unzipped form, and collect information that can be used to determine the -52 * associated CPE. -53 * -54 * @author Dale Visser -55 */ -56 @Experimental -57 public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer { -58 -59 /** -60 * Name of egg metadata files to analyze. -61 */ -62 private static final String PKG_INFO = "PKG-INFO"; -63 -64 /** -65 * Name of wheel metadata files to analyze. -66 */ -67 private static final String METADATA = "METADATA"; -68 -69 /** -70 * The logger. -71 */ -72 private static final Logger LOGGER = LoggerFactory -73 .getLogger(PythonDistributionAnalyzer.class); -74 -75 /** -76 * The count of directories created during analysis. This is used for -77 * creating temporary directories. -78 */ -79 private static int dirCount = 0; -80 -81 /** -82 * The name of the analyzer. -83 */ -84 private static final String ANALYZER_NAME = "Python Distribution Analyzer"; -85 /** -86 * The phase that this analyzer is intended to run in. -87 */ -88 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; -89 -90 /** -91 * The set of file extensions supported by this analyzer. -92 */ -93 private static final String[] EXTENSIONS = {"whl", "egg", "zip"}; -94 -95 /** -96 * Used to match on egg archive candidate extensions. -97 */ -98 private static final FileFilter EGG_OR_ZIP = FileFilterBuilder.newInstance().addExtensions("egg", "zip").build(); -99 -100 /** -101 * Used to detect files with a .whl extension. -102 */ -103 private static final FileFilter WHL_FILTER = FileFilterBuilder.newInstance().addExtensions("whl").build(); -104 -105 /** -106 * The parent directory for the individual directories per archive. -107 */ -108 private File tempFileLocation; -109 -110 /** -111 * Filter that detects *.dist-info files (but doesn't verify they are -112 * directories. -113 */ -114 private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter( -115 ".dist-info"); -116 -117 /** -118 * Filter that detects files named "METADATA". -119 */ -120 private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter( -121 "EGG-INFO"); -122 -123 /** -124 * Filter that detects files named "METADATA". -125 */ -126 private static final NameFileFilter METADATA_FILTER = new NameFileFilter( -127 METADATA); -128 -129 /** -130 * Filter that detects files named "PKG-INFO". -131 */ -132 private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter( -133 PKG_INFO); -134 -135 /** -136 * The file filter used to determine which files this analyzer supports. -137 */ -138 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFileFilters( -139 METADATA_FILTER, PKG_INFO_FILTER).addExtensions(EXTENSIONS).build(); -140 -141 /** -142 * Returns the FileFilter -143 * -144 * @return the FileFilter -145 */ -146 @Override -147 protected FileFilter getFileFilter() { -148 return FILTER; -149 } -150 -151 /** -152 * Returns the name of the analyzer. -153 * -154 * @return the name of the analyzer. -155 */ -156 @Override -157 public String getName() { -158 return ANALYZER_NAME; -159 } -160 -161 /** -162 * Returns the phase that the analyzer is intended to run in. -163 * -164 * @return the phase that the analyzer is intended to run in. -165 */ -166 @Override -167 public AnalysisPhase getAnalysisPhase() { -168 return ANALYSIS_PHASE; -169 } -170 -171 /** -172 * Returns the key used in the properties file to reference the analyzer's -173 * enabled property. -174 * -175 * @return the analyzer's enabled property setting key -176 */ -177 @Override -178 protected String getAnalyzerEnabledSettingKey() { -179 return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED; -180 } -181 -182 @Override -183 protected void analyzeFileType(Dependency dependency, Engine engine) -184 throws AnalysisException { -185 final File actualFile = dependency.getActualFile(); -186 if (WHL_FILTER.accept(actualFile)) { -187 collectMetadataFromArchiveFormat(dependency, DIST_INFO_FILTER, -188 METADATA_FILTER); -189 } else if (EGG_OR_ZIP.accept(actualFile)) { -190 collectMetadataFromArchiveFormat(dependency, EGG_INFO_FILTER, -191 PKG_INFO_FILTER); -192 } else { -193 final String name = actualFile.getName(); -194 final boolean metadata = METADATA.equals(name); -195 if (metadata || PKG_INFO.equals(name)) { -196 final File parent = actualFile.getParentFile(); -197 final String parentName = parent.getName(); -198 dependency.setDisplayFileName(parentName + "/" + name); -199 if (parent.isDirectory() -200 && (metadata && parentName.endsWith(".dist-info") -201 || parentName.endsWith(".egg-info") || "EGG-INFO" -202 .equals(parentName))) { -203 collectWheelMetadata(dependency, actualFile); -204 } -205 } -206 } -207 } -208 -209 /** -210 * Collects the meta data from an archive. -211 * -212 * @param dependency the archive being scanned -213 * @param folderFilter the filter to apply to the folder -214 * @param metadataFilter the filter to apply to the meta data -215 * @throws AnalysisException thrown when there is a problem analyzing the -216 * dependency -217 */ -218 private void collectMetadataFromArchiveFormat(Dependency dependency, -219 FilenameFilter folderFilter, FilenameFilter metadataFilter) -220 throws AnalysisException { -221 final File temp = getNextTempDirectory(); -222 LOGGER.debug("{} exists? {}", temp, temp.exists()); -223 try { -224 ExtractionUtil.extractFilesUsingFilter( -225 new File(dependency.getActualFilePath()), temp, -226 metadataFilter); -227 } catch (ExtractionException ex) { -228 throw new AnalysisException(ex); -229 } -230 -231 File matchingFile = getMatchingFile(temp, folderFilter); -232 if (matchingFile != null) { -233 matchingFile = getMatchingFile(matchingFile, metadataFilter); -234 if (matchingFile != null) { -235 collectWheelMetadata(dependency, matchingFile); -236 } -237 } -238 } -239 -240 /** -241 * Makes sure a usable temporary directory is available. -242 * -243 * @throws InitializationException an AnalyzeException is thrown when the -244 * temp directory cannot be created -245 */ -246 @Override -247 protected void initializeFileTypeAnalyzer() throws InitializationException { -248 try { -249 final File baseDir = Settings.getTempDirectory(); -250 tempFileLocation = File.createTempFile("check", "tmp", baseDir); -251 if (!tempFileLocation.delete()) { -252 setEnabled(false); -253 final String msg = String.format( -254 "Unable to delete temporary file '%s'.", -255 tempFileLocation.getAbsolutePath()); -256 throw new InitializationException(msg); -257 } -258 if (!tempFileLocation.mkdirs()) { -259 setEnabled(false); -260 final String msg = String.format( -261 "Unable to create directory '%s'.", -262 tempFileLocation.getAbsolutePath()); -263 throw new InitializationException(msg); -264 } -265 } catch (IOException ex) { -266 setEnabled(false); -267 throw new InitializationException("Unable to create a temporary file", ex); -268 } -269 } -270 -271 /** -272 * Deletes any files extracted from the Wheel during analysis. -273 */ -274 @Override -275 public void close() { -276 if (tempFileLocation != null && tempFileLocation.exists()) { -277 LOGGER.debug("Attempting to delete temporary files"); -278 final boolean success = FileUtils.delete(tempFileLocation); -279 if (!success) { -280 LOGGER.warn( -281 "Failed to delete some temporary files, see the log for more details"); -282 } -283 } -284 } -285 -286 /** -287 * Gathers evidence from the METADATA file. -288 * -289 * @param dependency the dependency being analyzed -290 * @param file a reference to the manifest/properties file -291 */ -292 private static void collectWheelMetadata(Dependency dependency, File file) { -293 final InternetHeaders headers = getManifestProperties(file); -294 addPropertyToEvidence(headers, dependency.getVersionEvidence(), -295 "Version", Confidence.HIGHEST); -296 addPropertyToEvidence(headers, dependency.getProductEvidence(), "Name", -297 Confidence.HIGHEST); -298 final String url = headers.getHeader("Home-page", null); -299 final EvidenceCollection vendorEvidence = dependency -300 .getVendorEvidence(); -301 if (StringUtils.isNotBlank(url)) { -302 if (UrlStringUtils.isUrl(url)) { -303 vendorEvidence.addEvidence(METADATA, "vendor", url, -304 Confidence.MEDIUM); -305 } -306 } -307 addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW); -308 final String summary = headers.getHeader("Summary", null); -309 if (StringUtils.isNotBlank(summary)) { -310 JarAnalyzer -311 .addDescription(dependency, summary, METADATA, "summary"); -312 } -313 } -314 -315 /** -316 * Adds a value to the evidence collection. -317 * -318 * @param headers the properties collection -319 * @param evidence the evidence collection to add the value -320 * @param property the property name -321 * @param confidence the confidence of the evidence -322 */ -323 private static void addPropertyToEvidence(InternetHeaders headers, -324 EvidenceCollection evidence, String property, Confidence confidence) { -325 final String value = headers.getHeader(property, null); -326 LOGGER.debug("Property: {}, Value: {}", property, value); -327 if (StringUtils.isNotBlank(value)) { -328 evidence.addEvidence(METADATA, property, value, confidence); -329 } -330 } -331 -332 /** -333 * Returns a list of files that match the given filter, this does not -334 * recursively scan the directory. -335 * -336 * @param folder the folder to filter -337 * @param filter the filter to apply to the files in the directory -338 * @return the list of Files in the directory that match the provided filter -339 */ -340 private static File getMatchingFile(File folder, FilenameFilter filter) { -341 File result = null; -342 final File[] matches = folder.listFiles(filter); -343 if (null != matches && 1 == matches.length) { -344 result = matches[0]; -345 } -346 return result; -347 } -348 -349 /** -350 * Reads the manifest entries from the provided file. -351 * -352 * @param manifest the manifest -353 * @return the manifest entries -354 */ -355 private static InternetHeaders getManifestProperties(File manifest) { -356 final InternetHeaders result = new InternetHeaders(); -357 if (null == manifest) { -358 LOGGER.debug("Manifest file not found."); -359 } else { -360 InputStream in = null; -361 try { -362 in = new BufferedInputStream(new FileInputStream(manifest)); -363 result.load(in); -364 } catch (MessagingException e) { -365 LOGGER.warn(e.getMessage(), e); -366 } catch (FileNotFoundException e) { -367 LOGGER.warn(e.getMessage(), e); -368 } finally { -369 if (in != null) { -370 try { -371 in.close(); -372 } catch (IOException ex) { -373 LOGGER.debug("failed to close input stream", ex); -374 } -375 } -376 } -377 } -378 return result; -379 } -380 -381 /** -382 * Retrieves the next temporary destination directory for extracting an -383 * archive. -384 * -385 * @return a directory -386 * @throws AnalysisException thrown if unable to create temporary directory -387 */ -388 private File getNextTempDirectory() throws AnalysisException { -389 File directory; -390 -391 // getting an exception for some directories not being able to be -392 // created; might be because the directory already exists? -393 do { -394 dirCount += 1; -395 directory = new File(tempFileLocation, String.valueOf(dirCount)); -396 } while (directory.exists()); -397 if (!directory.mkdirs()) { -398 throw new AnalysisException(String.format( -399 "Unable to create temp directory '%s'.", -400 directory.getAbsolutePath())); -401 } -402 return directory; -403 } -404 } +48 import java.util.concurrent.atomic.AtomicInteger; +49 +50 /** +51 * Used to analyze a Wheel or egg distribution files, or their contents in +52 * unzipped form, and collect information that can be used to determine the +53 * associated CPE. +54 * +55 * @author Dale Visser +56 */ +57 @Experimental +58 public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer { +59 +60 /** +61 * Name of egg metadata files to analyze. +62 */ +63 private static final String PKG_INFO = "PKG-INFO"; +64 +65 /** +66 * Name of wheel metadata files to analyze. +67 */ +68 private static final String METADATA = "METADATA"; +69 +70 /** +71 * The logger. +72 */ +73 private static final Logger LOGGER = LoggerFactory +74 .getLogger(PythonDistributionAnalyzer.class); +75 +76 /** +77 * The count of directories created during analysis. This is used for +78 * creating temporary directories. +79 */ +80 private static final AtomicInteger DIR_COUNT = new AtomicInteger(0); +81 +82 /** +83 * The name of the analyzer. +84 */ +85 private static final String ANALYZER_NAME = "Python Distribution Analyzer"; +86 /** +87 * The phase that this analyzer is intended to run in. +88 */ +89 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; +90 +91 /** +92 * The set of file extensions supported by this analyzer. +93 */ +94 private static final String[] EXTENSIONS = {"whl", "egg", "zip"}; +95 +96 /** +97 * Used to match on egg archive candidate extensions. +98 */ +99 private static final FileFilter EGG_OR_ZIP = FileFilterBuilder.newInstance().addExtensions("egg", "zip").build(); +100 +101 /** +102 * Used to detect files with a .whl extension. +103 */ +104 private static final FileFilter WHL_FILTER = FileFilterBuilder.newInstance().addExtensions("whl").build(); +105 +106 /** +107 * The parent directory for the individual directories per archive. +108 */ +109 private File tempFileLocation; +110 +111 /** +112 * Filter that detects *.dist-info files (but doesn't verify they are +113 * directories. +114 */ +115 private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter( +116 ".dist-info"); +117 +118 /** +119 * Filter that detects files named "METADATA". +120 */ +121 private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter( +122 "EGG-INFO"); +123 +124 /** +125 * Filter that detects files named "METADATA". +126 */ +127 private static final NameFileFilter METADATA_FILTER = new NameFileFilter( +128 METADATA); +129 +130 /** +131 * Filter that detects files named "PKG-INFO". +132 */ +133 private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter( +134 PKG_INFO); +135 +136 /** +137 * The file filter used to determine which files this analyzer supports. +138 */ +139 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFileFilters( +140 METADATA_FILTER, PKG_INFO_FILTER).addExtensions(EXTENSIONS).build(); +141 +142 /** +143 * Returns the FileFilter +144 * +145 * @return the FileFilter +146 */ +147 @Override +148 protected FileFilter getFileFilter() { +149 return FILTER; +150 } +151 +152 /** +153 * Returns the name of the analyzer. +154 * +155 * @return the name of the analyzer. +156 */ +157 @Override +158 public String getName() { +159 return ANALYZER_NAME; +160 } +161 +162 /** +163 * Returns the phase that the analyzer is intended to run in. +164 * +165 * @return the phase that the analyzer is intended to run in. +166 */ +167 @Override +168 public AnalysisPhase getAnalysisPhase() { +169 return ANALYSIS_PHASE; +170 } +171 +172 /** +173 * Returns the key used in the properties file to reference the analyzer's +174 * enabled property. +175 * +176 * @return the analyzer's enabled property setting key +177 */ +178 @Override +179 protected String getAnalyzerEnabledSettingKey() { +180 return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED; +181 } +182 +183 @Override +184 protected void analyzeFileType(Dependency dependency, Engine engine) +185 throws AnalysisException { +186 final File actualFile = dependency.getActualFile(); +187 if (WHL_FILTER.accept(actualFile)) { +188 collectMetadataFromArchiveFormat(dependency, DIST_INFO_FILTER, +189 METADATA_FILTER); +190 } else if (EGG_OR_ZIP.accept(actualFile)) { +191 collectMetadataFromArchiveFormat(dependency, EGG_INFO_FILTER, +192 PKG_INFO_FILTER); +193 } else { +194 final String name = actualFile.getName(); +195 final boolean metadata = METADATA.equals(name); +196 if (metadata || PKG_INFO.equals(name)) { +197 final File parent = actualFile.getParentFile(); +198 final String parentName = parent.getName(); +199 dependency.setDisplayFileName(parentName + "/" + name); +200 if (parent.isDirectory() +201 && (metadata && parentName.endsWith(".dist-info") +202 || parentName.endsWith(".egg-info") || "EGG-INFO" +203 .equals(parentName))) { +204 collectWheelMetadata(dependency, actualFile); +205 } +206 } +207 } +208 } +209 +210 /** +211 * Collects the meta data from an archive. +212 * +213 * @param dependency the archive being scanned +214 * @param folderFilter the filter to apply to the folder +215 * @param metadataFilter the filter to apply to the meta data +216 * @throws AnalysisException thrown when there is a problem analyzing the +217 * dependency +218 */ +219 private void collectMetadataFromArchiveFormat(Dependency dependency, +220 FilenameFilter folderFilter, FilenameFilter metadataFilter) +221 throws AnalysisException { +222 final File temp = getNextTempDirectory(); +223 LOGGER.debug("{} exists? {}", temp, temp.exists()); +224 try { +225 ExtractionUtil.extractFilesUsingFilter( +226 new File(dependency.getActualFilePath()), temp, +227 metadataFilter); +228 } catch (ExtractionException ex) { +229 throw new AnalysisException(ex); +230 } +231 +232 File matchingFile = getMatchingFile(temp, folderFilter); +233 if (matchingFile != null) { +234 matchingFile = getMatchingFile(matchingFile, metadataFilter); +235 if (matchingFile != null) { +236 collectWheelMetadata(dependency, matchingFile); +237 } +238 } +239 } +240 +241 /** +242 * Makes sure a usable temporary directory is available. +243 * +244 * @throws InitializationException an AnalyzeException is thrown when the +245 * temp directory cannot be created +246 */ +247 @Override +248 protected void initializeFileTypeAnalyzer() throws InitializationException { +249 try { +250 final File baseDir = Settings.getTempDirectory(); +251 tempFileLocation = File.createTempFile("check", "tmp", baseDir); +252 if (!tempFileLocation.delete()) { +253 setEnabled(false); +254 final String msg = String.format( +255 "Unable to delete temporary file '%s'.", +256 tempFileLocation.getAbsolutePath()); +257 throw new InitializationException(msg); +258 } +259 if (!tempFileLocation.mkdirs()) { +260 setEnabled(false); +261 final String msg = String.format( +262 "Unable to create directory '%s'.", +263 tempFileLocation.getAbsolutePath()); +264 throw new InitializationException(msg); +265 } +266 } catch (IOException ex) { +267 setEnabled(false); +268 throw new InitializationException("Unable to create a temporary file", ex); +269 } +270 } +271 +272 /** +273 * Deletes any files extracted from the Wheel during analysis. +274 */ +275 @Override +276 public void close() { +277 if (tempFileLocation != null && tempFileLocation.exists()) { +278 LOGGER.debug("Attempting to delete temporary files"); +279 final boolean success = FileUtils.delete(tempFileLocation); +280 if (!success && tempFileLocation.exists()) { +281 final String[] l = tempFileLocation.list(); +282 if (l != null && l.length > 0) { +283 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); +284 } +285 } +286 } +287 } +288 +289 /** +290 * Gathers evidence from the METADATA file. +291 * +292 * @param dependency the dependency being analyzed +293 * @param file a reference to the manifest/properties file +294 */ +295 private static void collectWheelMetadata(Dependency dependency, File file) { +296 final InternetHeaders headers = getManifestProperties(file); +297 addPropertyToEvidence(headers, dependency.getVersionEvidence(), +298 "Version", Confidence.HIGHEST); +299 addPropertyToEvidence(headers, dependency.getProductEvidence(), "Name", +300 Confidence.HIGHEST); +301 final String url = headers.getHeader("Home-page", null); +302 final EvidenceCollection vendorEvidence = dependency +303 .getVendorEvidence(); +304 if (StringUtils.isNotBlank(url)) { +305 if (UrlStringUtils.isUrl(url)) { +306 vendorEvidence.addEvidence(METADATA, "vendor", url, +307 Confidence.MEDIUM); +308 } +309 } +310 addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW); +311 final String summary = headers.getHeader("Summary", null); +312 if (StringUtils.isNotBlank(summary)) { +313 JarAnalyzer +314 .addDescription(dependency, summary, METADATA, "summary"); +315 } +316 } +317 +318 /** +319 * Adds a value to the evidence collection. +320 * +321 * @param headers the properties collection +322 * @param evidence the evidence collection to add the value +323 * @param property the property name +324 * @param confidence the confidence of the evidence +325 */ +326 private static void addPropertyToEvidence(InternetHeaders headers, +327 EvidenceCollection evidence, String property, Confidence confidence) { +328 final String value = headers.getHeader(property, null); +329 LOGGER.debug("Property: {}, Value: {}", property, value); +330 if (StringUtils.isNotBlank(value)) { +331 evidence.addEvidence(METADATA, property, value, confidence); +332 } +333 } +334 +335 /** +336 * Returns a list of files that match the given filter, this does not +337 * recursively scan the directory. +338 * +339 * @param folder the folder to filter +340 * @param filter the filter to apply to the files in the directory +341 * @return the list of Files in the directory that match the provided filter +342 */ +343 private static File getMatchingFile(File folder, FilenameFilter filter) { +344 File result = null; +345 final File[] matches = folder.listFiles(filter); +346 if (null != matches && 1 == matches.length) { +347 result = matches[0]; +348 } +349 return result; +350 } +351 +352 /** +353 * Reads the manifest entries from the provided file. +354 * +355 * @param manifest the manifest +356 * @return the manifest entries +357 */ +358 private static InternetHeaders getManifestProperties(File manifest) { +359 final InternetHeaders result = new InternetHeaders(); +360 if (null == manifest) { +361 LOGGER.debug("Manifest file not found."); +362 } else { +363 InputStream in = null; +364 try { +365 in = new BufferedInputStream(new FileInputStream(manifest)); +366 result.load(in); +367 } catch (MessagingException e) { +368 LOGGER.warn(e.getMessage(), e); +369 } catch (FileNotFoundException e) { +370 LOGGER.warn(e.getMessage(), e); +371 } finally { +372 if (in != null) { +373 try { +374 in.close(); +375 } catch (IOException ex) { +376 LOGGER.debug("failed to close input stream", ex); +377 } +378 } +379 } +380 } +381 return result; +382 } +383 +384 /** +385 * Retrieves the next temporary destination directory for extracting an +386 * archive. +387 * +388 * @return a directory +389 * @throws AnalysisException thrown if unable to create temporary directory +390 */ +391 private File getNextTempDirectory() throws AnalysisException { +392 File directory; +393 +394 // getting an exception for some directories not being able to be +395 // created; might be because the directory already exists? +396 do { +397 final int dirCount = DIR_COUNT.incrementAndGet(); +398 directory = new File(tempFileLocation, String.valueOf(dirCount)); +399 } while (directory.exists()); +400 if (!directory.mkdirs()) { +401 throw new AnalysisException(String.format( +402 "Unable to create temp directory '%s'.", +403 directory.getAbsolutePath())); +404 } +405 return directory; +406 } +407 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.html index 847ae696f..8ce3074e6 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.html @@ -41,295 +41,289 @@ 33 import java.io.FileFilter; 34 import java.io.IOException; 35 import java.nio.charset.Charset; -36 import java.util.ArrayList; -37 import java.util.List; -38 import java.util.regex.Matcher; -39 import java.util.regex.Pattern; -40 import org.owasp.dependencycheck.exception.InitializationException; -41 -42 /** -43 * Used to analyze a Python package, and collect information that can be used to -44 * determine the associated CPE. -45 * -46 * @author Dale Visser -47 */ -48 @Experimental -49 public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { -50 -51 /** -52 * Used when compiling file scanning regex patterns. -53 */ -54 private static final int REGEX_OPTIONS = Pattern.DOTALL -55 | Pattern.CASE_INSENSITIVE; -56 -57 /** -58 * Filename extensions for files to be analyzed. -59 */ -60 private static final String EXTENSIONS = "py"; -61 -62 /** -63 * Pattern for matching the module docstring in a source file. -64 */ -65 private static final Pattern MODULE_DOCSTRING = Pattern.compile( -66 "^(['\\\"]{3})(.*?)\\1", REGEX_OPTIONS); -67 -68 /** -69 * Matches assignments to version variables in Python source code. -70 */ -71 private static final Pattern VERSION_PATTERN = Pattern.compile( -72 "\\b(__)?version(__)? *= *(['\"]+)(\\d+\\.\\d+.*?)\\3", -73 REGEX_OPTIONS); -74 -75 /** -76 * Matches assignments to title variables in Python source code. -77 */ -78 private static final Pattern TITLE_PATTERN = compileAssignPattern("title"); -79 -80 /** -81 * Matches assignments to summary variables in Python source code. -82 */ -83 private static final Pattern SUMMARY_PATTERN = compileAssignPattern("summary"); -84 -85 /** -86 * Matches assignments to URL/URL variables in Python source code. -87 */ -88 private static final Pattern URI_PATTERN = compileAssignPattern("ur[il]"); -89 -90 /** -91 * Matches assignments to home page variables in Python source code. -92 */ -93 private static final Pattern HOMEPAGE_PATTERN = compileAssignPattern("home_?page"); -94 -95 /** -96 * Matches assignments to author variables in Python source code. -97 */ -98 private static final Pattern AUTHOR_PATTERN = compileAssignPattern("author"); -99 -100 /** -101 * Filter that detects files named "__init__.py". -102 */ -103 private static final FileFilter INIT_PY_FILTER = new NameFileFilter("__init__.py"); -104 -105 /** -106 * The file filter for python files. -107 */ -108 private static final FileFilter PY_FILTER = new SuffixFileFilter(".py"); -109 -110 /** -111 * Returns the name of the Python Package Analyzer. -112 * -113 * @return the name of the analyzer -114 */ -115 @Override -116 public String getName() { -117 return "Python Package Analyzer"; -118 } -119 -120 /** -121 * Tell that we are used for information collection. -122 * -123 * @return INFORMATION_COLLECTION -124 */ -125 @Override -126 public AnalysisPhase getAnalysisPhase() { -127 return AnalysisPhase.INFORMATION_COLLECTION; -128 } -129 -130 /** -131 * The file filter used to determine which files this analyzer supports. -132 */ -133 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build(); -134 -135 /** -136 * Returns the FileFilter -137 * -138 * @return the FileFilter -139 */ -140 @Override -141 protected FileFilter getFileFilter() { -142 return FILTER; -143 } -144 -145 /** -146 * No-op initializer implementation. -147 * -148 * @throws InitializationException never thrown -149 */ -150 @Override -151 protected void initializeFileTypeAnalyzer() throws InitializationException { -152 // Nothing to do here. -153 } -154 -155 /** -156 * Utility function to create a regex pattern matcher. -157 * -158 * @param name the value to use when constructing the assignment pattern -159 * @return the compiled Pattern -160 */ -161 private static Pattern compileAssignPattern(String name) { -162 return Pattern.compile( -163 String.format("\\b(__)?%s(__)?\\b *= *(['\"]+)(.*?)\\3", name), -164 REGEX_OPTIONS); -165 } -166 -167 /** -168 * Analyzes python packages and adds evidence to the dependency. -169 * -170 * @param dependency the dependency being analyzed -171 * @param engine the engine being used to perform the scan -172 * @throws AnalysisException thrown if there is an unrecoverable error -173 * analyzing the dependency -174 */ -175 @Override -176 protected void analyzeFileType(Dependency dependency, Engine engine) -177 throws AnalysisException { -178 final File file = dependency.getActualFile(); -179 final File parent = file.getParentFile(); -180 final String parentName = parent.getName(); -181 if (INIT_PY_FILTER.accept(file)) { -182 //by definition, the containing folder of __init__.py is considered the package, even the file is empty: -183 //"The __init__.py files are required to make Python treat the directories as containing packages" -184 //see section "6.4 Packages" from https://docs.python.org/2/tutorial/modules.html; -185 dependency.setDisplayFileName(parentName + "/__init__.py"); -186 dependency.getProductEvidence().addEvidence(file.getName(), -187 "PackageName", parentName, Confidence.HIGHEST); -188 -189 final File[] fileList = parent.listFiles(PY_FILTER); -190 if (fileList != null) { -191 for (final File sourceFile : fileList) { -192 analyzeFileContents(dependency, sourceFile); -193 } -194 } -195 } else { -196 // copy, alter and set in case some other thread is iterating over -197 final List<Dependency> dependencies = new ArrayList<Dependency>( -198 engine.getDependencies()); -199 dependencies.remove(dependency); -200 engine.setDependencies(dependencies); -201 } -202 } -203 -204 /** -205 * This should gather information from leading docstrings, file comments, -206 * and assignments to __version__, __title__, __summary__, __uri__, __url__, -207 * __home*page__, __author__, and their all caps equivalents. -208 * -209 * @param dependency the dependency being analyzed -210 * @param file the file name to analyze -211 * @return whether evidence was found -212 * @throws AnalysisException thrown if there is an unrecoverable error -213 */ -214 private boolean analyzeFileContents(Dependency dependency, File file) -215 throws AnalysisException { -216 String contents; -217 try { -218 contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); -219 } catch (IOException e) { -220 throw new AnalysisException( -221 "Problem occurred while reading dependency file.", e); -222 } -223 boolean found = false; -224 if (!contents.isEmpty()) { -225 final String source = file.getName(); -226 found = gatherEvidence(VERSION_PATTERN, contents, source, -227 dependency.getVersionEvidence(), "SourceVersion", -228 Confidence.MEDIUM); -229 found |= addSummaryInfo(dependency, SUMMARY_PATTERN, 4, contents, -230 source, "summary"); -231 if (INIT_PY_FILTER.accept(file)) { -232 found |= addSummaryInfo(dependency, MODULE_DOCSTRING, 2, -233 contents, source, "docstring"); -234 } -235 found |= gatherEvidence(TITLE_PATTERN, contents, source, -236 dependency.getProductEvidence(), "SourceTitle", -237 Confidence.LOW); -238 final EvidenceCollection vendorEvidence = dependency -239 .getVendorEvidence(); -240 found |= gatherEvidence(AUTHOR_PATTERN, contents, source, -241 vendorEvidence, "SourceAuthor", Confidence.MEDIUM); -242 found |= gatherHomePageEvidence(URI_PATTERN, vendorEvidence, -243 source, "URL", contents); -244 found |= gatherHomePageEvidence(HOMEPAGE_PATTERN, -245 vendorEvidence, source, "HomePage", contents); -246 } -247 return found; -248 } -249 -250 /** -251 * Adds summary information to the dependency -252 * -253 * @param dependency the dependency being analyzed -254 * @param pattern the pattern used to perform analysis -255 * @param group the group from the pattern that indicates the data to use -256 * @param contents the data being analyzed -257 * @param source the source name to use when recording the evidence -258 * @param key the key name to use when recording the evidence -259 * @return true if evidence was collected; otherwise false -260 */ -261 private boolean addSummaryInfo(Dependency dependency, Pattern pattern, -262 int group, String contents, String source, String key) { -263 final Matcher matcher = pattern.matcher(contents); -264 final boolean found = matcher.find(); -265 if (found) { -266 JarAnalyzer.addDescription(dependency, matcher.group(group), -267 source, key); -268 } -269 return found; -270 } -271 -272 /** -273 * Collects evidence from the home page URL. -274 * -275 * @param pattern the pattern to match -276 * @param evidence the evidence collection to add the evidence to -277 * @param source the source of the evidence -278 * @param name the name of the evidence -279 * @param contents the home page URL -280 * @return true if evidence was collected; otherwise false -281 */ -282 private boolean gatherHomePageEvidence(Pattern pattern, -283 EvidenceCollection evidence, String source, String name, -284 String contents) { -285 final Matcher matcher = pattern.matcher(contents); -286 boolean found = false; -287 if (matcher.find()) { -288 final String url = matcher.group(4); -289 if (UrlStringUtils.isUrl(url)) { -290 found = true; -291 evidence.addEvidence(source, name, url, Confidence.MEDIUM); -292 } -293 } -294 return found; -295 } -296 -297 /** -298 * Gather evidence from a Python source file using the given string -299 * assignment regex pattern. -300 * -301 * @param pattern to scan contents with -302 * @param contents of Python source file -303 * @param source for storing evidence -304 * @param evidence to store evidence in -305 * @param name of evidence -306 * @param confidence in evidence -307 * @return whether evidence was found -308 */ -309 private boolean gatherEvidence(Pattern pattern, String contents, -310 String source, EvidenceCollection evidence, String name, -311 Confidence confidence) { -312 final Matcher matcher = pattern.matcher(contents); -313 final boolean found = matcher.find(); -314 if (found) { -315 evidence.addEvidence(source, name, matcher.group(4), confidence); -316 } -317 return found; -318 } -319 -320 @Override -321 protected String getAnalyzerEnabledSettingKey() { -322 return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED; -323 } -324 } +36 import java.util.regex.Matcher; +37 import java.util.regex.Pattern; +38 import org.owasp.dependencycheck.exception.InitializationException; +39 +40 /** +41 * Used to analyze a Python package, and collect information that can be used to +42 * determine the associated CPE. +43 * +44 * @author Dale Visser +45 */ +46 @Experimental +47 public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { +48 +49 /** +50 * Used when compiling file scanning regex patterns. +51 */ +52 private static final int REGEX_OPTIONS = Pattern.DOTALL +53 | Pattern.CASE_INSENSITIVE; +54 +55 /** +56 * Filename extensions for files to be analyzed. +57 */ +58 private static final String EXTENSIONS = "py"; +59 +60 /** +61 * Pattern for matching the module docstring in a source file. +62 */ +63 private static final Pattern MODULE_DOCSTRING = Pattern.compile( +64 "^(['\\\"]{3})(.*?)\\1", REGEX_OPTIONS); +65 +66 /** +67 * Matches assignments to version variables in Python source code. +68 */ +69 private static final Pattern VERSION_PATTERN = Pattern.compile( +70 "\\b(__)?version(__)? *= *(['\"]+)(\\d+\\.\\d+.*?)\\3", +71 REGEX_OPTIONS); +72 +73 /** +74 * Matches assignments to title variables in Python source code. +75 */ +76 private static final Pattern TITLE_PATTERN = compileAssignPattern("title"); +77 +78 /** +79 * Matches assignments to summary variables in Python source code. +80 */ +81 private static final Pattern SUMMARY_PATTERN = compileAssignPattern("summary"); +82 +83 /** +84 * Matches assignments to URL/URL variables in Python source code. +85 */ +86 private static final Pattern URI_PATTERN = compileAssignPattern("ur[il]"); +87 +88 /** +89 * Matches assignments to home page variables in Python source code. +90 */ +91 private static final Pattern HOMEPAGE_PATTERN = compileAssignPattern("home_?page"); +92 +93 /** +94 * Matches assignments to author variables in Python source code. +95 */ +96 private static final Pattern AUTHOR_PATTERN = compileAssignPattern("author"); +97 +98 /** +99 * Filter that detects files named "__init__.py". +100 */ +101 private static final FileFilter INIT_PY_FILTER = new NameFileFilter("__init__.py"); +102 +103 /** +104 * The file filter for python files. +105 */ +106 private static final FileFilter PY_FILTER = new SuffixFileFilter(".py"); +107 +108 /** +109 * Returns the name of the Python Package Analyzer. +110 * +111 * @return the name of the analyzer +112 */ +113 @Override +114 public String getName() { +115 return "Python Package Analyzer"; +116 } +117 +118 /** +119 * Tell that we are used for information collection. +120 * +121 * @return INFORMATION_COLLECTION +122 */ +123 @Override +124 public AnalysisPhase getAnalysisPhase() { +125 return AnalysisPhase.INFORMATION_COLLECTION; +126 } +127 +128 /** +129 * The file filter used to determine which files this analyzer supports. +130 */ +131 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build(); +132 +133 /** +134 * Returns the FileFilter +135 * +136 * @return the FileFilter +137 */ +138 @Override +139 protected FileFilter getFileFilter() { +140 return FILTER; +141 } +142 +143 /** +144 * No-op initializer implementation. +145 * +146 * @throws InitializationException never thrown +147 */ +148 @Override +149 protected void initializeFileTypeAnalyzer() throws InitializationException { +150 // Nothing to do here. +151 } +152 +153 /** +154 * Utility function to create a regex pattern matcher. +155 * +156 * @param name the value to use when constructing the assignment pattern +157 * @return the compiled Pattern +158 */ +159 private static Pattern compileAssignPattern(String name) { +160 return Pattern.compile( +161 String.format("\\b(__)?%s(__)?\\b *= *(['\"]+)(.*?)\\3", name), +162 REGEX_OPTIONS); +163 } +164 +165 /** +166 * Analyzes python packages and adds evidence to the dependency. +167 * +168 * @param dependency the dependency being analyzed +169 * @param engine the engine being used to perform the scan +170 * @throws AnalysisException thrown if there is an unrecoverable error +171 * analyzing the dependency +172 */ +173 @Override +174 protected void analyzeFileType(Dependency dependency, Engine engine) +175 throws AnalysisException { +176 final File file = dependency.getActualFile(); +177 final File parent = file.getParentFile(); +178 final String parentName = parent.getName(); +179 if (INIT_PY_FILTER.accept(file)) { +180 //by definition, the containing folder of __init__.py is considered the package, even the file is empty: +181 //"The __init__.py files are required to make Python treat the directories as containing packages" +182 //see section "6.4 Packages" from https://docs.python.org/2/tutorial/modules.html; +183 dependency.setDisplayFileName(parentName + "/__init__.py"); +184 dependency.getProductEvidence().addEvidence(file.getName(), +185 "PackageName", parentName, Confidence.HIGHEST); +186 +187 final File[] fileList = parent.listFiles(PY_FILTER); +188 if (fileList != null) { +189 for (final File sourceFile : fileList) { +190 analyzeFileContents(dependency, sourceFile); +191 } +192 } +193 } else { +194 engine.getDependencies().remove(dependency); +195 } +196 } +197 +198 /** +199 * This should gather information from leading docstrings, file comments, +200 * and assignments to __version__, __title__, __summary__, __uri__, __url__, +201 * __home*page__, __author__, and their all caps equivalents. +202 * +203 * @param dependency the dependency being analyzed +204 * @param file the file name to analyze +205 * @return whether evidence was found +206 * @throws AnalysisException thrown if there is an unrecoverable error +207 */ +208 private boolean analyzeFileContents(Dependency dependency, File file) +209 throws AnalysisException { +210 String contents; +211 try { +212 contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); +213 } catch (IOException e) { +214 throw new AnalysisException( +215 "Problem occurred while reading dependency file.", e); +216 } +217 boolean found = false; +218 if (!contents.isEmpty()) { +219 final String source = file.getName(); +220 found = gatherEvidence(VERSION_PATTERN, contents, source, +221 dependency.getVersionEvidence(), "SourceVersion", +222 Confidence.MEDIUM); +223 found |= addSummaryInfo(dependency, SUMMARY_PATTERN, 4, contents, +224 source, "summary"); +225 if (INIT_PY_FILTER.accept(file)) { +226 found |= addSummaryInfo(dependency, MODULE_DOCSTRING, 2, +227 contents, source, "docstring"); +228 } +229 found |= gatherEvidence(TITLE_PATTERN, contents, source, +230 dependency.getProductEvidence(), "SourceTitle", +231 Confidence.LOW); +232 final EvidenceCollection vendorEvidence = dependency +233 .getVendorEvidence(); +234 found |= gatherEvidence(AUTHOR_PATTERN, contents, source, +235 vendorEvidence, "SourceAuthor", Confidence.MEDIUM); +236 found |= gatherHomePageEvidence(URI_PATTERN, vendorEvidence, +237 source, "URL", contents); +238 found |= gatherHomePageEvidence(HOMEPAGE_PATTERN, +239 vendorEvidence, source, "HomePage", contents); +240 } +241 return found; +242 } +243 +244 /** +245 * Adds summary information to the dependency +246 * +247 * @param dependency the dependency being analyzed +248 * @param pattern the pattern used to perform analysis +249 * @param group the group from the pattern that indicates the data to use +250 * @param contents the data being analyzed +251 * @param source the source name to use when recording the evidence +252 * @param key the key name to use when recording the evidence +253 * @return true if evidence was collected; otherwise false +254 */ +255 private boolean addSummaryInfo(Dependency dependency, Pattern pattern, +256 int group, String contents, String source, String key) { +257 final Matcher matcher = pattern.matcher(contents); +258 final boolean found = matcher.find(); +259 if (found) { +260 JarAnalyzer.addDescription(dependency, matcher.group(group), +261 source, key); +262 } +263 return found; +264 } +265 +266 /** +267 * Collects evidence from the home page URL. +268 * +269 * @param pattern the pattern to match +270 * @param evidence the evidence collection to add the evidence to +271 * @param source the source of the evidence +272 * @param name the name of the evidence +273 * @param contents the home page URL +274 * @return true if evidence was collected; otherwise false +275 */ +276 private boolean gatherHomePageEvidence(Pattern pattern, +277 EvidenceCollection evidence, String source, String name, +278 String contents) { +279 final Matcher matcher = pattern.matcher(contents); +280 boolean found = false; +281 if (matcher.find()) { +282 final String url = matcher.group(4); +283 if (UrlStringUtils.isUrl(url)) { +284 found = true; +285 evidence.addEvidence(source, name, url, Confidence.MEDIUM); +286 } +287 } +288 return found; +289 } +290 +291 /** +292 * Gather evidence from a Python source file using the given string +293 * assignment regex pattern. +294 * +295 * @param pattern to scan contents with +296 * @param contents of Python source file +297 * @param source for storing evidence +298 * @param evidence to store evidence in +299 * @param name of evidence +300 * @param confidence in evidence +301 * @return whether evidence was found +302 */ +303 private boolean gatherEvidence(Pattern pattern, String contents, +304 String source, EvidenceCollection evidence, String name, +305 Confidence confidence) { +306 final Matcher matcher = pattern.matcher(contents); +307 final boolean found = matcher.find(); +308 if (found) { +309 evidence.addEvidence(source, name, matcher.group(4), confidence); +310 } +311 return found; +312 } +313 +314 @Override +315 protected String getAnalyzerEnabledSettingKey() { +316 return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED; +317 } +318 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html index 3cd157e12..3c4daa4be 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html @@ -294,7 +294,7 @@ 286 } catch (InterruptedException ie) { 287 throw new AnalysisException("bundle-audit process interrupted", ie); 288 } -289 if (exitValue != 0) { +289 if (exitValue < 0 || exitValue > 1) { 290 final String msg = String.format("Unexpected exit code from bundle-audit process; exit code: %s", exitValue); 291 throw new AnalysisException(msg); 292 } diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html index 7db4df437..df0c4fae3 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer.exception + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.analyzer.exception diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html index 80571f23e..2eac02e78 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer.exception + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.analyzer.exception diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-frame.html index 937c7a0ad..de016eea6 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.analyzer diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-summary.html index bc76dfe4e..ca46d55a1 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/analyzer/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.analyzer diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/central/CentralSearch.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/central/CentralSearch.html index b7dba63dd..4d8e1cc43 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/central/CentralSearch.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/central/CentralSearch.html @@ -59,7 +59,7 @@ 51 /** 52 * Whether to use the Proxy when making requests 53 */ -54 private boolean useProxy; +54 private final boolean useProxy; 55 56 /** 57 * Used for logging. @@ -118,62 +118,63 @@ 110 if (conn.getResponseCode() == 200) { 111 boolean missing = false; 112 try { -113 final DocumentBuilder builder = DocumentBuilderFactory -114 .newInstance().newDocumentBuilder(); -115 final Document doc = builder.parse(conn.getInputStream()); -116 final XPath xpath = XPathFactory.newInstance().newXPath(); -117 final String numFound = xpath.evaluate("/response/result/@numFound", doc); -118 if ("0".equals(numFound)) { -119 missing = true; -120 } else { -121 result = new ArrayList<MavenArtifact>(); -122 final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET); -123 for (int i = 0; i < docs.getLength(); i++) { -124 final String g = xpath.evaluate("./str[@name='g']", docs.item(i)); -125 LOGGER.trace("GroupId: {}", g); -126 final String a = xpath.evaluate("./str[@name='a']", docs.item(i)); -127 LOGGER.trace("ArtifactId: {}", a); -128 final String v = xpath.evaluate("./str[@name='v']", docs.item(i)); -129 NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET); -130 boolean pomAvailable = false; -131 boolean jarAvailable = false; -132 for (int x = 0; x < atts.getLength(); x++) { -133 final String tmp = xpath.evaluate(".", atts.item(x)); -134 if (".pom".equals(tmp)) { -135 pomAvailable = true; -136 } else if (".jar".equals(tmp)) { -137 jarAvailable = true; -138 } -139 } -140 -141 atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET); -142 boolean useHTTPS = false; -143 for (int x = 0; x < atts.getLength(); x++) { -144 final String tmp = xpath.evaluate(".", atts.item(x)); -145 if ("https".equals(tmp)) { -146 useHTTPS = true; -147 } -148 } -149 LOGGER.trace("Version: {}", v); -150 result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS)); -151 } -152 } -153 } catch (Throwable e) { -154 // Anything else is jacked up XML stuff that we really can't recover from well -155 throw new IOException(e.getMessage(), e); -156 } -157 -158 if (missing) { -159 throw new FileNotFoundException("Artifact not found in Central"); -160 } -161 } else { -162 LOGGER.debug("Could not connect to Central received response code: {} {}", -163 conn.getResponseCode(), conn.getResponseMessage()); -164 throw new IOException("Could not connect to Central"); -165 } -166 return result; -167 } -168 } +113 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +114 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +115 final DocumentBuilder builder = factory.newDocumentBuilder(); +116 final Document doc = builder.parse(conn.getInputStream()); +117 final XPath xpath = XPathFactory.newInstance().newXPath(); +118 final String numFound = xpath.evaluate("/response/result/@numFound", doc); +119 if ("0".equals(numFound)) { +120 missing = true; +121 } else { +122 result = new ArrayList<MavenArtifact>(); +123 final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET); +124 for (int i = 0; i < docs.getLength(); i++) { +125 final String g = xpath.evaluate("./str[@name='g']", docs.item(i)); +126 LOGGER.trace("GroupId: {}", g); +127 final String a = xpath.evaluate("./str[@name='a']", docs.item(i)); +128 LOGGER.trace("ArtifactId: {}", a); +129 final String v = xpath.evaluate("./str[@name='v']", docs.item(i)); +130 NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET); +131 boolean pomAvailable = false; +132 boolean jarAvailable = false; +133 for (int x = 0; x < atts.getLength(); x++) { +134 final String tmp = xpath.evaluate(".", atts.item(x)); +135 if (".pom".equals(tmp)) { +136 pomAvailable = true; +137 } else if (".jar".equals(tmp)) { +138 jarAvailable = true; +139 } +140 } +141 +142 atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET); +143 boolean useHTTPS = false; +144 for (int x = 0; x < atts.getLength(); x++) { +145 final String tmp = xpath.evaluate(".", atts.item(x)); +146 if ("https".equals(tmp)) { +147 useHTTPS = true; +148 } +149 } +150 LOGGER.trace("Version: {}", v); +151 result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS)); +152 } +153 } +154 } catch (Throwable e) { +155 // Anything else is jacked up XML stuff that we really can't recover from well +156 throw new IOException(e.getMessage(), e); +157 } +158 +159 if (missing) { +160 throw new FileNotFoundException("Artifact not found in Central"); +161 } +162 } else { +163 LOGGER.debug("Could not connect to Central received response code: {} {}", +164 conn.getResponseCode(), conn.getResponseMessage()); +165 throw new IOException("Could not connect to Central"); +166 } +167 return result; +168 } +169 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/central/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/central/package-frame.html index 118ce92d0..d4ae137f5 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/central/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/central/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.central diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/central/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/central/package-summary.html index fa8ea42f5..fb5a82171 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/central/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/central/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.central diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/composer/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/composer/package-frame.html index 2bbd651de..d9d73a212 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/composer/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/composer/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.composer diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/composer/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/composer/package-summary.html index 77209fccf..3fe97fabb 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/composer/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/composer/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.composer diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/package-frame.html index cd9c39350..bd72af3a6 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.cpe diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/package-summary.html index 17e1a2016..7ecea126b 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/cpe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.cpe diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/cwe/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/cwe/package-frame.html index 372d0b944..676ea9626 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/cwe/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/cwe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.cwe diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/cwe/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/cwe/package-summary.html index 07f6df814..fcffb18bf 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/cwe/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/cwe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.cwe diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/lucene/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/lucene/package-frame.html index dbdb4b256..aaba9500a 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/lucene/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/lucene/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.lucene diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/lucene/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/lucene/package-summary.html index c260699c2..7ef5bffc1 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/lucene/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/lucene/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.lucene diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/NexusSearch.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/NexusSearch.html index 45df20fa9..53f965702 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/NexusSearch.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/NexusSearch.html @@ -33,165 +33,163 @@ 25 import javax.xml.parsers.DocumentBuilderFactory; 26 import javax.xml.xpath.XPath; 27 import javax.xml.xpath.XPathFactory; -28 import org.owasp.dependencycheck.utils.InvalidSettingException; -29 import org.owasp.dependencycheck.utils.Settings; -30 import org.owasp.dependencycheck.utils.URLConnectionFactory; -31 import org.slf4j.Logger; -32 import org.slf4j.LoggerFactory; -33 import org.w3c.dom.Document; -34 -35 /** -36 * Class of methods to search Nexus repositories. -37 * -38 * @author colezlaw -39 */ -40 public class NexusSearch { -41 -42 /** -43 * The root URL for the Nexus repository service. -44 */ -45 private final URL rootURL; -46 -47 /** -48 * Whether to use the Proxy when making requests. -49 */ -50 private boolean useProxy; -51 /** -52 * Used for logging. -53 */ -54 private static final Logger LOGGER = LoggerFactory.getLogger(NexusSearch.class); -55 -56 /** -57 * Creates a NexusSearch for the given repository URL. -58 * -59 * @param rootURL the root URL of the repository on which searches should execute. full URL's are calculated relative to this -60 * URL, so it should end with a / -61 */ -62 public NexusSearch(URL rootURL) { -63 this.rootURL = rootURL; -64 try { -65 if (null != Settings.getString(Settings.KEYS.PROXY_SERVER) -66 && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY)) { -67 useProxy = true; -68 LOGGER.debug("Using proxy"); -69 } else { -70 useProxy = false; -71 LOGGER.debug("Not using proxy"); -72 } -73 } catch (InvalidSettingException ise) { -74 useProxy = false; -75 } -76 } -77 -78 /** -79 * Searches the configured Nexus repository for the given sha1 hash. If the artifact is found, a <code>MavenArtifact</code> is -80 * populated with the coordinate information. -81 * -82 * @param sha1 The SHA-1 hash string for which to search -83 * @return the populated Maven coordinates -84 * @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not found. -85 */ -86 public MavenArtifact searchSha1(String sha1) throws IOException { -87 if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) { -88 throw new IllegalArgumentException("Invalid SHA1 format"); -89 } +28 +29 import org.owasp.dependencycheck.utils.InvalidSettingException; +30 import org.owasp.dependencycheck.utils.Settings; +31 import org.owasp.dependencycheck.utils.URLConnectionFactory; +32 import org.slf4j.Logger; +33 import org.slf4j.LoggerFactory; +34 import org.w3c.dom.Document; +35 +36 /** +37 * Class of methods to search Nexus repositories. +38 * +39 * @author colezlaw +40 */ +41 public class NexusSearch { +42 +43 /** +44 * The root URL for the Nexus repository service. +45 */ +46 private final URL rootURL; +47 +48 /** +49 * Whether to use the Proxy when making requests. +50 */ +51 private final boolean useProxy; +52 /** +53 * Used for logging. +54 */ +55 private static final Logger LOGGER = LoggerFactory.getLogger(NexusSearch.class); +56 +57 /** +58 * Creates a NexusSearch for the given repository URL. +59 * +60 * @param rootURL the root URL of the repository on which searches should +61 * execute. full URL's are calculated relative to this URL, so it should end +62 * with a / +63 * @param useProxy flag indicating if the proxy settings should be used +64 */ +65 public NexusSearch(URL rootURL, boolean useProxy) { +66 this.rootURL = rootURL; +67 this.useProxy = useProxy; +68 LOGGER.debug("Using proxy: {}", useProxy); +69 } +70 +71 /** +72 * Searches the configured Nexus repository for the given sha1 hash. If the +73 * artifact is found, a <code>MavenArtifact</code> is populated with the +74 * coordinate information. +75 * +76 * @param sha1 The SHA-1 hash string for which to search +77 * @return the populated Maven coordinates +78 * @throws IOException if it's unable to connect to the specified repository +79 * or if the specified artifact is not found. +80 */ +81 public MavenArtifact searchSha1(String sha1) throws IOException { +82 if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) { +83 throw new IllegalArgumentException("Invalid SHA1 format"); +84 } +85 +86 final URL url = new URL(rootURL, String.format("identify/sha1/%s", +87 sha1.toLowerCase())); +88 +89 LOGGER.debug("Searching Nexus url {}", url); 90 -91 final URL url = new URL(rootURL, String.format("identify/sha1/%s", -92 sha1.toLowerCase())); -93 -94 LOGGER.debug("Searching Nexus url {}", url); -95 -96 // Determine if we need to use a proxy. The rules: -97 // 1) If the proxy is set, AND the setting is set to true, use the proxy -98 // 2) Otherwise, don't use the proxy (either the proxy isn't configured, -99 // or proxy is specifically set to false -100 HttpURLConnection conn; -101 conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); -102 conn.setDoOutput(true); +91 // Determine if we need to use a proxy. The rules: +92 // 1) If the proxy is set, AND the setting is set to true, use the proxy +93 // 2) Otherwise, don't use the proxy (either the proxy isn't configured, +94 // or proxy is specifically set to false +95 HttpURLConnection conn; +96 conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); +97 conn.setDoOutput(true); +98 +99 // JSON would be more elegant, but there's not currently a dependency +100 // on JSON, so don't want to add one just for this +101 conn.addRequestProperty("Accept", "application/xml"); +102 conn.connect(); 103 -104 // JSON would be more elegant, but there's not currently a dependency -105 // on JSON, so don't want to add one just for this -106 conn.addRequestProperty("Accept", "application/xml"); -107 conn.connect(); -108 -109 if (conn.getResponseCode() == 200) { -110 try { -111 final DocumentBuilder builder = DocumentBuilderFactory -112 .newInstance().newDocumentBuilder(); -113 final Document doc = builder.parse(conn.getInputStream()); -114 final XPath xpath = XPathFactory.newInstance().newXPath(); -115 final String groupId = xpath -116 .evaluate( -117 "/org.sonatype.nexus.rest.model.NexusArtifact/groupId", -118 doc); -119 final String artifactId = xpath.evaluate( -120 "/org.sonatype.nexus.rest.model.NexusArtifact/artifactId", -121 doc); -122 final String version = xpath -123 .evaluate( -124 "/org.sonatype.nexus.rest.model.NexusArtifact/version", -125 doc); -126 final String link = xpath -127 .evaluate( -128 "/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink", -129 doc); -130 final String pomLink = xpath -131 .evaluate( -132 "/org.sonatype.nexus.rest.model.NexusArtifact/pomLink", -133 doc); -134 final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version); -135 if (link != null && !link.isEmpty()) { -136 ma.setArtifactUrl(link); -137 } -138 if (pomLink != null && !pomLink.isEmpty()) { -139 ma.setPomUrl(pomLink); -140 } -141 return ma; -142 } catch (Throwable e) { -143 // Anything else is jacked-up XML stuff that we really can't recover -144 // from well -145 throw new IOException(e.getMessage(), e); -146 } -147 } else if (conn.getResponseCode() == 404) { -148 throw new FileNotFoundException("Artifact not found in Nexus"); -149 } else { -150 LOGGER.debug("Could not connect to Nexus received response code: {} {}", -151 conn.getResponseCode(), conn.getResponseMessage()); -152 throw new IOException("Could not connect to Nexus"); -153 } -154 } -155 -156 /** -157 * Do a preflight request to see if the repository is actually working. -158 * -159 * @return whether the repository is listening and returns the /status URL correctly -160 */ -161 public boolean preflightRequest() { -162 HttpURLConnection conn; -163 try { -164 final URL url = new URL(rootURL, "status"); -165 conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); -166 conn.addRequestProperty("Accept", "application/xml"); -167 conn.connect(); -168 if (conn.getResponseCode() != 200) { -169 LOGGER.warn("Expected 200 result from Nexus, got {}", conn.getResponseCode()); -170 return false; -171 } -172 final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); -173 final Document doc = builder.parse(conn.getInputStream()); -174 if (!"status".equals(doc.getDocumentElement().getNodeName())) { -175 LOGGER.warn("Expected root node name of status, got {}", doc.getDocumentElement().getNodeName()); -176 return false; -177 } -178 } catch (Throwable e) { -179 return false; -180 } -181 -182 return true; -183 } -184 } -185 -186 // vim: cc=120:sw=4:ts=4:sts=4 +104 switch (conn.getResponseCode()) { +105 case 200: +106 try { +107 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +108 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +109 final DocumentBuilder builder = factory.newDocumentBuilder(); +110 final Document doc = builder.parse(conn.getInputStream()); +111 final XPath xpath = XPathFactory.newInstance().newXPath(); +112 final String groupId = xpath +113 .evaluate( +114 "/org.sonatype.nexus.rest.model.NexusArtifact/groupId", +115 doc); +116 final String artifactId = xpath.evaluate( +117 "/org.sonatype.nexus.rest.model.NexusArtifact/artifactId", +118 doc); +119 final String version = xpath +120 .evaluate( +121 "/org.sonatype.nexus.rest.model.NexusArtifact/version", +122 doc); +123 final String link = xpath +124 .evaluate( +125 "/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink", +126 doc); +127 final String pomLink = xpath +128 .evaluate( +129 "/org.sonatype.nexus.rest.model.NexusArtifact/pomLink", +130 doc); +131 final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version); +132 if (link != null && !link.isEmpty()) { +133 ma.setArtifactUrl(link); +134 } +135 if (pomLink != null && !pomLink.isEmpty()) { +136 ma.setPomUrl(pomLink); +137 } +138 return ma; +139 } catch (Throwable e) { +140 // Anything else is jacked-up XML stuff that we really can't recover +141 // from well +142 throw new IOException(e.getMessage(), e); +143 } +144 case 404: +145 throw new FileNotFoundException("Artifact not found in Nexus"); +146 default: +147 LOGGER.debug("Could not connect to Nexus received response code: {} {}", +148 conn.getResponseCode(), conn.getResponseMessage()); +149 throw new IOException("Could not connect to Nexus"); +150 } +151 } +152 +153 /** +154 * Do a preflight request to see if the repository is actually working. +155 * +156 * @return whether the repository is listening and returns the /status URL +157 * correctly +158 */ +159 public boolean preflightRequest() { +160 HttpURLConnection conn; +161 try { +162 final URL url = new URL(rootURL, "status"); +163 conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); +164 conn.addRequestProperty("Accept", "application/xml"); +165 conn.connect(); +166 if (conn.getResponseCode() != 200) { +167 LOGGER.warn("Expected 200 result from Nexus, got {}", conn.getResponseCode()); +168 return false; +169 } +170 final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); +171 final Document doc = builder.parse(conn.getInputStream()); +172 if (!"status".equals(doc.getDocumentElement().getNodeName())) { +173 LOGGER.warn("Expected root node name of status, got {}", doc.getDocumentElement().getNodeName()); +174 return false; +175 } +176 } catch (Throwable e) { +177 return false; +178 } +179 +180 return true; +181 } +182 } +183 +184 // vim: cc=120:sw=4:ts=4:sts=4
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/package-frame.html index 23bb8a19d..2fa173dea 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nexus diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/package-summary.html index bb2853d20..ca44efdd6 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nexus/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nexus diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.html index 6714f54b9..8dc802819 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.html @@ -44,49 +44,53 @@ 36 * Gets the string value of a node or null if it's not present 37 * 38 * @param n the node to test -39 * @return the string content of the node, or null if the node itself is null -40 */ -41 private String getOrNull(Node n) { -42 if (n != null) { -43 return n.getTextContent(); -44 } else { -45 return null; -46 } -47 } -48 -49 /** -50 * Parse an input stream and return the resulting {@link NugetPackage}. -51 * -52 * @param stream the input stream to parse -53 * @return the populated bean -54 * @throws NuspecParseException when an exception occurs -55 */ -56 @Override -57 public NugetPackage parse(InputStream stream) throws NuspecParseException { -58 try { -59 final Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream); -60 final XPath xpath = XPathFactory.newInstance().newXPath(); -61 final NugetPackage nuspec = new NugetPackage(); -62 -63 if (xpath.evaluate("/package/metadata/id", d, XPathConstants.NODE) == null -64 || xpath.evaluate("/package/metadata/version", d, XPathConstants.NODE) == null -65 || xpath.evaluate("/package/metadata/authors", d, XPathConstants.NODE) == null -66 || xpath.evaluate("/package/metadata/description", d, XPathConstants.NODE) == null) { -67 throw new NuspecParseException("Invalid Nuspec format"); -68 } -69 -70 nuspec.setId(xpath.evaluate("/package/metadata/id", d)); -71 nuspec.setVersion(xpath.evaluate("/package/metadata/version", d)); -72 nuspec.setAuthors(xpath.evaluate("/package/metadata/authors", d)); -73 nuspec.setOwners(getOrNull((Node) xpath.evaluate("/package/metadata/owners", d, XPathConstants.NODE))); -74 nuspec.setLicenseUrl(getOrNull((Node) xpath.evaluate("/package/metadata/licenseUrl", d, XPathConstants.NODE))); -75 nuspec.setTitle(getOrNull((Node) xpath.evaluate("/package/metadata/title", d, XPathConstants.NODE))); -76 return nuspec; -77 } catch (Throwable e) { -78 throw new NuspecParseException("Unable to parse nuspec", e); -79 } -80 } -81 } +39 * @return the string content of the node, or null if the node itself is +40 * null +41 */ +42 private String getOrNull(Node n) { +43 if (n != null) { +44 return n.getTextContent(); +45 } else { +46 return null; +47 } +48 } +49 +50 /** +51 * Parse an input stream and return the resulting {@link NugetPackage}. +52 * +53 * @param stream the input stream to parse +54 * @return the populated bean +55 * @throws NuspecParseException when an exception occurs +56 */ +57 @Override +58 public NugetPackage parse(InputStream stream) throws NuspecParseException { +59 try { +60 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +61 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +62 final Document d = factory.newDocumentBuilder().parse(stream); +63 +64 final XPath xpath = XPathFactory.newInstance().newXPath(); +65 final NugetPackage nuspec = new NugetPackage(); +66 +67 if (xpath.evaluate("/package/metadata/id", d, XPathConstants.NODE) == null +68 || xpath.evaluate("/package/metadata/version", d, XPathConstants.NODE) == null +69 || xpath.evaluate("/package/metadata/authors", d, XPathConstants.NODE) == null +70 || xpath.evaluate("/package/metadata/description", d, XPathConstants.NODE) == null) { +71 throw new NuspecParseException("Invalid Nuspec format"); +72 } +73 +74 nuspec.setId(xpath.evaluate("/package/metadata/id", d)); +75 nuspec.setVersion(xpath.evaluate("/package/metadata/version", d)); +76 nuspec.setAuthors(xpath.evaluate("/package/metadata/authors", d)); +77 nuspec.setOwners(getOrNull((Node) xpath.evaluate("/package/metadata/owners", d, XPathConstants.NODE))); +78 nuspec.setLicenseUrl(getOrNull((Node) xpath.evaluate("/package/metadata/licenseUrl", d, XPathConstants.NODE))); +79 nuspec.setTitle(getOrNull((Node) xpath.evaluate("/package/metadata/title", d, XPathConstants.NODE))); +80 return nuspec; +81 } catch (Throwable e) { +82 throw new NuspecParseException("Unable to parse nuspec", e); +83 } +84 } +85 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/package-frame.html index 997d8d324..de7c37dd5 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/package-summary.html index becd19a0c..6a5313968 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nuget/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html index 1d4d2db7a..acfa82354 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html @@ -127,7 +127,7 @@ 119 * @throws DatabaseException thrown if there is an error opening the 120 * database connection 121 */ -122 public final void open() throws DatabaseException { +122 public final synchronized void open() throws DatabaseException { 123 if (!isOpen()) { 124 conn = ConnectionFactory.getConnection(); 125 } @@ -137,7 +137,7 @@ 129 * Closes the DB4O database. Close should be called on this object when it 130 * is done being used. 131 */ -132 public void close() { +132 public synchronized void close() { 133 if (conn != null) { 134 try { 135 conn.close(); @@ -157,7 +157,7 @@ 149 * 150 * @return whether the database connection is open or closed 151 */ -152 public boolean isOpen() { +152 public synchronized boolean isOpen() { 153 return conn != null; 154 } 155 @@ -166,7 +166,7 @@ 158 * 159 * @throws SQLException thrown if a SQL Exception occurs 160 */ -161 public void commit() throws SQLException { +161 public synchronized void commit() throws SQLException { 162 //temporary remove this as autocommit is on. 163 //if (conn != null) { 164 // conn.commit(); @@ -210,7 +210,7 @@ 202 * analyzed 203 * @return a set of vulnerable software 204 */ -205 public Set<VulnerableSoftware> getCPEs(String vendor, String product) { +205 public synchronized Set<VulnerableSoftware> getCPEs(String vendor, String product) { 206 final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>(); 207 ResultSet rs = null; 208 PreparedStatement ps = null; @@ -242,7 +242,7 @@ 234 * @throws DatabaseException thrown when there is an error retrieving the 235 * data from the DB 236 */ -237 public Set<Pair<String, String>> getVendorProductList() throws DatabaseException { +237 public synchronized Set<Pair<String, String>> getVendorProductList() throws DatabaseException { 238 final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>(); 239 ResultSet rs = null; 240 PreparedStatement ps = null; @@ -267,7 +267,7 @@ 259 * 260 * @return the properties from the database 261 */ -262 Properties getProperties() { +262 synchronized Properties getProperties() { 263 final Properties prop = new Properties(); 264 PreparedStatement ps = null; 265 ResultSet rs = null; @@ -293,7 +293,7 @@ 285 * @param key the property key 286 * @param value the property value 287 */ -288 void saveProperty(String key, String value) { +288 synchronized void saveProperty(String key, String value) { 289 try { 290 try { 291 final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY")); @@ -336,7 +336,7 @@ 328 * @return a list of Vulnerabilities 329 * @throws DatabaseException thrown if there is an exception retrieving data 330 */ -331 public List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException { +331 public synchronized List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException { 332 final VulnerableSoftware cpe = new VulnerableSoftware(); 333 try { 334 cpe.parseName(cpeStr); @@ -397,7 +397,7 @@ 389 * @return a vulnerability object 390 * @throws DatabaseException if an exception occurs 391 */ -392 public Vulnerability getVulnerability(String cve) throws DatabaseException { +392 public synchronized Vulnerability getVulnerability(String cve) throws DatabaseException { 393 PreparedStatement psV = null; 394 PreparedStatement psR = null; 395 PreparedStatement psS = null; @@ -470,7 +470,7 @@ 462 * @param vuln the vulnerability to add to the database 463 * @throws DatabaseException is thrown if the database 464 */ -465 public void updateVulnerability(Vulnerability vuln) throws DatabaseException { +465 public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException { 466 PreparedStatement selectVulnerabilityId = null; 467 PreparedStatement deleteVulnerability = null; 468 PreparedStatement deleteReferences = null; @@ -646,7 +646,7 @@ 638 * 639 * @return <code>true</code> if data exists; otherwise <code>false</code> 640 */ -641 public boolean dataExists() { +641 public synchronized boolean dataExists() { 642 Statement cs = null; 643 ResultSet rs = null; 644 try { @@ -682,7 +682,7 @@ 674 * updates. This should be called after all updates have been completed to 675 * ensure orphan entries are removed. 676 */ -677 public void cleanupDatabase() { +677 public synchronized void cleanupDatabase() { 678 PreparedStatement ps = null; 679 try { 680 ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS")); @@ -820,7 +820,7 @@ 812 * 813 * Deletes unused dictionary entries from the database. 814 */ -815 public void deleteUnusedCpe() { +815 public synchronized void deleteUnusedCpe() { 816 PreparedStatement ps = null; 817 try { 818 ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE")); @@ -842,7 +842,7 @@ 834 * @param vendor the CPE vendor 835 * @param product the CPE product 836 */ -837 public void addCpe(String cpe, String vendor, String product) { +837 public synchronized void addCpe(String cpe, String vendor, String product) { 838 PreparedStatement ps = null; 839 try { 840 ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE")); diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html index 32bb11201..7462a25e1 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nvdcve diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/package-summary.html index afcb19c07..e02440e8e 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/nvdcve/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.nvdcve diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html index 7a0aec0a8..4551a7929 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html @@ -52,162 +52,170 @@ 44 45 /** 46 * -47 * This class is currently unused and if enabled will likely not work on MySQL as the MERGE statement is used. -48 * -49 * The CpeUpdater is designed to download the CPE data file from NIST and import the data into the database. However, as this -50 * currently adds no beneficial data, compared to what is in the CPE data contained in the CVE data files, this class is not -51 * currently used. The code is being kept as a future update may utilize more data from the CPE xml files. -52 * -53 * @author Jeremy Long -54 */ -55 public class CpeUpdater extends BaseUpdater implements CachedWebDataSource { -56 -57 /** -58 * Static logger. -59 */ -60 private static final Logger LOGGER = LoggerFactory.getLogger(CpeUpdater.class); -61 -62 @Override -63 public void update() throws UpdateException { -64 try { -65 openDataStores(); -66 if (updateNeeded()) { -67 LOGGER.info("Updating the Common Platform Enumeration (CPE)"); -68 final File xml = downloadCpe(); -69 final List<Cpe> cpes = processXML(xml); -70 getCveDB().deleteUnusedCpe(); -71 for (Cpe cpe : cpes) { -72 getCveDB().addCpe(cpe.getValue(), cpe.getVendor(), cpe.getProduct()); -73 } -74 final long now = System.currentTimeMillis(); -75 getProperties().save(LAST_CPE_UPDATE, Long.toString(now)); -76 LOGGER.info("CPE update complete"); -77 } -78 } finally { -79 closeDataStores(); -80 } -81 } -82 -83 /** -84 * Downloads the CPE XML file. -85 * -86 * @return the file reference to the CPE.xml file -87 * @throws UpdateException thrown if there is an issue downloading the XML file -88 */ -89 private File downloadCpe() throws UpdateException { -90 File xml; -91 final URL url; -92 try { -93 url = new URL(Settings.getString(Settings.KEYS.CPE_URL)); -94 xml = File.createTempFile("cpe", ".xml", Settings.getTempDirectory()); -95 Downloader.fetchFile(url, xml); -96 if (url.toExternalForm().endsWith(".xml.gz")) { -97 extractGzip(xml); -98 } -99 -100 } catch (MalformedURLException ex) { -101 throw new UpdateException("Invalid CPE URL", ex); -102 } catch (DownloadFailedException ex) { -103 throw new UpdateException("Unable to download CPE XML file", ex); -104 } catch (IOException ex) { -105 throw new UpdateException("Unable to create temporary file to download CPE", ex); -106 } -107 return xml; -108 } -109 -110 /** -111 * Parses the CPE XML file to return a list of CPE entries. -112 * -113 * @param xml the CPE data file -114 * @return the list of CPE entries -115 * @throws UpdateException thrown if there is an issue with parsing the XML file -116 */ -117 private List<Cpe> processXML(final File xml) throws UpdateException { -118 try { -119 final SAXParserFactory factory = SAXParserFactory.newInstance(); -120 final SAXParser saxParser = factory.newSAXParser(); -121 final CPEHandler handler = new CPEHandler(); -122 saxParser.parse(xml, handler); -123 return handler.getData(); -124 } catch (ParserConfigurationException ex) { -125 throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Issue", ex); -126 } catch (SAXException ex) { -127 throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Exception", ex); -128 } catch (IOException ex) { -129 throw new UpdateException("Unable to parse CPE XML file due to IO Failure", ex); -130 } -131 } -132 -133 /** -134 * Checks to find the last time the CPE data was refreshed and if it needs to be updated. -135 * -136 * @return true if the CPE data should be refreshed -137 */ -138 private boolean updateNeeded() { -139 final long now = System.currentTimeMillis(); -140 final int days = Settings.getInt(Settings.KEYS.CPE_MODIFIED_VALID_FOR_DAYS, 30); -141 long timestamp = 0; -142 final String ts = getProperties().getProperty(LAST_CPE_UPDATE); -143 if (ts != null && ts.matches("^[0-9]+$")) { -144 timestamp = Long.parseLong(ts); -145 } -146 return !DateUtil.withinDateRange(timestamp, now, days); -147 } -148 -149 /** -150 * Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file specified. -151 * -152 * @param file the archive file -153 * @throws FileNotFoundException thrown if the file does not exist -154 * @throws IOException thrown if there is an error extracting the file. -155 */ -156 private void extractGzip(File file) throws FileNotFoundException, IOException { -157 //TODO - move this to a util class as it is duplicative of (copy of) code in the DownloadTask -158 final String originalPath = file.getPath(); -159 final File gzip = new File(originalPath + ".gz"); -160 if (gzip.isFile() && !gzip.delete()) { -161 LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString()); -162 gzip.deleteOnExit(); -163 } -164 if (!file.renameTo(gzip)) { -165 throw new IOException("Unable to rename '" + file.getPath() + "'"); -166 } -167 final File newfile = new File(originalPath); -168 -169 final byte[] buffer = new byte[4096]; -170 -171 GZIPInputStream cin = null; -172 FileOutputStream out = null; -173 try { -174 cin = new GZIPInputStream(new FileInputStream(gzip)); -175 out = new FileOutputStream(newfile); +47 * This class is currently unused and if enabled will likely not work on MySQL +48 * as the MERGE statement is used. +49 * +50 * The CpeUpdater is designed to download the CPE data file from NIST and import +51 * the data into the database. However, as this currently adds no beneficial +52 * data, compared to what is in the CPE data contained in the CVE data files, +53 * this class is not currently used. The code is being kept as a future update +54 * may utilize more data from the CPE XML files. +55 * +56 * @author Jeremy Long +57 */ +58 public class CpeUpdater extends BaseUpdater implements CachedWebDataSource { +59 +60 /** +61 * Static logger. +62 */ +63 private static final Logger LOGGER = LoggerFactory.getLogger(CpeUpdater.class); +64 +65 @Override +66 public void update() throws UpdateException { +67 try { +68 openDataStores(); +69 if (updateNeeded()) { +70 LOGGER.info("Updating the Common Platform Enumeration (CPE)"); +71 final File xml = downloadCpe(); +72 final List<Cpe> cpes = processXML(xml); +73 getCveDB().deleteUnusedCpe(); +74 for (Cpe cpe : cpes) { +75 getCveDB().addCpe(cpe.getValue(), cpe.getVendor(), cpe.getProduct()); +76 } +77 final long now = System.currentTimeMillis(); +78 getProperties().save(LAST_CPE_UPDATE, Long.toString(now)); +79 LOGGER.info("CPE update complete"); +80 } +81 } finally { +82 closeDataStores(); +83 } +84 } +85 +86 /** +87 * Downloads the CPE XML file. +88 * +89 * @return the file reference to the CPE.xml file +90 * @throws UpdateException thrown if there is an issue downloading the XML +91 * file +92 */ +93 private File downloadCpe() throws UpdateException { +94 File xml; +95 final URL url; +96 try { +97 url = new URL(Settings.getString(Settings.KEYS.CPE_URL)); +98 xml = File.createTempFile("cpe", ".xml", Settings.getTempDirectory()); +99 Downloader.fetchFile(url, xml); +100 if (url.toExternalForm().endsWith(".xml.gz")) { +101 extractGzip(xml); +102 } +103 +104 } catch (MalformedURLException ex) { +105 throw new UpdateException("Invalid CPE URL", ex); +106 } catch (DownloadFailedException ex) { +107 throw new UpdateException("Unable to download CPE XML file", ex); +108 } catch (IOException ex) { +109 throw new UpdateException("Unable to create temporary file to download CPE", ex); +110 } +111 return xml; +112 } +113 +114 /** +115 * Parses the CPE XML file to return a list of CPE entries. +116 * +117 * @param xml the CPE data file +118 * @return the list of CPE entries +119 * @throws UpdateException thrown if there is an issue with parsing the XML +120 * file +121 */ +122 private List<Cpe> processXML(final File xml) throws UpdateException { +123 try { +124 final SAXParserFactory factory = SAXParserFactory.newInstance(); +125 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +126 final SAXParser saxParser = factory.newSAXParser(); +127 final CPEHandler handler = new CPEHandler(); +128 saxParser.parse(xml, handler); +129 return handler.getData(); +130 } catch (ParserConfigurationException ex) { +131 throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Issue", ex); +132 } catch (SAXException ex) { +133 throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Exception", ex); +134 } catch (IOException ex) { +135 throw new UpdateException("Unable to parse CPE XML file due to IO Failure", ex); +136 } +137 } +138 +139 /** +140 * Checks to find the last time the CPE data was refreshed and if it needs +141 * to be updated. +142 * +143 * @return true if the CPE data should be refreshed +144 */ +145 private boolean updateNeeded() { +146 final long now = System.currentTimeMillis(); +147 final int days = Settings.getInt(Settings.KEYS.CPE_MODIFIED_VALID_FOR_DAYS, 30); +148 long timestamp = 0; +149 final String ts = getProperties().getProperty(LAST_CPE_UPDATE); +150 if (ts != null && ts.matches("^[0-9]+$")) { +151 timestamp = Long.parseLong(ts); +152 } +153 return !DateUtil.withinDateRange(timestamp, now, days); +154 } +155 +156 /** +157 * Extracts the file contained in a gzip archive. The extracted file is +158 * placed in the exact same path as the file specified. +159 * +160 * @param file the archive file +161 * @throws FileNotFoundException thrown if the file does not exist +162 * @throws IOException thrown if there is an error extracting the file. +163 */ +164 private void extractGzip(File file) throws FileNotFoundException, IOException { +165 //TODO - move this to a util class as it is duplicative of (copy of) code in the DownloadTask +166 final String originalPath = file.getPath(); +167 final File gzip = new File(originalPath + ".gz"); +168 if (gzip.isFile() && !gzip.delete()) { +169 LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString()); +170 gzip.deleteOnExit(); +171 } +172 if (!file.renameTo(gzip)) { +173 throw new IOException("Unable to rename '" + file.getPath() + "'"); +174 } +175 final File newfile = new File(originalPath); 176 -177 int len; -178 while ((len = cin.read(buffer)) > 0) { -179 out.write(buffer, 0, len); -180 } -181 } finally { -182 if (cin != null) { -183 try { -184 cin.close(); -185 } catch (IOException ex) { -186 LOGGER.trace("ignore", ex); -187 } +177 final byte[] buffer = new byte[4096]; +178 +179 GZIPInputStream cin = null; +180 FileOutputStream out = null; +181 try { +182 cin = new GZIPInputStream(new FileInputStream(gzip)); +183 out = new FileOutputStream(newfile); +184 +185 int len; +186 while ((len = cin.read(buffer)) > 0) { +187 out.write(buffer, 0, len); 188 } -189 if (out != null) { -190 try { -191 out.close(); -192 } catch (IOException ex) { -193 LOGGER.trace("ignore", ex); -194 } -195 } -196 if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) { -197 LOGGER.debug("Failed to delete temporary file {}", gzip.toString()); -198 gzip.deleteOnExit(); -199 } -200 } -201 } -202 } +189 } finally { +190 if (cin != null) { +191 try { +192 cin.close(); +193 } catch (IOException ex) { +194 LOGGER.trace("ignore", ex); +195 } +196 } +197 if (out != null) { +198 try { +199 out.close(); +200 } catch (IOException ex) { +201 LOGGER.trace("ignore", ex); +202 } +203 } +204 if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) { +205 LOGGER.debug("Failed to delete temporary file {}", gzip.toString()); +206 gzip.deleteOnExit(); +207 } +208 } +209 } +210 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html index 1edd3a333..e5e5eaa97 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html @@ -126,7 +126,7 @@ 118 } 119 } catch (DatabaseException ex) { 120 LOGGER.debug("Database Exception opening databases to retrieve properties", ex); -121 throw new UpdateException("Error occured updating database properties."); +121 throw new UpdateException("Error occurred updating database properties."); 122 } catch (InvalidSettingException ex) { 123 LOGGER.debug("Unable to determine if autoupdate is enabled", ex); 124 } finally { diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/cpe/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/cpe/package-frame.html index b7e43b555..bc1530fb5 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/cpe/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/cpe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.cpe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update.cpe diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/cpe/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/cpe/package-summary.html index e1c6da995..59b3db0a5 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/cpe/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/cpe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.cpe + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update.cpe diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/exception/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/exception/package-frame.html index 3af3b09a8..be533c5e2 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/exception/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/exception/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.exception + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update.exception diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/exception/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/exception/package-summary.html index a104f3f14..31a355e55 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/exception/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/exception/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.exception + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update.exception diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/ProcessTask.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/ProcessTask.html index ac404cb47..f6000e478 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/ProcessTask.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/ProcessTask.html @@ -46,151 +46,158 @@ 38 import org.xml.sax.SAXException; 39 40 /** -41 * A callable task that will process a given set of NVD CVE xml files and update the Cve Database accordingly. -42 * -43 * @author Jeremy Long -44 */ -45 public class ProcessTask implements Callable<ProcessTask> { -46 -47 /** -48 * The logger. -49 */ -50 private static final Logger LOGGER = LoggerFactory.getLogger(ProcessTask.class); -51 /** -52 * A field to store any update exceptions that occur during the "call". -53 */ -54 private UpdateException exception = null; -55 -56 /** -57 * Get the value of exception. -58 * -59 * @return the value of exception -60 */ -61 public UpdateException getException() { -62 return exception; -63 } -64 -65 /** -66 * Set the value of exception. -67 * -68 * @param exception new value of exception -69 */ -70 public void setException(UpdateException exception) { -71 this.exception = exception; -72 } -73 /** -74 * A reference to the CveDB. -75 */ -76 private final CveDB cveDB; -77 /** -78 * A reference to the callable download task. -79 */ -80 private final DownloadTask filePair; -81 /** -82 * A reference to the properties. -83 */ -84 private final DatabaseProperties properties; -85 /** -86 * A reference to the global settings object. -87 */ -88 private final Settings settings; -89 -90 /** -91 * Constructs a new ProcessTask used to process an NVD CVE update. -92 * -93 * @param cveDB the data store object -94 * @param filePair the download task that contains the URL references to download -95 * @param settings a reference to the global settings object; this is necessary so that when the thread is started the -96 * dependencies have a correct reference to the global settings. -97 */ -98 public ProcessTask(final CveDB cveDB, final DownloadTask filePair, Settings settings) { -99 this.cveDB = cveDB; -100 this.filePair = filePair; -101 this.properties = cveDB.getDatabaseProperties(); -102 this.settings = settings; -103 } -104 -105 /** -106 * Implements the callable interface. -107 * -108 * @return this object -109 * @throws Exception thrown if there is an exception; note that any UpdateExceptions are simply added to the tasks exception -110 * collection -111 */ -112 @Override -113 public ProcessTask call() throws Exception { -114 try { -115 Settings.setInstance(settings); -116 processFiles(); -117 } catch (UpdateException ex) { -118 this.exception = ex; -119 } finally { -120 Settings.cleanup(false); -121 } -122 return this; -123 } -124 -125 /** -126 * Imports the NVD CVE XML File into the Lucene Index. -127 * -128 * @param file the file containing the NVD CVE XML -129 * @param oldVersion contains the file containing the NVD CVE XML 1.2 -130 * @throws ParserConfigurationException is thrown if there is a parser configuration exception -131 * @throws SAXException is thrown if there is a SAXException -132 * @throws IOException is thrown if there is a IO Exception -133 * @throws SQLException is thrown if there is a SQL exception -134 * @throws DatabaseException is thrown if there is a database exception -135 * @throws ClassNotFoundException thrown if the h2 database driver cannot be loaded -136 */ -137 protected void importXML(File file, File oldVersion) throws ParserConfigurationException, -138 SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException { -139 -140 final SAXParserFactory factory = SAXParserFactory.newInstance(); -141 final SAXParser saxParser = factory.newSAXParser(); -142 -143 final NvdCve12Handler cve12Handler = new NvdCve12Handler(); -144 saxParser.parse(oldVersion, cve12Handler); -145 final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities(); -146 -147 final NvdCve20Handler cve20Handler = new NvdCve20Handler(); -148 cve20Handler.setCveDB(cveDB); -149 cve20Handler.setPrevVersionVulnMap(prevVersionVulnMap); -150 saxParser.parse(file, cve20Handler); -151 } +41 * A callable task that will process a given set of NVD CVE xml files and update +42 * the Cve Database accordingly. +43 * +44 * @author Jeremy Long +45 */ +46 public class ProcessTask implements Callable<ProcessTask> { +47 +48 /** +49 * The logger. +50 */ +51 private static final Logger LOGGER = LoggerFactory.getLogger(ProcessTask.class); +52 /** +53 * A field to store any update exceptions that occur during the "call". +54 */ +55 private UpdateException exception = null; +56 +57 /** +58 * Get the value of exception. +59 * +60 * @return the value of exception +61 */ +62 public UpdateException getException() { +63 return exception; +64 } +65 +66 /** +67 * Set the value of exception. +68 * +69 * @param exception new value of exception +70 */ +71 public void setException(UpdateException exception) { +72 this.exception = exception; +73 } +74 /** +75 * A reference to the CveDB. +76 */ +77 private final CveDB cveDB; +78 /** +79 * A reference to the callable download task. +80 */ +81 private final DownloadTask filePair; +82 /** +83 * A reference to the properties. +84 */ +85 private final DatabaseProperties properties; +86 /** +87 * A reference to the global settings object. +88 */ +89 private final Settings settings; +90 +91 /** +92 * Constructs a new ProcessTask used to process an NVD CVE update. +93 * +94 * @param cveDB the data store object +95 * @param filePair the download task that contains the URL references to +96 * download +97 * @param settings a reference to the global settings object; this is +98 * necessary so that when the thread is started the dependencies have a +99 * correct reference to the global settings. +100 */ +101 public ProcessTask(final CveDB cveDB, final DownloadTask filePair, Settings settings) { +102 this.cveDB = cveDB; +103 this.filePair = filePair; +104 this.properties = cveDB.getDatabaseProperties(); +105 this.settings = settings; +106 } +107 +108 /** +109 * Implements the callable interface. +110 * +111 * @return this object +112 * @throws Exception thrown if there is an exception; note that any +113 * UpdateExceptions are simply added to the tasks exception collection +114 */ +115 @Override +116 public ProcessTask call() throws Exception { +117 try { +118 Settings.setInstance(settings); +119 processFiles(); +120 } catch (UpdateException ex) { +121 this.exception = ex; +122 } finally { +123 Settings.cleanup(false); +124 } +125 return this; +126 } +127 +128 /** +129 * Imports the NVD CVE XML File into the Lucene Index. +130 * +131 * @param file the file containing the NVD CVE XML +132 * @param oldVersion contains the file containing the NVD CVE XML 1.2 +133 * @throws ParserConfigurationException is thrown if there is a parser +134 * configuration exception +135 * @throws SAXException is thrown if there is a SAXException +136 * @throws IOException is thrown if there is a IO Exception +137 * @throws SQLException is thrown if there is a SQL exception +138 * @throws DatabaseException is thrown if there is a database exception +139 * @throws ClassNotFoundException thrown if the h2 database driver cannot be +140 * loaded +141 */ +142 protected void importXML(File file, File oldVersion) throws ParserConfigurationException, +143 SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException { +144 +145 final SAXParserFactory factory = SAXParserFactory.newInstance(); +146 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +147 final SAXParser saxParser = factory.newSAXParser(); +148 +149 final NvdCve12Handler cve12Handler = new NvdCve12Handler(); +150 saxParser.parse(oldVersion, cve12Handler); +151 final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities(); 152 -153 /** -154 * Processes the NVD CVE XML file and imports the data into the DB. -155 * -156 * @throws UpdateException thrown if there is an error loading the data into the database -157 */ -158 private void processFiles() throws UpdateException { -159 LOGGER.info("Processing Started for NVD CVE - {}", filePair.getNvdCveInfo().getId()); -160 final long startProcessing = System.currentTimeMillis(); -161 try { -162 importXML(filePair.getFirst(), filePair.getSecond()); -163 cveDB.commit(); -164 properties.save(filePair.getNvdCveInfo()); -165 } catch (FileNotFoundException ex) { -166 throw new UpdateException(ex); -167 } catch (ParserConfigurationException ex) { -168 throw new UpdateException(ex); -169 } catch (SAXException ex) { -170 throw new UpdateException(ex); -171 } catch (IOException ex) { -172 throw new UpdateException(ex); -173 } catch (SQLException ex) { -174 throw new UpdateException(ex); -175 } catch (DatabaseException ex) { -176 throw new UpdateException(ex); -177 } catch (ClassNotFoundException ex) { -178 throw new UpdateException(ex); -179 } finally { -180 filePair.cleanup(); -181 } -182 LOGGER.info("Processing Complete for NVD CVE - {} ({} ms)", filePair.getNvdCveInfo().getId(), -183 System.currentTimeMillis() - startProcessing); -184 } -185 } +153 final NvdCve20Handler cve20Handler = new NvdCve20Handler(); +154 cve20Handler.setCveDB(cveDB); +155 cve20Handler.setPrevVersionVulnMap(prevVersionVulnMap); +156 saxParser.parse(file, cve20Handler); +157 } +158 +159 /** +160 * Processes the NVD CVE XML file and imports the data into the DB. +161 * +162 * @throws UpdateException thrown if there is an error loading the data into +163 * the database +164 */ +165 private void processFiles() throws UpdateException { +166 LOGGER.info("Processing Started for NVD CVE - {}", filePair.getNvdCveInfo().getId()); +167 final long startProcessing = System.currentTimeMillis(); +168 try { +169 importXML(filePair.getFirst(), filePair.getSecond()); +170 cveDB.commit(); +171 properties.save(filePair.getNvdCveInfo()); +172 } catch (FileNotFoundException ex) { +173 throw new UpdateException(ex); +174 } catch (ParserConfigurationException ex) { +175 throw new UpdateException(ex); +176 } catch (SAXException ex) { +177 throw new UpdateException(ex); +178 } catch (IOException ex) { +179 throw new UpdateException(ex); +180 } catch (SQLException ex) { +181 throw new UpdateException(ex); +182 } catch (DatabaseException ex) { +183 throw new UpdateException(ex); +184 } catch (ClassNotFoundException ex) { +185 throw new UpdateException(ex); +186 } finally { +187 filePair.cleanup(); +188 } +189 LOGGER.info("Processing Complete for NVD CVE - {} ({} ms)", filePair.getNvdCveInfo().getId(), +190 System.currentTimeMillis() - startProcessing); +191 } +192 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/package-frame.html index c1f7615ba..0e40eaa42 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update.nvd diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/package-summary.html index 9438d807a..bc8a688a9 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/nvd/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update.nvd diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/package-frame.html index 6d7293b91..434f2b4bd 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/package-summary.html index 052b9887a..e34636831 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/data/update/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/data/update/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.data.update diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Evidence.html b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Evidence.html index 6607886c1..e4a87d8dd 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Evidence.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/Evidence.html @@ -61,9 +61,9 @@ 53 /** 54 * Creates a new Evidence objects. 55 * -56 * @param source the source of the evidence. -57 * @param name the name of the evidence. -58 * @param value the value of the evidence. +56 * @param source the source of the evidence. +57 * @param name the name of the evidence. +58 * @param value the value of the evidence. 59 * @param confidence the confidence of the evidence. 60 */ 61 public Evidence(String source, String name, String value, Confidence confidence) { @@ -135,167 +135,176 @@ 127 } 128 129 /** -130 * Get the value of value. If setUsed is set to false this call to get will not mark the evidence as used. -131 * -132 * @param setUsed whether or not this call to getValue should cause the used flag to be updated -133 * @return the value of value -134 */ -135 public String getValue(Boolean setUsed) { -136 used = used || setUsed; -137 return value; -138 } -139 -140 /** -141 * Set the value of value. -142 * -143 * @param value new value of value -144 */ -145 public void setValue(String value) { -146 this.value = value; -147 } -148 -149 /** -150 * A value indicating if the Evidence has been "used" (aka read). -151 */ -152 private boolean used; -153 -154 /** -155 * Get the value of used. -156 * -157 * @return the value of used -158 */ -159 public boolean isUsed() { -160 return used; -161 } -162 -163 /** -164 * Set the value of used. -165 * -166 * @param used new value of used -167 */ -168 public void setUsed(boolean used) { -169 this.used = used; -170 } -171 -172 /** -173 * The confidence level for the evidence. -174 */ -175 private Confidence confidence; -176 -177 /** -178 * Get the value of confidence. -179 * -180 * @return the value of confidence -181 */ -182 public Confidence getConfidence() { -183 return confidence; -184 } -185 -186 /** -187 * Set the value of confidence. -188 * -189 * @param confidence new value of confidence -190 */ -191 public void setConfidence(Confidence confidence) { -192 this.confidence = confidence; -193 } -194 -195 /** -196 * Implements the hashCode for Evidence. -197 * -198 * @return hash code. -199 */ -200 @Override -201 public int hashCode() { -202 return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER) -203 .append(StringUtils.lowerCase(name)) -204 .append(StringUtils.lowerCase(source)) -205 .append(StringUtils.lowerCase(value)) -206 .append(confidence) -207 .toHashCode(); -208 } -209 -210 /** -211 * Implements equals for Evidence. -212 * -213 * @param that an object to check the equality of. -214 * @return whether the two objects are equal. -215 */ -216 @Override -217 public boolean equals(Object that) { -218 if (this == that) { -219 return true; -220 } -221 if (!(that instanceof Evidence)) { -222 return false; +130 * Get the value of value. If setUsed is set to false this call to get will +131 * not mark the evidence as used. +132 * +133 * @param setUsed whether or not this call to getValue should cause the used +134 * flag to be updated +135 * @return the value of value +136 */ +137 public String getValue(Boolean setUsed) { +138 used = used || setUsed; +139 return value; +140 } +141 +142 /** +143 * Set the value of value. +144 * +145 * @param value new value of value +146 */ +147 public void setValue(String value) { +148 this.value = value; +149 } +150 +151 /** +152 * A value indicating if the Evidence has been "used" (aka read). +153 */ +154 private boolean used; +155 +156 /** +157 * Get the value of used. +158 * +159 * @return the value of used +160 */ +161 public boolean isUsed() { +162 return used; +163 } +164 +165 /** +166 * Set the value of used. +167 * +168 * @param used new value of used +169 */ +170 public void setUsed(boolean used) { +171 this.used = used; +172 } +173 +174 /** +175 * The confidence level for the evidence. +176 */ +177 private Confidence confidence; +178 +179 /** +180 * Get the value of confidence. +181 * +182 * @return the value of confidence +183 */ +184 public Confidence getConfidence() { +185 return confidence; +186 } +187 +188 /** +189 * Set the value of confidence. +190 * +191 * @param confidence new value of confidence +192 */ +193 public void setConfidence(Confidence confidence) { +194 this.confidence = confidence; +195 } +196 +197 /** +198 * Implements the hashCode for Evidence. +199 * +200 * @return hash code. +201 */ +202 @Override +203 public int hashCode() { +204 return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER) +205 .append(StringUtils.lowerCase(name)) +206 .append(StringUtils.lowerCase(source)) +207 .append(StringUtils.lowerCase(value)) +208 .append(confidence) +209 .toHashCode(); +210 } +211 +212 /** +213 * Implements equals for Evidence. +214 * +215 * @param that an object to check the equality of. +216 * @return whether the two objects are equal. +217 */ +218 @SuppressWarnings("deprecation") +219 @Override +220 public boolean equals(Object that) { +221 if (this == that) { +222 return true; 223 } -224 final Evidence e = (Evidence) that; -225 -226 return StringUtils.equalsIgnoreCase(name, e.name) -227 && StringUtils.equalsIgnoreCase(source, e.source) -228 && StringUtils.equalsIgnoreCase(value, e.value) -229 && ObjectUtils.equals(confidence, e.confidence); -230 } -231 -232 /** -233 * Implementation of the comparable interface. -234 * -235 * @param o the evidence being compared -236 * @return an integer indicating the ordering of the two objects -237 */ -238 @Override -239 public int compareTo(Evidence o) { -240 if (o == null) { -241 return 1; -242 } -243 if (StringUtils.equalsIgnoreCase(source, o.source)) { -244 if (StringUtils.equalsIgnoreCase(name, o.name)) { -245 if (StringUtils.equalsIgnoreCase(value, o.value)) { -246 if (ObjectUtils.equals(confidence, o.confidence)) { -247 return 0; //they are equal -248 } else { -249 return ObjectUtils.compare(confidence, o.confidence); -250 } -251 } else { -252 return compareToIgnoreCaseWithNullCheck(value, o.value); -253 } -254 } else { -255 return compareToIgnoreCaseWithNullCheck(name, o.name); -256 } -257 } else { -258 return compareToIgnoreCaseWithNullCheck(source, o.source); -259 } -260 } -261 -262 /** -263 * Wrapper around {@link java.lang.String#compareToIgnoreCase(java.lang.String) String.compareToIgnoreCase} with an -264 * exhaustive, possibly duplicative, check against nulls. -265 * -266 * @param me the value to be compared -267 * @param other the other value to be compared -268 * @return true if the values are equal; otherwise false -269 */ -270 private int compareToIgnoreCaseWithNullCheck(String me, String other) { -271 if (me == null && other == null) { -272 return 0; -273 } else if (me == null) { -274 return -1; //the other string is greater then me -275 } else if (other == null) { -276 return 1; //me is greater then the other string -277 } -278 return me.compareToIgnoreCase(other); -279 } -280 -281 /** -282 * Standard toString() implementation. -283 * -284 * @return the string representation of the object -285 */ -286 @Override -287 public String toString() { -288 return "Evidence{" + "name=" + name + ", source=" + source + ", value=" + value + ", confidence=" + confidence + '}'; -289 } -290 } +224 if (!(that instanceof Evidence)) { +225 return false; +226 } +227 final Evidence e = (Evidence) that; +228 +229 //TODO the call to ObjectUtils.equals needs to be replaced when we +230 //stop supporting Jenkins 1.6 requirement. +231 return StringUtils.equalsIgnoreCase(name, e.name) +232 && StringUtils.equalsIgnoreCase(source, e.source) +233 && StringUtils.equalsIgnoreCase(value, e.value) +234 && ObjectUtils.equals(confidence, e.confidence); +235 } +236 +237 /** +238 * Implementation of the comparable interface. +239 * +240 * @param o the evidence being compared +241 * @return an integer indicating the ordering of the two objects +242 */ +243 @SuppressWarnings("deprecation") +244 @Override +245 public int compareTo(Evidence o) { +246 if (o == null) { +247 return 1; +248 } +249 if (StringUtils.equalsIgnoreCase(source, o.source)) { +250 if (StringUtils.equalsIgnoreCase(name, o.name)) { +251 if (StringUtils.equalsIgnoreCase(value, o.value)) { +252 //TODO the call to ObjectUtils.equals needs to be replaced when we +253 //stop supporting Jenkins 1.6 requirement. +254 if (ObjectUtils.equals(confidence, o.confidence)) { +255 return 0; //they are equal +256 } else { +257 return ObjectUtils.compare(confidence, o.confidence); +258 } +259 } else { +260 return compareToIgnoreCaseWithNullCheck(value, o.value); +261 } +262 } else { +263 return compareToIgnoreCaseWithNullCheck(name, o.name); +264 } +265 } else { +266 return compareToIgnoreCaseWithNullCheck(source, o.source); +267 } +268 } +269 +270 /** +271 * Wrapper around +272 * {@link java.lang.String#compareToIgnoreCase(java.lang.String) String.compareToIgnoreCase} +273 * with an exhaustive, possibly duplicative, check against nulls. +274 * +275 * @param me the value to be compared +276 * @param other the other value to be compared +277 * @return true if the values are equal; otherwise false +278 */ +279 private int compareToIgnoreCaseWithNullCheck(String me, String other) { +280 if (me == null && other == null) { +281 return 0; +282 } else if (me == null) { +283 return -1; //the other string is greater then me +284 } else if (other == null) { +285 return 1; //me is greater then the other string +286 } +287 return me.compareToIgnoreCase(other); +288 } +289 +290 /** +291 * Standard toString() implementation. +292 * +293 * @return the string representation of the object +294 */ +295 @Override +296 public String toString() { +297 return "Evidence{" + "name=" + name + ", source=" + source + ", value=" + value + ", confidence=" + confidence + '}'; +298 } +299 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/package-frame.html index 61451b600..4216bace8 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.dependency diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/package-summary.html index bb56a57a2..6d2d39b43 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/dependency/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/dependency/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.dependency diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html b/dependency-check-core/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html index 05272f763..73e0ed175 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html @@ -33,7 +33,7 @@ 25 /** 26 * A collection of several exceptions. 27 * -28 * @author Jeremy Lomg +28 * @author Jeremy Long 29 */ 30 public class ExceptionCollection extends Exception { 31 @@ -62,7 +62,7 @@ 54 * Instantiates a new exception collection. 55 * 56 * @param exceptions a list of exceptions -57 * @param fatal indicates if the exception that occurred is fatal - meaning +57 * @param fatal indicates if any of the exceptions that occurred is fatal - meaning 58 * that no analysis was performed. 59 */ 60 public ExceptionCollection(List<Throwable> exceptions, boolean fatal) { @@ -76,7 +76,7 @@ 68 * 69 * @param msg the exception message 70 * @param exceptions a list of exceptions -71 * @param fatal indicates if the exception that occurred is fatal - meaning +71 * @param fatal indicates if any of the exceptions that occurred is fatal - meaning 72 * that no analysis was performed. 73 */ 74 public ExceptionCollection(String msg, List<Throwable> exceptions, boolean fatal) { @@ -189,7 +189,7 @@ 181 */ 182 @Override 183 public void printStackTrace(PrintWriter s) { -184 s.println("Multiple Exceptions Occured"); +184 s.println("Multiple Exceptions Occurred"); 185 super.printStackTrace(s); 186 for (Throwable t : this.exceptions) { 187 s.println("Next Exception:"); @@ -223,7 +223,7 @@ 215 final StringBuilder sb = new StringBuilder(); 216 final String msg = super.getMessage(); 217 if (msg == null || msg.isEmpty()) { -218 sb.append("One or more exceptions occured during analysis:"); +218 sb.append("One or more exceptions occurred during analysis:"); 219 } else { 220 sb.append(msg); 221 } diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/exception/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/exception/package-frame.html index a407701bb..7b5d707a5 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/exception/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/exception/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.exception + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.exception diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/exception/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/exception/package-summary.html index 86a3e7dac..c77be6708 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/exception/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/exception/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.exception + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.exception diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/package-frame.html index e68c36ddd..b7b2efa9b 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck @@ -16,6 +16,9 @@ diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/package-summary.html index f2b1081d9..0cebfc257 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck @@ -36,6 +36,11 @@
    18. + + + diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-frame.html index 3c6d7a48c..01070d8ca 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.reporting diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-summary.html index ea6ad70c5..20ae050e4 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/reporting/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.reporting diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/utils/DependencyVersion.html b/dependency-check-core/xref/org/owasp/dependencycheck/utils/DependencyVersion.html index baa7d9ced..2d6813654 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/utils/DependencyVersion.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/utils/DependencyVersion.html @@ -34,236 +34,247 @@ 2627/**28 * <p> -29 * Simple object to track the parts of a version number. The parts are contained in a List such that version 1.2.3 will -30 * be stored as: <code>versionParts[0] = 1; +29 * Simple object to track the parts of a version number. The parts are contained +30 * in a List such that version 1.2.3 will be stored as: <code>versionParts[0] = 1;31 * versionParts[1] = 2;32 * versionParts[2] = 3;33 * </code></p>34 * <p> -35 * Note, the parser contained in this class expects the version numbers to be separated by periods. If a different -36 * separator is used the parser will likely fail.</p> -37 * -38 * @author Jeremy Long -39 */ -40publicclassDependencyVersionimplements Iterable<String>, Comparable<DependencyVersion> { -41 -42/** -43 * Constructor for a empty DependencyVersion. -44 */ -45publicDependencyVersion() { -46 } -47 -48/** -49 * Constructor for a DependencyVersion that will parse a version string. -50 * <b>Note</b>, this should only be used when the version passed in is already known to be a well formatted version -51 * number. Otherwise, DependencyVersionUtil.parseVersion() should be used instead. -52 * -53 * @param version the well formatted version number to parse -54 */ -55publicDependencyVersion(String version) { -56 parseVersion(version); -57 } -58 -59/** -60 * Parses a version string into its sub parts: major, minor, revision, build, etc. <b>Note</b>, this should only be -61 * used to parse something that is already known to be a version number. -62 * -63 * @param version the version string to parse -64 */ -65publicfinalvoid parseVersion(String version) { -66 versionParts = new ArrayList<String>(); -67if (version != null) { -68final Pattern rx = Pattern.compile("(\\d+[a-z]{1,3}$|[a-z]+\\d+|\\d+|(release|beta|alpha)$)"); -69final Matcher matcher = rx.matcher(version.toLowerCase()); -70while (matcher.find()) { -71 versionParts.add(matcher.group()); -72 } -73if (versionParts.isEmpty()) { -74 versionParts.add(version); +35 * Note, the parser contained in this class expects the version numbers to be +36 * separated by periods. If a different separator is used the parser will likely +37 * fail.</p> +38 * +39 * @author Jeremy Long +40 */ +41publicclassDependencyVersionimplements Iterable<String>, Comparable<DependencyVersion> { +42 +43/** +44 * Constructor for a empty DependencyVersion. +45 */ +46publicDependencyVersion() { +47 } +48 +49/** +50 * Constructor for a DependencyVersion that will parse a version string. +51 * <b>Note</b>, this should only be used when the version passed in is +52 * already known to be a well formatted version number. Otherwise, +53 * DependencyVersionUtil.parseVersion() should be used instead. +54 * +55 * @param version the well formatted version number to parse +56 */ +57publicDependencyVersion(String version) { +58 parseVersion(version); +59 } +60 +61/** +62 * Parses a version string into its sub parts: major, minor, revision, +63 * build, etc. <b>Note</b>, this should only be used to parse something that +64 * is already known to be a version number. +65 * +66 * @param version the version string to parse +67 */ +68publicfinalvoid parseVersion(String version) { +69 versionParts = new ArrayList<String>(); +70if (version != null) { +71final Pattern rx = Pattern.compile("(\\d+[a-z]{1,3}$|[a-z]+\\d+|\\d+|(release|beta|alpha)$)"); +72final Matcher matcher = rx.matcher(version.toLowerCase()); +73while (matcher.find()) { +74 versionParts.add(matcher.group()); 75 } -76 } -77 } -78/** -79 * A list of the version parts. -80 */ -81private List<String> versionParts; -82 -83/** -84 * Get the value of versionParts. -85 * -86 * @return the value of versionParts -87 */ -88public List<String> getVersionParts() { -89return versionParts; -90 } -91 -92/** -93 * Set the value of versionParts. -94 * -95 * @param versionParts new value of versionParts -96 */ -97publicvoid setVersionParts(List<String> versionParts) { -98this.versionParts = versionParts; -99 } -100 -101/** -102 * Retrieves an iterator for the version parts. -103 * -104 * @return an iterator for the version parts -105 */ -106 @Override -107public Iterator<String> iterator() { -108return versionParts.iterator(); -109 } -110 -111/** -112 * Reconstructs the version string from the split version parts. -113 * -114 * @return a string representing the version. -115 */ -116 @Override -117public String toString() { -118return StringUtils.join(versionParts, '.'); -119 } -120 -121/** -122 * Compares the equality of this object to the one passed in as a parameter. -123 * -124 * @param obj the object to compare equality -125 * @return returns true only if the two objects are equal, otherwise false -126 */ -127 @Override -128publicboolean equals(Object obj) { -129if (obj == null) { -130return false; -131 } -132if (getClass() != obj.getClass()) { +76if (versionParts.isEmpty()) { +77 versionParts.add(version); +78 } +79 } +80 } +81/** +82 * A list of the version parts. +83 */ +84private List<String> versionParts; +85 +86/** +87 * Get the value of versionParts. +88 * +89 * @return the value of versionParts +90 */ +91public List<String> getVersionParts() { +92return versionParts; +93 } +94 +95/** +96 * Set the value of versionParts. +97 * +98 * @param versionParts new value of versionParts +99 */ +100publicvoid setVersionParts(List<String> versionParts) { +101this.versionParts = versionParts; +102 } +103 +104/** +105 * Retrieves an iterator for the version parts. +106 * +107 * @return an iterator for the version parts +108 */ +109 @Override +110public Iterator<String> iterator() { +111return versionParts.iterator(); +112 } +113 +114/** +115 * Reconstructs the version string from the split version parts. +116 * +117 * @return a string representing the version. +118 */ +119 @Override +120public String toString() { +121return StringUtils.join(versionParts, '.'); +122 } +123 +124/** +125 * Compares the equality of this object to the one passed in as a parameter. +126 * +127 * @param obj the object to compare equality +128 * @return returns true only if the two objects are equal, otherwise false +129 */ +130 @Override +131publicboolean equals(Object obj) { +132if (obj == null) { 133return false; 134 } -135finalDependencyVersion other = (DependencyVersion) obj; -136finalint max = (this.versionParts.size() < other.versionParts.size()) -137 ? this.versionParts.size() : other.versionParts.size(); -138//TODO steal better version of code from compareTo -139for (int i = 0; i < max; i++) { -140final String thisPart = this.versionParts.get(i); -141final String otherPart = other.versionParts.get(i); -142if (!thisPart.equals(otherPart)) { -143return false; -144 } -145 } -146if (this.versionParts.size() > max) { -147for (int i = max; i < this.versionParts.size(); i++) { -148if (!"0".equals(this.versionParts.get(i))) { -149return false; -150 } -151 } -152 } -153 -154if (other.versionParts.size() > max) { -155for (int i = max; i < other.versionParts.size(); i++) { -156if (!"0".equals(other.versionParts.get(i))) { -157return false; -158 } -159 } -160 } -161 -162/* -163 * if (this.versionParts != other.versionParts && (this.versionParts == null || !this.versionParts.equals(other.versionParts))) { -164 * return false; -165 * } -166 */ -167returntrue; -168 } -169 -170/** -171 * Calculates the hashCode for this object. -172 * -173 * @return the hashCode -174 */ -175 @Override -176publicint hashCode() { -177int hash = 5; -178 hash = 71 * hash + (this.versionParts != null ? this.versionParts.hashCode() : 0); -179return hash; -180 } -181 -182/** -183 * Determines if the three most major major version parts are identical. For instances, if version 1.2.3.4 was -184 * compared to 1.2.3 this function would return true. -185 * -186 * @param version the version number to compare -187 * @return true if the first three major parts of the version are identical -188 */ -189publicboolean matchesAtLeastThreeLevels(DependencyVersion version) { -190if (version == null) { -191return false; -192 } -193if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) { -194return false; -195 } -196 -197finalint max = (this.versionParts.size() < version.versionParts.size()) -198 ? this.versionParts.size() : version.versionParts.size(); -199 -200boolean ret = true; -201for (int i = 0; i < max; i++) { -202final String thisVersion = this.versionParts.get(i); -203final String otherVersion = version.getVersionParts().get(i); -204if (i >= 3) { -205if (thisVersion.compareToIgnoreCase(otherVersion) >= 0) { -206 ret = false; -207break; -208 } -209 } elseif (!thisVersion.equals(otherVersion)) { -210 ret = false; -211break; -212 } -213 } -214 -215return ret; -216 } -217 -218 @Override -219publicint compareTo(DependencyVersion version) { -220if (version == null) { -221return 1; -222 } -223final List<String> left = this.getVersionParts(); -224final List<String> right = version.getVersionParts(); -225finalint max = left.size() < right.size() ? left.size() : right.size(); -226 -227for (int i = 0; i < max; i++) { -228final String lStr = left.get(i); -229final String rStr = right.get(i); -230if (lStr.equals(rStr)) { -231continue; -232 } -233try { -234finalint l = Integer.parseInt(lStr); -235finalint r = Integer.parseInt(rStr); -236if (l < r) { -237return -1; -238 } elseif (l > r) { -239return 1; -240 } -241 } catch (NumberFormatException ex) { -242finalint comp = left.get(i).compareTo(right.get(i)); -243if (comp < 0) { -244return -1; -245 } elseif (comp > 0) { -246return 1; -247 } -248 } -249 } -250if (left.size() < right.size()) { -251return -1; -252 } elseif (left.size() > right.size()) { -253return 1; -254 } else { -255return 0; -256 } -257 } -258 } +135if (getClass() != obj.getClass()) { +136return false; +137 } +138finalDependencyVersion other = (DependencyVersion) obj; +139finalint minVersionMatchLength = (this.versionParts.size() < other.versionParts.size()) +140 ? this.versionParts.size() : other.versionParts.size(); +141finalint maxVersionMatchLength = (this.versionParts.size() > other.versionParts.size()) +142 ? this.versionParts.size() : other.versionParts.size(); +143 +144if (minVersionMatchLength == 1 && maxVersionMatchLength >= 3) { +145return false; +146 } +147 +148//TODO steal better version of code from compareTo +149for (int i = 0; i < minVersionMatchLength; i++) { +150final String thisPart = this.versionParts.get(i); +151final String otherPart = other.versionParts.get(i); +152if (!thisPart.equals(otherPart)) { +153return false; +154 } +155 } +156if (this.versionParts.size() > minVersionMatchLength) { +157for (int i = minVersionMatchLength; i < this.versionParts.size(); i++) { +158if (!"0".equals(this.versionParts.get(i))) { +159return false; +160 } +161 } +162 } +163 +164if (other.versionParts.size() > minVersionMatchLength) { +165for (int i = minVersionMatchLength; i < other.versionParts.size(); i++) { +166if (!"0".equals(other.versionParts.get(i))) { +167return false; +168 } +169 } +170 } +171 +172/* +173 * if (this.versionParts != other.versionParts && (this.versionParts == null || !this.versionParts.equals(other.versionParts))) { +174 * return false; +175 * } +176 */ +177returntrue; +178 } +179 +180/** +181 * Calculates the hashCode for this object. +182 * +183 * @return the hashCode +184 */ +185 @Override +186publicint hashCode() { +187int hash = 5; +188 hash = 71 * hash + (this.versionParts != null ? this.versionParts.hashCode() : 0); +189return hash; +190 } +191 +192/** +193 * Determines if the three most major major version parts are identical. For +194 * instances, if version 1.2.3.4 was compared to 1.2.3 this function would +195 * return true. +196 * +197 * @param version the version number to compare +198 * @return true if the first three major parts of the version are identical +199 */ +200publicboolean matchesAtLeastThreeLevels(DependencyVersion version) { +201if (version == null) { +202return false; +203 } +204if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) { +205return false; +206 } +207 +208finalint max = (this.versionParts.size() < version.versionParts.size()) +209 ? this.versionParts.size() : version.versionParts.size(); +210 +211boolean ret = true; +212for (int i = 0; i < max; i++) { +213final String thisVersion = this.versionParts.get(i); +214final String otherVersion = version.getVersionParts().get(i); +215if (i >= 3) { +216if (thisVersion.compareToIgnoreCase(otherVersion) >= 0) { +217 ret = false; +218break; +219 } +220 } elseif (!thisVersion.equals(otherVersion)) { +221 ret = false; +222break; +223 } +224 } +225 +226return ret; +227 } +228 +229 @Override +230publicint compareTo(DependencyVersion version) { +231if (version == null) { +232return 1; +233 } +234final List<String> left = this.getVersionParts(); +235final List<String> right = version.getVersionParts(); +236finalint max = left.size() < right.size() ? left.size() : right.size(); +237 +238for (int i = 0; i < max; i++) { +239final String lStr = left.get(i); +240final String rStr = right.get(i); +241if (lStr.equals(rStr)) { +242continue; +243 } +244try { +245finalint l = Integer.parseInt(lStr); +246finalint r = Integer.parseInt(rStr); +247if (l < r) { +248return -1; +249 } elseif (l > r) { +250return 1; +251 } +252 } catch (NumberFormatException ex) { +253finalint comp = left.get(i).compareTo(right.get(i)); +254if (comp < 0) { +255return -1; +256 } elseif (comp > 0) { +257return 1; +258 } +259 } +260 } +261if (left.size() < right.size()) { +262return -1; +263 } elseif (left.size() > right.size()) { +264return 1; +265 } else { +266return 0; +267 } +268 } +269 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-frame.html index 90e99a4d0..c644670df 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-summary.html index bcaf3ed01..2377622c4 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/utils/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintParser.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintParser.html index 7ffb4ffda..bab80dd83 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintParser.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/HintParser.html @@ -117,50 +117,51 @@ 109 schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA); 110finalHintHandler handler = newHintHandler(); 111final SAXParserFactory factory = SAXParserFactory.newInstance(); -112 factory.setNamespaceAware(true); -113 factory.setValidating(true); -114final SAXParser saxParser = factory.newSAXParser(); -115 saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA); -116 saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -117final XMLReader xmlReader = saxParser.getXMLReader(); -118 xmlReader.setErrorHandler(newHintErrorHandler()); -119 xmlReader.setContentHandler(handler); -120 -121final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -122final InputSource in = new InputSource(reader); -123 -124 xmlReader.parse(in); -125finalHints hints = newHints(); -126 hints.setHintRules(handler.getHintRules()); -127 hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules()); -128return hints; -129 } catch (ParserConfigurationException ex) { -130 LOGGER.debug("", ex); -131thrownewHintParseException(ex); -132 } catch (SAXException ex) { -133if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) { -134throw ex; -135 } else { -136 LOGGER.debug("", ex); -137thrownewHintParseException(ex); -138 } -139 } catch (FileNotFoundException ex) { -140 LOGGER.debug("", ex); -141thrownewHintParseException(ex); -142 } catch (IOException ex) { -143 LOGGER.debug("", ex); -144thrownewHintParseException(ex); -145 } finally { -146if (schemaStream != null) { -147try { -148 schemaStream.close(); -149 } catch (IOException ex) { -150 LOGGER.debug("Error closing hint file stream", ex); -151 } -152 } -153 } -154 } -155 } +112 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +113 factory.setNamespaceAware(true); +114 factory.setValidating(true); +115final SAXParser saxParser = factory.newSAXParser(); +116 saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA); +117 saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); +118final XMLReader xmlReader = saxParser.getXMLReader(); +119 xmlReader.setErrorHandler(newHintErrorHandler()); +120 xmlReader.setContentHandler(handler); +121 +122final Reader reader = new InputStreamReader(inputStream, "UTF-8"); +123final InputSource in = new InputSource(reader); +124 +125 xmlReader.parse(in); +126finalHints hints = newHints(); +127 hints.setHintRules(handler.getHintRules()); +128 hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules()); +129return hints; +130 } catch (ParserConfigurationException ex) { +131 LOGGER.debug("", ex); +132thrownewHintParseException(ex); +133 } catch (SAXException ex) { +134if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) { +135throw ex; +136 } else { +137 LOGGER.debug("", ex); +138thrownewHintParseException(ex); +139 } +140 } catch (FileNotFoundException ex) { +141 LOGGER.debug("", ex); +142thrownewHintParseException(ex); +143 } catch (IOException ex) { +144 LOGGER.debug("", ex); +145thrownewHintParseException(ex); +146 } finally { +147if (schemaStream != null) { +148try { +149 schemaStream.close(); +150 } catch (IOException ex) { +151 LOGGER.debug("Error closing hint file stream", ex); +152 } +153 } +154 } +155 } +156 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/package-frame.html index d3276ca69..c28aefa67 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/package-summary.html index cf7481c87..71efb22ff 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/hints/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/Model.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/Model.html index ae086b16f..448a24c5d 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/Model.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/Model.html @@ -356,7 +356,7 @@ 348 * Utility class that can provide values from a Properties object to a349 * StrSubstitutor.350 */ -351privatestaticclassPropertyLookupextends StrLookup { +351privatestaticclassPropertyLookupextends StrLookup<String> { 352353/**354 * Reference to the properties to lookup. diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/PomParser.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/PomParser.html index daa097f12..1cdc873b2 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/PomParser.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/PomParser.html @@ -55,70 +55,74 @@ 47privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(PomParser.class); 4849/** -50 * Parses the given xml file and returns a Model object containing only the fields dependency-check requires. -51 * -52 * @param file a pom.xml -53 * @return a Model object containing only the fields dependency-check requires -54 * @throws PomParseException thrown if the xml file cannot be parsed -55 */ -56publicModel parse(File file) throws PomParseException { -57 FileInputStream fis = null; -58try { -59 fis = new FileInputStream(file); -60return parse(fis); -61 } catch (IOException ex) { -62 LOGGER.debug("", ex); -63thrownewPomParseException(ex); -64 } finally { -65if (fis != null) { -66try { -67 fis.close(); -68 } catch (IOException ex) { -69 LOGGER.debug("Unable to close stream", ex); -70 } -71 } -72 } -73 } -74 -75/** -76 * Parses the given XML file and returns a Model object containing only the fields dependency-check requires. -77 * -78 * @param inputStream an InputStream containing suppression rues -79 * @return a list of suppression rules -80 * @throws PomParseException if the XML cannot be parsed -81 */ -82publicModel parse(InputStream inputStream) throws PomParseException { -83try { -84finalPomHandler handler = newPomHandler(); -85final SAXParserFactory factory = SAXParserFactory.newInstance(); -86// factory.setNamespaceAware(true); -87// factory.setValidating(true); -88final SAXParser saxParser = factory.newSAXParser(); -89final XMLReader xmlReader = saxParser.getXMLReader(); -90 xmlReader.setContentHandler(handler); -91 -92final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -93final InputSource in = new InputSource(reader); -94//in.setEncoding("UTF-8"); +50 * Parses the given xml file and returns a Model object containing only the +51 * fields dependency-check requires. +52 * +53 * @param file a pom.xml +54 * @return a Model object containing only the fields dependency-check +55 * requires +56 * @throws PomParseException thrown if the xml file cannot be parsed +57 */ +58publicModel parse(File file) throws PomParseException { +59 FileInputStream fis = null; +60try { +61 fis = new FileInputStream(file); +62return parse(fis); +63 } catch (IOException ex) { +64 LOGGER.debug("", ex); +65thrownewPomParseException(ex); +66 } finally { +67if (fis != null) { +68try { +69 fis.close(); +70 } catch (IOException ex) { +71 LOGGER.debug("Unable to close stream", ex); +72 } +73 } +74 } +75 } +76 +77/** +78 * Parses the given XML file and returns a Model object containing only the +79 * fields dependency-check requires. +80 * +81 * @param inputStream an InputStream containing suppression rues +82 * @return a list of suppression rules +83 * @throws PomParseException if the XML cannot be parsed +84 */ +85publicModel parse(InputStream inputStream) throws PomParseException { +86try { +87finalPomHandler handler = newPomHandler(); +88final SAXParserFactory factory = SAXParserFactory.newInstance(); +89// factory.setNamespaceAware(true); +90// factory.setValidating(true); +91 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +92final SAXParser saxParser = factory.newSAXParser(); +93final XMLReader xmlReader = saxParser.getXMLReader(); +94 xmlReader.setContentHandler(handler); 95 -96 xmlReader.parse(in); -97 -98return handler.getModel(); -99 } catch (ParserConfigurationException ex) { -100 LOGGER.debug("", ex); -101thrownewPomParseException(ex); -102 } catch (SAXException ex) { -103 LOGGER.debug("", ex); -104thrownewPomParseException(ex); -105 } catch (FileNotFoundException ex) { -106 LOGGER.debug("", ex); -107thrownewPomParseException(ex); -108 } catch (IOException ex) { -109 LOGGER.debug("", ex); -110thrownewPomParseException(ex); -111 } -112 } -113 } +96final Reader reader = new InputStreamReader(inputStream, "UTF-8"); +97final InputSource in = new InputSource(reader); +98//in.setEncoding("UTF-8"); +99 +100 xmlReader.parse(in); +101 +102return handler.getModel(); +103 } catch (ParserConfigurationException ex) { +104 LOGGER.debug("", ex); +105thrownewPomParseException(ex); +106 } catch (SAXException ex) { +107 LOGGER.debug("", ex); +108thrownewPomParseException(ex); +109 } catch (FileNotFoundException ex) { +110 LOGGER.debug("", ex); +111thrownewPomParseException(ex); +112 } catch (IOException ex) { +113 LOGGER.debug("", ex); +114thrownewPomParseException(ex); +115 } +116 } +117 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/package-frame.html index 59f55f9bc..93b174939 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/package-summary.html index 45879868a..858e1be74 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/pom/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html index 584dfa251..f87b87fb0 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html @@ -136,99 +136,100 @@ 128final SAXParserFactory factory = SAXParserFactory.newInstance(); 129 factory.setNamespaceAware(true); 130 factory.setValidating(true); -131final SAXParser saxParser = factory.newSAXParser(); -132 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); -133 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -134final XMLReader xmlReader = saxParser.getXMLReader(); -135 xmlReader.setErrorHandler(newSuppressionErrorHandler()); -136 xmlReader.setContentHandler(handler); -137 -138final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -139final InputSource in = new InputSource(reader); -140//in.setEncoding("UTF-8"); -141 -142 xmlReader.parse(in); -143 -144return handler.getSuppressionRules(); -145 } catch (ParserConfigurationException ex) { -146 LOGGER.debug("", ex); -147thrownewSuppressionParseException(ex); -148 } catch (SAXException ex) { -149if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) { -150throw ex; -151 } else { -152 LOGGER.debug("", ex); -153thrownewSuppressionParseException(ex); -154 } -155 } catch (FileNotFoundException ex) { -156 LOGGER.debug("", ex); -157thrownewSuppressionParseException(ex); -158 } catch (IOException ex) { -159 LOGGER.debug("", ex); -160thrownewSuppressionParseException(ex); -161 } finally { -162if (schemaStream != null) { -163try { -164 schemaStream.close(); -165 } catch (IOException ex) { -166 LOGGER.debug("Error closing suppression file stream", ex); -167 } -168 } -169 } -170 } -171 -172/** -173 * Parses the given XML stream and returns a list of the suppression rules -174 * contained. -175 * -176 * @param inputStream an InputStream containing suppression rues -177 * @return a list of suppression rules -178 * @throws SuppressionParseException if the XML cannot be parsed -179 */ -180private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException { -181 InputStream schemaStream = null; -182try { -183 schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA); -184finalSuppressionHandler handler = newSuppressionHandler(); -185final SAXParserFactory factory = SAXParserFactory.newInstance(); -186 factory.setNamespaceAware(true); -187 factory.setValidating(true); -188final SAXParser saxParser = factory.newSAXParser(); -189 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); -190 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -191final XMLReader xmlReader = saxParser.getXMLReader(); -192 xmlReader.setErrorHandler(newSuppressionErrorHandler()); -193 xmlReader.setContentHandler(handler); -194 -195final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -196final InputSource in = new InputSource(reader); -197 -198 xmlReader.parse(in); -199 -200return handler.getSuppressionRules(); -201 } catch (ParserConfigurationException ex) { -202 LOGGER.debug("", ex); -203thrownewSuppressionParseException(ex); -204 } catch (SAXException ex) { -205 LOGGER.debug("", ex); -206thrownewSuppressionParseException(ex); -207 } catch (FileNotFoundException ex) { -208 LOGGER.debug("", ex); -209thrownewSuppressionParseException(ex); -210 } catch (IOException ex) { -211 LOGGER.debug("", ex); -212thrownewSuppressionParseException(ex); -213 } finally { -214if (schemaStream != null) { -215try { -216 schemaStream.close(); -217 } catch (IOException ex) { -218 LOGGER.debug("Error closing old suppression file stream", ex); -219 } -220 } -221 } -222 } -223 } +131 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +132final SAXParser saxParser = factory.newSAXParser(); +133 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); +134 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); +135final XMLReader xmlReader = saxParser.getXMLReader(); +136 xmlReader.setErrorHandler(newSuppressionErrorHandler()); +137 xmlReader.setContentHandler(handler); +138 +139final Reader reader = new InputStreamReader(inputStream, "UTF-8"); +140final InputSource in = new InputSource(reader); +141//in.setEncoding("UTF-8"); +142 +143 xmlReader.parse(in); +144 +145return handler.getSuppressionRules(); +146 } catch (ParserConfigurationException ex) { +147 LOGGER.debug("", ex); +148thrownewSuppressionParseException(ex); +149 } catch (SAXException ex) { +150if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) { +151throw ex; +152 } else { +153 LOGGER.debug("", ex); +154thrownewSuppressionParseException(ex); +155 } +156 } catch (FileNotFoundException ex) { +157 LOGGER.debug("", ex); +158thrownewSuppressionParseException(ex); +159 } catch (IOException ex) { +160 LOGGER.debug("", ex); +161thrownewSuppressionParseException(ex); +162 } finally { +163if (schemaStream != null) { +164try { +165 schemaStream.close(); +166 } catch (IOException ex) { +167 LOGGER.debug("Error closing suppression file stream", ex); +168 } +169 } +170 } +171 } +172 +173/** +174 * Parses the given XML stream and returns a list of the suppression rules +175 * contained. +176 * +177 * @param inputStream an InputStream containing suppression rues +178 * @return a list of suppression rules +179 * @throws SuppressionParseException if the XML cannot be parsed +180 */ +181private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException { +182 InputStream schemaStream = null; +183try { +184 schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA); +185finalSuppressionHandler handler = newSuppressionHandler(); +186final SAXParserFactory factory = SAXParserFactory.newInstance(); +187 factory.setNamespaceAware(true); +188 factory.setValidating(true); +189final SAXParser saxParser = factory.newSAXParser(); +190 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); +191 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); +192final XMLReader xmlReader = saxParser.getXMLReader(); +193 xmlReader.setErrorHandler(newSuppressionErrorHandler()); +194 xmlReader.setContentHandler(handler); +195 +196final Reader reader = new InputStreamReader(inputStream, "UTF-8"); +197final InputSource in = new InputSource(reader); +198 +199 xmlReader.parse(in); +200 +201return handler.getSuppressionRules(); +202 } catch (ParserConfigurationException ex) { +203 LOGGER.debug("", ex); +204thrownewSuppressionParseException(ex); +205 } catch (SAXException ex) { +206 LOGGER.debug("", ex); +207thrownewSuppressionParseException(ex); +208 } catch (FileNotFoundException ex) { +209 LOGGER.debug("", ex); +210thrownewSuppressionParseException(ex); +211 } catch (IOException ex) { +212 LOGGER.debug("", ex); +213thrownewSuppressionParseException(ex); +214 } finally { +215if (schemaStream != null) { +216try { +217 schemaStream.close(); +218 } catch (IOException ex) { +219 LOGGER.debug("Error closing old suppression file stream", ex); +220 } +221 } +222 } +223 } +224 }
      diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html index 5c3fa0c2d..1d29efbe3 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.suppression diff --git a/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/package-summary.html b/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/package-summary.html index e9a452f38..e2ae6ef82 100644 --- a/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/package-summary.html +++ b/dependency-check-core/xref/org/owasp/dependencycheck/xml/suppression/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check Core 1.4.4 Reference Package org.owasp.dependencycheck.xml.suppression diff --git a/dependency-check-core/xref/overview-frame.html b/dependency-check-core/xref/overview-frame.html index 6199e9f5a..6023b9e1c 100644 --- a/dependency-check-core/xref/overview-frame.html +++ b/dependency-check-core/xref/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference + Dependency-Check Core 1.4.4 Reference diff --git a/dependency-check-core/xref/overview-summary.html b/dependency-check-core/xref/overview-summary.html index 7ae7797b0..22f0544f2 100644 --- a/dependency-check-core/xref/overview-summary.html +++ b/dependency-check-core/xref/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Core 1.4.3 Reference + Dependency-Check Core 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Core 1.4.3 Reference

      +

      Dependency-Check Core 1.4.4 Reference

      + AnalysisTask +
      Engine
      diff --git a/dependency-check-gradle/configuration-purge.html b/dependency-check-gradle/configuration-purge.html index 81f99e375..86b87b593 100644 --- a/dependency-check-gradle/configuration-purge.html +++ b/dependency-check-gradle/configuration-purge.html @@ -1,13 +1,13 @@ - + dependency-check – Tasks @@ -59,9 +59,9 @@
    19. Tasks
    20. -
    21. | Last Published: 2016-09-06
    22. +
    23. | Last Published: 2016-11-05
    24. - Version: 1.4.3 + Version: 1.4.4
    25. @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@ + + + + + + + + + @@ -345,7 +354,7 @@ - + diff --git a/dependency-check-gradle/index.html b/dependency-check-gradle/index.html index 24b3132b3..bef83bf7b 100644 --- a/dependency-check-gradle/index.html +++ b/dependency-check-gradle/index.html @@ -1,13 +1,13 @@ - + dependency-check – Usage @@ -59,9 +59,9 @@
    26. Usage
    27. -
    28. | Last Published: 2016-09-06
    29. +
    30. | Last Published: 2016-11-05
    31. - Version: 1.4.3 + Version: 1.4.4
    32. @@ -74,14 +74,14 @@
      @@ -74,14 +74,14 @@ - + @@ -215,7 +215,7 @@ vulnerabilities. +the CVSS scores are 0-10, by default the build will never fail.
      Default value is: 11.
      User property is: failBuildOnCVSS.
      @@ -226,7 +226,7 @@ the CVSS scores are 0-10, by default the build will never fail.
      Default - + @@ -239,7 +239,7 @@ the CVSS scores are 0-10, by default the build will never fail.
      Default
      +plug-in unless the externalReport is set to true. Default is HTML.
      Default value is: HTML.
      User property is: format.
      @@ -250,7 +250,7 @@ plug-in unless the externalReport is set to true. Default is HTML.
      Defau
      - + @@ -273,7 +273,7 @@ plug-in unless the externalReport is set to true. Default is HTML.
      Defau
      +Dependency-Check report. This generally maps to "target/site".
      User property is: project.reporting.outputDirectory.
      hintsFile The file path to the XML hints file - used to resolve false negatives  
      skipConfigurations A list of configurations that will be skipped. This is mutually exclusive with the scanConfigurations property. [] which means no configuration is skipped.
      scanConfigurations -Sets whether or not the external report format should be used.
      Default value is: dependency-check.ser.
      User property is: metaFileName.
      Sets whether or not the external report format should be used.
      Default value is: dependency-check.ser.
      User property is: metaFileName.
      Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since -the CVSS scores are 0-10, by default the build will never fail.
      Default value is: 11.
      User property is: failBuildOnCVSS.
      -Sets whether or not the external report format should be used.
      Default value is: true.
      User property is: failOnError.
      Sets whether or not the external report format should be used.
      Default value is: true.
      User property is: failOnError.
      The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site -plug-in unless the externalReport is set to true. Default is HTML.
      Default value is: HTML.
      User property is: format.
      -The name of the report in the site.
      Default value is: dependency-check:aggregate.
      User property is: name.
      The name of the report in the site.
      Default value is: dependency-check:aggregate.
      User property is: name.
      - Specifies the destination directory for the generated -Dependency-Check report. This generally maps to "target/site".
      User property is: project.reporting.outputDirectory.
      @@ -302,7 +302,7 @@ Dependency-Check report. This generally maps to "target/site".
      - -Deprecated. use the aggregate goal instead
      User property is: aggregate. +Deprecated. use the aggregate goal instead
      User property is: aggregate.
      @@ -313,7 +313,7 @@ Dependency-Check report. This generally maps to "target/site".
      - -Whether or not the Archive Analyzer is enabled.
      User property is: archiveAnalyzerEnabled. +Whether or not the Archive Analyzer is enabled.
      User property is: archiveAnalyzerEnabled.
      @@ -324,7 +324,7 @@ Dependency-Check report. This generally maps to "target/site".
      - -Whether or not the .NET Assembly Analyzer is enabled.
      User property is: assemblyAnalyzerEnabled. +Whether or not the .NET Assembly Analyzer is enabled.
      User property is: assemblyAnalyzerEnabled.
      @@ -336,7 +336,7 @@ Dependency-Check report. This generally maps to "target/site".
      - Sets whether auto-updating of the NVD CVE/CPE data is enabled. It -is not recommended that this be turned to false. Default is true.
      User property is: autoUpdate. +is not recommended that this be turned to false. Default is true.
      User property is: autoUpdate.
      @@ -347,7 +347,7 @@ is not recommended that this be turned to false. Default is true.
      User p - -Sets whether or not the autoconf Analyzer should be used.
      User property is: autoconfAnalyzerEnabled. +Sets whether or not the autoconf Analyzer should be used.
      User property is: autoconfAnalyzerEnabled.
      @@ -358,7 +358,7 @@ is not recommended that this be turned to false. Default is true.
      User p - -Whether or not the Central Analyzer is enabled.
      User property is: centralAnalyzerEnabled. +Whether or not the Central Analyzer is enabled.
      User property is: centralAnalyzerEnabled.
      @@ -369,7 +369,7 @@ is not recommended that this be turned to false. Default is true.
      User p - -Sets whether or not the CMake Analyzer should be used.
      User property is: cmakeAnalyzerEnabled. +Sets whether or not the CMake Analyzer should be used.
      User property is: cmakeAnalyzerEnabled.
      @@ -381,7 +381,7 @@ is not recommended that this be turned to false. Default is true.
      User p - Sets whether or not the PHP Composer Lock File Analyzer should be -used.
      User property is: composerAnalyzerEnabled. +used.
      User property is: composerAnalyzerEnabled.
      @@ -392,7 +392,7 @@ used.
      User property is: composerAnalyzerEnabled. - -The database connection string.
      User property is: connectionString. +The database connection string.
      User property is: connectionString.
      @@ -403,7 +403,7 @@ used.
      User property is: composerAnalyzerEnabled. - -The Connection Timeout.
      User property is: connectionTimeout. +The Connection Timeout.
      User property is: connectionTimeout.
      @@ -414,7 +414,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Base Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Base. +Base Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Base.
      @@ -425,7 +425,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Modified. +Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Modified.
      @@ -436,7 +436,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Base. +Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Base.
      @@ -447,7 +447,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Modified. +Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Modified.
      @@ -459,7 +459,7 @@ used.
      User property is: composerAnalyzerEnabled. - Optionally skip excessive CVE update checks for a designated -duration in hours.
      User property is: cveValidForHours. +duration in hours.
      User property is: cveValidForHours.
      @@ -470,7 +470,7 @@ duration in hours.
      User property is: cveValidForHours. - -The data directory, hold DC SQL DB.
      User property is: dataDirectory. +The data directory, hold DC SQL DB.
      User property is: dataDirectory.
      @@ -481,7 +481,7 @@ duration in hours.
      User property is: cveValidForHours. - -The database driver name. An example would be org.h2.Driver.
      User property is: databaseDriverName. +The database driver name. An example would be org.h2.Driver.
      User property is: databaseDriverName.
      @@ -492,7 +492,7 @@ duration in hours.
      User property is: cveValidForHours. - -The path to the database driver if it is not on the class path.
      User property is: databaseDriverPath. +The path to the database driver if it is not on the class path.
      User property is: databaseDriverPath.
      @@ -503,7 +503,7 @@ duration in hours.
      User property is: cveValidForHours. - -The password to use when connecting to the database.
      User property is: databasePassword. +The password to use when connecting to the database.
      User property is: databasePassword.
      @@ -514,7 +514,7 @@ duration in hours.
      User property is: cveValidForHours. - -The database user name.
      User property is: databaseUser. +The database user name.
      User property is: databaseUser.
      @@ -525,7 +525,7 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether Experimental analyzers are enabled. Default is false.
      User property is: enableExperimental. +Sets whether Experimental analyzers are enabled. Default is false.
      User property is: enableExperimental.
      @@ -536,21 +536,32 @@ duration in hours.
      User property is: cveValidForHours. - -Deprecated. the internal report is no longer supported
      User property is: externalReport. +Deprecated. the internal report is no longer supported
      User property is: externalReport.
      +hintsFile + +String + +- + +The path to the hints file.
      User property is: hintsFile.
      + + + + jarAnalyzerEnabled Boolean - -Whether or not the Jar Analyzer is enabled.
      User property is: jarAnalyzerEnabled. +Whether or not the Jar Analyzer is enabled.
      User property is: jarAnalyzerEnabled.
      - + mavenSettings @@ -558,10 +569,10 @@ duration in hours.
      User property is: cveValidForHours. - -The Maven settings.
      Default value is: ${settings}.
      User property is: mavenSettings. +The Maven settings.
      Default value is: ${settings}.
      User property is: mavenSettings.
      - + mavenSettingsProxyId @@ -569,10 +580,10 @@ duration in hours.
      User property is: cveValidForHours. - -The maven settings proxy id.
      User property is: mavenSettingsProxyId. +The maven settings proxy id.
      User property is: mavenSettingsProxyId.
      - + nexusAnalyzerEnabled @@ -580,10 +591,10 @@ duration in hours.
      User property is: cveValidForHours. - -Whether or not the Nexus Analyzer is enabled.
      User property is: nexusAnalyzerEnabled. +Whether or not the Nexus Analyzer is enabled.
      User property is: nexusAnalyzerEnabled.
      - + nexusUrl @@ -592,10 +603,10 @@ duration in hours.
      User property is: cveValidForHours. - The URL of a Nexus server's REST API end point -(http://domain/nexus/service/local).
      User property is: nexusUrl. +(http://domain/nexus/service/local).
      User property is: nexusUrl.
      - + nexusUsesProxy @@ -603,10 +614,10 @@ duration in hours.
      User property is: cveValidForHours. - -Whether or not the configured proxy is used to connect to Nexus.
      User property is: nexusUsesProxy. +Whether or not the configured proxy is used to connect to Nexus.
      User property is: nexusUsesProxy.
      - + nodeAnalyzerEnabled @@ -614,10 +625,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether or not the Node.js Analyzer should be used.
      User property is: nodeAnalyzerEnabled. +Sets whether or not the Node.js Analyzer should be used.
      User property is: nodeAnalyzerEnabled.
      - + nuspecAnalyzerEnabled @@ -625,10 +636,10 @@ duration in hours.
      User property is: cveValidForHours. - -Whether or not the .NET Nuspec Analyzer is enabled.
      User property is: nuspecAnalyzerEnabled. +Whether or not the .NET Nuspec Analyzer is enabled.
      User property is: nuspecAnalyzerEnabled.
      - + opensslAnalyzerEnabled @@ -636,10 +647,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether or not the openssl Analyzer should be used.
      User property is: opensslAnalyzerEnabled. +Sets whether or not the openssl Analyzer should be used.
      User property is: opensslAnalyzerEnabled.
      - + pathToMono @@ -647,10 +658,10 @@ duration in hours.
      User property is: cveValidForHours. - -The path to mono for .NET Assembly analysis on non-windows systems.
      User property is: pathToMono. +The path to mono for .NET Assembly analysis on non-windows systems.
      User property is: pathToMono.
      - + proxyUrl @@ -658,10 +669,10 @@ duration in hours.
      User property is: cveValidForHours. - -Deprecated. Please use mavenSettings instead
      User property is: proxyUrl. +Deprecated. Please use mavenSettings instead
      User property is: proxyUrl.
      - + pyDistributionAnalyzerEnabled @@ -669,10 +680,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether the Python Distribution Analyzer will be used.
      User property is: pyDistributionAnalyzerEnabled. +Sets whether the Python Distribution Analyzer will be used.
      User property is: pyDistributionAnalyzerEnabled.
      - + pyPackageAnalyzerEnabled @@ -680,10 +691,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether the Python Package Analyzer will be used.
      User property is: pyPackageAnalyzerEnabled. +Sets whether the Python Package Analyzer will be used.
      User property is: pyPackageAnalyzerEnabled.
      - + rubygemsAnalyzerEnabled @@ -691,10 +702,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether the Ruby Gemspec Analyzer will be used.
      User property is: rubygemsAnalyzerEnabled. +Sets whether the Ruby Gemspec Analyzer will be used.
      User property is: rubygemsAnalyzerEnabled.
      - + serverId @@ -703,10 +714,10 @@ duration in hours.
      User property is: cveValidForHours. - The server id in the settings.xml; used to retrieve encrypted -passwords from the settings.xml.
      User property is: serverId. +passwords from the settings.xml.
      User property is: serverId.
      - + showSummary @@ -714,10 +725,10 @@ passwords from the settings.xml.
      User property is: serverId - -Flag indicating whether or not to show a summary in the output.
      Default value is: true.
      User property is: showSummary. +Flag indicating whether or not to show a summary in the output.
      Default value is: true.
      User property is: showSummary.
      - + skip @@ -725,10 +736,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Dependency Check altogether.
      Default value is: false.
      User property is: dependency-check.skip. +Skip Dependency Check altogether.
      Default value is: false.
      User property is: dependency-check.skip.
      - + skipProvidedScope @@ -736,10 +747,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Analysis for Provided Scope Dependencies.
      Default value is: false.
      User property is: skipProvidedScope. +Skip Analysis for Provided Scope Dependencies.
      Default value is: false.
      User property is: skipProvidedScope.
      - + skipRuntimeScope @@ -747,10 +758,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Analysis for Runtime Scope Dependencies.
      Default value is: false.
      User property is: skipRuntimeScope. +Skip Analysis for Runtime Scope Dependencies.
      Default value is: false.
      User property is: skipRuntimeScope.
      - + skipTestScope @@ -758,10 +769,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Analysis for Test Scope Dependencies.
      Default value is: true.
      User property is: skipTestScope. +Skip Analysis for Test Scope Dependencies.
      Default value is: true.
      User property is: skipTestScope.
      - + suppressionFile @@ -769,10 +780,10 @@ passwords from the settings.xml.
      User property is: serverId - -The path to the suppression file.
      User property is: suppressionFile. +The path to the suppression file.
      User property is: suppressionFile.
      - + zipExtensions @@ -781,7 +792,7 @@ passwords from the settings.xml.
      User property is: serverId - A comma-separated list of file extensions to add to analysis next -to jar, zip, ....
      User property is: zipExtensions. +to jar, zip, ....
      User property is: zipExtensions.
      @@ -1120,6 +1131,18 @@ plug-in unless the externalReport is set to true. Default is HTML.
    33. Default: HTML

    34. +

      hintsFile:

      + +
      The path to the hints file.
      + +
        + +
      • Type: java.lang.String
      • + +
      • Required: No
      • + +
      • User Property: hintsFile
      • +

      jarAnalyzerEnabled:

      Whether or not the Jar Analyzer is enabled.
      diff --git a/dependency-check-maven/apidocs/allclasses-frame.html b/dependency-check-maven/apidocs/allclasses-frame.html index c141604ec..1454042a4 100644 --- a/dependency-check-maven/apidocs/allclasses-frame.html +++ b/dependency-check-maven/apidocs/allclasses-frame.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Maven Plugin 1.4.3 API) - +All Classes (Dependency-Check Maven Plugin 1.4.4 API) + @@ -18,10 +18,7 @@
    35. CheckMojo
    36. HelpMojo
    37. MavenEngine
    38. -
    39. MavenLoggerAdapter
    40. -
    41. MavenLoggerFactory
    42. PurgeMojo
    43. -
    44. StaticLoggerBinder
    45. UpdateMojo
    46. diff --git a/dependency-check-maven/apidocs/allclasses-noframe.html b/dependency-check-maven/apidocs/allclasses-noframe.html index c76cbada7..282abc01a 100644 --- a/dependency-check-maven/apidocs/allclasses-noframe.html +++ b/dependency-check-maven/apidocs/allclasses-noframe.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Maven Plugin 1.4.3 API) - +All Classes (Dependency-Check Maven Plugin 1.4.4 API) + @@ -18,10 +18,7 @@
    47. CheckMojo
    48. HelpMojo
    49. MavenEngine
    50. -
    51. MavenLoggerAdapter
    52. -
    53. MavenLoggerFactory
    54. PurgeMojo
    55. -
    56. StaticLoggerBinder
    57. UpdateMojo
    58. diff --git a/dependency-check-maven/apidocs/constant-values.html b/dependency-check-maven/apidocs/constant-values.html index 8139b828c..9d1a876e4 100644 --- a/dependency-check-maven/apidocs/constant-values.html +++ b/dependency-check-maven/apidocs/constant-values.html @@ -2,10 +2,10 @@ - + -Constant Field Values (Dependency-Check Maven Plugin 1.4.3 API) - +Constant Field Values (Dependency-Check Maven Plugin 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ - - - - + <noscript> <div>JavaScript is disabled on your browser.</div> </noscript> <h2>Frame Alert</h2> -<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> +<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="org/owasp/dependencycheck/maven/package-summary.html">Non-frame version</a>.</p> diff --git a/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/AggregateMojo.html b/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/AggregateMojo.html index cc76b59fb..0346a7389 100644 --- a/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/AggregateMojo.html +++ b/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/AggregateMojo.html @@ -2,10 +2,10 @@ - + -AggregateMojo (Dependency-Check Maven Plugin 1.4.3 API) - +AggregateMojo (Dependency-Check Maven Plugin 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/package-summary.html b/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/package-summary.html index 3abada450..24251cb98 100644 --- a/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/package-summary.html +++ b/dependency-check-maven/apidocs/org/owasp/dependencycheck/maven/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.maven (Dependency-Check Maven Plugin 1.4.3 API) - +org.owasp.dependencycheck.maven (Dependency-Check Maven Plugin 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ - + diff --git a/dependency-check-maven/cobertura/frame-summary.html b/dependency-check-maven/cobertura/frame-summary.html index f4cee4298..8a4b8391e 100644 --- a/dependency-check-maven/cobertura/frame-summary.html +++ b/dependency-check-maven/cobertura/frame-summary.html @@ -16,10 +16,8 @@ - - - - + +
      Package # Classes Line Coverage Branch Coverage Complexity
      All Packages10
      2%
      25/952
      0%
      3/532
      4.009
      org.owasp.dependencycheck.maven7
      0%
      0/797
      0%
      0/472
      5.026
      org.owasp.dependencycheck.maven.slf4j2
      10%
      15/142
      5%
      3/60
      2.061
      org.slf4j.impl1
      76%
      10/13
      N/A
      1
      All Packages7
      0%
      0/799
      0%
      0/474
      5.038
      org.owasp.dependencycheck.maven7
      0%
      0/799
      0%
      0/474
      5.038
      - + diff --git a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.AggregateMojo.html b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.AggregateMojo.html index 65aa9a848..74febc790 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.AggregateMojo.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.AggregateMojo.html @@ -225,10 +225,10 @@  124  
                   }
       125  0
                   if (this.isFailOnError()) {
      -  126  0
                       throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
      +  126  0
                       throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
       127  
                   } else {
      -  128  0
                       getLog().debug("One or more exceptions occured during dependency-check analysis", exCol);
      +  128  0
                       getLog().debug("One or more exceptions occurred during dependency-check analysis", exCol);
       129  
                   }
       130  0
               }
      @@ -393,7 +393,7 @@  241  0
                       getLog().debug("Database connection error", ex);
       242  
                   }
      -  243  0
                   final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
      +  243  0
                   final String msg = "An exception occurred connecting to the local database. Please see the log file for more details.";
       244  0
                   if (this.isFailOnError()) {
       245  0
                       throw new MojoExecutionException(msg, ex);
       246   @@ -477,6 +477,6 @@
       }
      - + diff --git a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.BaseDependencyCheckMojo.html b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.BaseDependencyCheckMojo.html index c19cf306b..17be0cf8d 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.BaseDependencyCheckMojo.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.BaseDependencyCheckMojo.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      BaseDependencyCheckMojo
      0%
      0/349
      0%
      0/174
      4.667
      BaseDependencyCheckMojo
      0%
      0/350
      0%
      0/174
      4.667
       
      @@ -429,1767 +429,1782 @@  208  
           private String suppressionFile;
       209   -
           /**
      +
       
       210   -
            * Flag indicating whether or not to show a summary in the output.
      +
           /**
       211   +
            * The path to the hints file.
      +  212  
            */
      -  212  0
           @SuppressWarnings("CanBeFinal")
       213   -
           @Parameter(property = "showSummary", defaultValue = "true", required = false)
      +
           @Parameter(property = "hintsFile", defaultValue = "", required = false)
       214   -
           private boolean showSummary = true;
      +
           private String hintsFile;
       215  
       
       216  
           /**
       217   -
            * Whether or not the Jar Analyzer is enabled.
      +
            * Flag indicating whether or not to show a summary in the output.
       218  
            */
      -  219   -
           @Parameter(property = "jarAnalyzerEnabled", required = false)
      +  219  0
           @SuppressWarnings("CanBeFinal")
       220   -
           private Boolean jarAnalyzerEnabled;
      +
           @Parameter(property = "showSummary", defaultValue = "true", required = false)
       221   -
       
      +
           private boolean showSummary = true;
       222   -
           /**
      +
       
       223   -
            * Whether or not the Archive Analyzer is enabled.
      +
           /**
       224   -
            */
      +
            * Whether or not the Jar Analyzer is enabled.
       225   -
           @Parameter(property = "archiveAnalyzerEnabled", required = false)
      +
            */
       226   -
           private Boolean archiveAnalyzerEnabled;
      +
           @Parameter(property = "jarAnalyzerEnabled", required = false)
       227   -
       
      +
           private Boolean jarAnalyzerEnabled;
       228   -
           /**
      +
       
       229   -
            * Sets whether the Python Distribution Analyzer will be used.
      +
           /**
       230   -
            */
      +
            * Whether or not the Archive Analyzer is enabled.
       231   -
           @Parameter(property = "pyDistributionAnalyzerEnabled", required = false)
      +
            */
       232   -
           private Boolean pyDistributionAnalyzerEnabled;
      +
           @Parameter(property = "archiveAnalyzerEnabled", required = false)
       233   -
           /**
      +
           private Boolean archiveAnalyzerEnabled;
       234   -
            * Sets whether the Python Package Analyzer will be used.
      +
       
       235   -
            */
      +
           /**
       236   -
           @Parameter(property = "pyPackageAnalyzerEnabled", required = false)
      +
            * Sets whether the Python Distribution Analyzer will be used.
       237   -
           private Boolean pyPackageAnalyzerEnabled;
      +
            */
       238   -
           /**
      +
           @Parameter(property = "pyDistributionAnalyzerEnabled", required = false)
       239   -
            * Sets whether the Ruby Gemspec Analyzer will be used.
      +
           private Boolean pyDistributionAnalyzerEnabled;
       240   -
            */
      +
           /**
       241   -
           @Parameter(property = "rubygemsAnalyzerEnabled", required = false)
      +
            * Sets whether the Python Package Analyzer will be used.
       242   -
           private Boolean rubygemsAnalyzerEnabled;
      +
            */
       243   -
           /**
      +
           @Parameter(property = "pyPackageAnalyzerEnabled", required = false)
       244   -
            * Sets whether or not the openssl Analyzer should be used.
      +
           private Boolean pyPackageAnalyzerEnabled;
       245   -
            */
      +
           /**
       246   -
           @Parameter(property = "opensslAnalyzerEnabled", required = false)
      +
            * Sets whether the Ruby Gemspec Analyzer will be used.
       247   -
           private Boolean opensslAnalyzerEnabled;
      +
            */
       248   -
           /**
      +
           @Parameter(property = "rubygemsAnalyzerEnabled", required = false)
       249   -
            * Sets whether or not the CMake Analyzer should be used.
      +
           private Boolean rubygemsAnalyzerEnabled;
       250   -
            */
      +
           /**
       251   -
           @Parameter(property = "cmakeAnalyzerEnabled", required = false)
      +
            * Sets whether or not the openssl Analyzer should be used.
       252   -
           private Boolean cmakeAnalyzerEnabled;
      +
            */
       253   -
           /**
      +
           @Parameter(property = "opensslAnalyzerEnabled", required = false)
       254   -
            * Sets whether or not the autoconf Analyzer should be used.
      +
           private Boolean opensslAnalyzerEnabled;
       255   -
            */
      +
           /**
       256   -
           @Parameter(property = "autoconfAnalyzerEnabled", required = false)
      +
            * Sets whether or not the CMake Analyzer should be used.
       257   -
           private Boolean autoconfAnalyzerEnabled;
      +
            */
       258   -
           /**
      +
           @Parameter(property = "cmakeAnalyzerEnabled", required = false)
       259   -
            * Sets whether or not the PHP Composer Lock File Analyzer should be used.
      +
           private Boolean cmakeAnalyzerEnabled;
       260   -
            */
      +
           /**
       261   -
           @Parameter(property = "composerAnalyzerEnabled", required = false)
      +
            * Sets whether or not the autoconf Analyzer should be used.
       262   -
           private Boolean composerAnalyzerEnabled;
      +
            */
       263   -
           /**
      +
           @Parameter(property = "autoconfAnalyzerEnabled", required = false)
       264   -
            * Sets whether or not the Node.js Analyzer should be used.
      +
           private Boolean autoconfAnalyzerEnabled;
       265   -
            */
      +
           /**
       266   -
           @Parameter(property = "nodeAnalyzerEnabled", required = false)
      +
            * Sets whether or not the PHP Composer Lock File Analyzer should be used.
       267   -
           private Boolean nodeAnalyzerEnabled;
      +
            */
       268   -
       
      +
           @Parameter(property = "composerAnalyzerEnabled", required = false)
       269   -
           /**
      +
           private Boolean composerAnalyzerEnabled;
       270   -
            * Whether or not the .NET Assembly Analyzer is enabled.
      +
           /**
       271   -
            */
      +
            * Sets whether or not the Node.js Analyzer should be used.
       272   -
           @Parameter(property = "assemblyAnalyzerEnabled", required = false)
      +
            */
       273   -
           private Boolean assemblyAnalyzerEnabled;
      +
           @Parameter(property = "nodeAnalyzerEnabled", required = false)
       274   -
       
      +
           private Boolean nodeAnalyzerEnabled;
       275   -
           /**
      +
       
       276   -
            * Whether or not the .NET Nuspec Analyzer is enabled.
      +
           /**
       277   -
            */
      +
            * Whether or not the .NET Assembly Analyzer is enabled.
       278   -
           @Parameter(property = "nuspecAnalyzerEnabled", required = false)
      +
            */
       279   -
           private Boolean nuspecAnalyzerEnabled;
      +
           @Parameter(property = "assemblyAnalyzerEnabled", required = false)
       280   -
       
      +
           private Boolean assemblyAnalyzerEnabled;
       281   -
           /**
      +
       
       282   -
            * Whether or not the Central Analyzer is enabled.
      +
           /**
       283   -
            */
      +
            * Whether or not the .NET Nuspec Analyzer is enabled.
       284   -
           @Parameter(property = "centralAnalyzerEnabled", required = false)
      -  285   -
           private Boolean centralAnalyzerEnabled;
      -  286   -
       
      -  287   -
           /**
      -  288   -
            * Whether or not the Nexus Analyzer is enabled.
      -  289  
            */
      -  290   -
           @Parameter(property = "nexusAnalyzerEnabled", required = false)
      -  291   -
           private Boolean nexusAnalyzerEnabled;
      -  292   +  285   +
           @Parameter(property = "nuspecAnalyzerEnabled", required = false)
      +  286   +
           private Boolean nuspecAnalyzerEnabled;
      +  287  
       
      -  293   +  288  
           /**
      +  289   +
            * Whether or not the Central Analyzer is enabled.
      +  290   +
            */
      +  291   +
           @Parameter(property = "centralAnalyzerEnabled", required = false)
      +  292   +
           private Boolean centralAnalyzerEnabled;
      +  293   +
       
       294   -
            * The URL of a Nexus server's REST API end point
      +
           /**
       295   -
            * (http://domain/nexus/service/local).
      +
            * Whether or not the Nexus Analyzer is enabled.
       296  
            */
       297   -
           @Parameter(property = "nexusUrl", required = false)
      +
           @Parameter(property = "nexusAnalyzerEnabled", required = false)
       298   -
           private String nexusUrl;
      +
           private Boolean nexusAnalyzerEnabled;
       299   -
           /**
      +
       
       300   -
            * Whether or not the configured proxy is used to connect to Nexus.
      +
           /**
       301   -
            */
      +
            * The URL of a Nexus server's REST API end point
       302   -
           @Parameter(property = "nexusUsesProxy", required = false)
      +
            * (http://domain/nexus/service/local).
       303   -
           private Boolean nexusUsesProxy;
      +
            */
       304   -
           /**
      +
           @Parameter(property = "nexusUrl", required = false)
       305   -
            * The database connection string.
      +
           private String nexusUrl;
       306   -
            */
      +
           /**
       307   -
           @Parameter(property = "connectionString", defaultValue = "", required = false)
      +
            * Whether or not the configured proxy is used to connect to Nexus.
       308   -
           private String connectionString;
      +
            */
       309   -
       
      +
           @Parameter(property = "nexusUsesProxy", required = false)
       310   -
           /**
      +
           private Boolean nexusUsesProxy;
       311   -
            * Returns the connection string.
      +
           /**
       312   -
            *
      +
            * The database connection string.
       313   -
            * @return the connection string
      +
            */
       314   -
            */
      +
           @Parameter(property = "connectionString", defaultValue = "", required = false)
       315   -
           protected String getConnectionString() {
      -  316  0
               return connectionString;
      -  317   -
           }
      -  318   -
           /**
      -  319   -
            * The database driver name. An example would be org.h2.Driver.
      -  320   -
            */
      -  321   -
           @Parameter(property = "databaseDriverName", defaultValue = "", required = false)
      -  322   -
           private String databaseDriverName;
      -  323   -
           /**
      -  324   -
            * The path to the database driver if it is not on the class path.
      -  325   -
            */
      -  326   -
           @Parameter(property = "databaseDriverPath", defaultValue = "", required = false)
      -  327   -
           private String databaseDriverPath;
      -  328   -
           /**
      -  329   -
            * The server id in the settings.xml; used to retrieve encrypted passwords
      -  330   -
            * from the settings.xml.
      -  331   -
            */
      -  332   -
           @Parameter(property = "serverId", defaultValue = "", required = false)
      -  333   -
           private String serverId;
      -  334   -
           /**
      -  335   -
            * A reference to the settings.xml settings.
      -  336   -
            */
      -  337   -
           @Parameter(defaultValue = "${settings}", readonly = true, required = true)
      -  338   -
           private org.apache.maven.settings.Settings settingsXml;
      -  339   -
           /**
      -  340   -
            * The security dispatcher that can decrypt passwords in the settings.xml.
      -  341   -
            */
      -  342   -
           @Component(role = SecDispatcher.class, hint = "default")
      -  343   -
           private SecDispatcher securityDispatcher;
      -  344   -
           /**
      -  345   -
            * The database user name.
      -  346   -
            */
      -  347   -
           @Parameter(property = "databaseUser", defaultValue = "", required = false)
      -  348   -
           private String databaseUser;
      -  349   -
           /**
      -  350   -
            * The password to use when connecting to the database.
      -  351   -
            */
      -  352   -
           @Parameter(property = "databasePassword", defaultValue = "", required = false)
      -  353   -
           private String databasePassword;
      -  354   -
           /**
      -  355   -
            * A comma-separated list of file extensions to add to analysis next to jar,
      -  356   -
            * zip, ....
      -  357   -
            */
      -  358   -
           @Parameter(property = "zipExtensions", required = false)
      -  359   -
           private String zipExtensions;
      -  360   -
           /**
      -  361   -
            * Skip Dependency Check altogether.
      -  362   -
            */
      -  363  0
           @SuppressWarnings("CanBeFinal")
      -  364   -
           @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false)
      -  365   -
           private boolean skip = false;
      -  366   -
           /**
      -  367   -
            * Skip Analysis for Test Scope Dependencies.
      -  368   -
            */
      -  369  0
           @SuppressWarnings("CanBeFinal")
      -  370   -
           @Parameter(property = "skipTestScope", defaultValue = "true", required = false)
      -  371   -
           private boolean skipTestScope = true;
      -  372   -
           /**
      -  373   -
            * Skip Analysis for Runtime Scope Dependencies.
      -  374   -
            */
      -  375  0
           @SuppressWarnings("CanBeFinal")
      -  376   -
           @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false)
      -  377   -
           private boolean skipRuntimeScope = false;
      -  378   -
           /**
      -  379   -
            * Skip Analysis for Provided Scope Dependencies.
      -  380   -
            */
      -  381  0
           @SuppressWarnings("CanBeFinal")
      -  382   -
           @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false)
      -  383   -
           private boolean skipProvidedScope = false;
      -  384   -
           /**
      -  385   -
            * The data directory, hold DC SQL DB.
      -  386   -
            */
      -  387   -
           @Parameter(property = "dataDirectory", defaultValue = "", required = false)
      -  388   -
           private String dataDirectory;
      -  389   -
           /**
      -  390   -
            * Data Mirror URL for CVE 1.2.
      -  391   -
            */
      -  392   -
           @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false)
      -  393   -
           private String cveUrl12Modified;
      -  394   -
           /**
      -  395   -
            * Data Mirror URL for CVE 2.0.
      -  396   -
            */
      -  397   -
           @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false)
      -  398   -
           private String cveUrl20Modified;
      -  399   -
           /**
      -  400   -
            * Base Data Mirror URL for CVE 1.2.
      -  401   -
            */
      -  402   -
           @Parameter(property = "cveUrl12Base", defaultValue = "", required = false)
      -  403   -
           private String cveUrl12Base;
      -  404   -
           /**
      -  405   -
            * Data Mirror URL for CVE 2.0.
      -  406   -
            */
      -  407   -
           @Parameter(property = "cveUrl20Base", defaultValue = "", required = false)
      -  408   -
           private String cveUrl20Base;
      -  409   -
           /**
      -  410   -
            * Optionally skip excessive CVE update checks for a designated duration in
      -  411   -
            * hours.
      -  412   -
            */
      -  413   -
           @Parameter(property = "cveValidForHours", defaultValue = "", required = false)
      -  414   -
           private Integer cveValidForHours;
      -  415   +
           private String connectionString;
      +  316  
       
      +  317   +
           /**
      +  318   +
            * Returns the connection string.
      +  319   +
            *
      +  320   +
            * @return the connection string
      +  321   +
            */
      +  322   +
           protected String getConnectionString() {
      +  323  0
               return connectionString;
      +  324   +
           }
      +  325   +
           /**
      +  326   +
            * The database driver name. An example would be org.h2.Driver.
      +  327   +
            */
      +  328   +
           @Parameter(property = "databaseDriverName", defaultValue = "", required = false)
      +  329   +
           private String databaseDriverName;
      +  330   +
           /**
      +  331   +
            * The path to the database driver if it is not on the class path.
      +  332   +
            */
      +  333   +
           @Parameter(property = "databaseDriverPath", defaultValue = "", required = false)
      +  334   +
           private String databaseDriverPath;
      +  335   +
           /**
      +  336   +
            * The server id in the settings.xml; used to retrieve encrypted passwords
      +  337   +
            * from the settings.xml.
      +  338   +
            */
      +  339   +
           @Parameter(property = "serverId", defaultValue = "", required = false)
      +  340   +
           private String serverId;
      +  341   +
           /**
      +  342   +
            * A reference to the settings.xml settings.
      +  343   +
            */
      +  344   +
           @Parameter(defaultValue = "${settings}", readonly = true, required = true)
      +  345   +
           private org.apache.maven.settings.Settings settingsXml;
      +  346   +
           /**
      +  347   +
            * The security dispatcher that can decrypt passwords in the settings.xml.
      +  348   +
            */
      +  349   +
           @Component(role = SecDispatcher.class, hint = "default")
      +  350   +
           private SecDispatcher securityDispatcher;
      +  351   +
           /**
      +  352   +
            * The database user name.
      +  353   +
            */
      +  354   +
           @Parameter(property = "databaseUser", defaultValue = "", required = false)
      +  355   +
           private String databaseUser;
      +  356   +
           /**
      +  357   +
            * The password to use when connecting to the database.
      +  358   +
            */
      +  359   +
           @Parameter(property = "databasePassword", defaultValue = "", required = false)
      +  360   +
           private String databasePassword;
      +  361   +
           /**
      +  362   +
            * A comma-separated list of file extensions to add to analysis next to jar,
      +  363   +
            * zip, ....
      +  364   +
            */
      +  365   +
           @Parameter(property = "zipExtensions", required = false)
      +  366   +
           private String zipExtensions;
      +  367   +
           /**
      +  368   +
            * Skip Dependency Check altogether.
      +  369   +
            */
      +  370  0
           @SuppressWarnings("CanBeFinal")
      +  371   +
           @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false)
      +  372   +
           private boolean skip = false;
      +  373   +
           /**
      +  374   +
            * Skip Analysis for Test Scope Dependencies.
      +  375   +
            */
      +  376  0
           @SuppressWarnings("CanBeFinal")
      +  377   +
           @Parameter(property = "skipTestScope", defaultValue = "true", required = false)
      +  378   +
           private boolean skipTestScope = true;
      +  379   +
           /**
      +  380   +
            * Skip Analysis for Runtime Scope Dependencies.
      +  381   +
            */
      +  382  0
           @SuppressWarnings("CanBeFinal")
      +  383   +
           @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false)
      +  384   +
           private boolean skipRuntimeScope = false;
      +  385   +
           /**
      +  386   +
            * Skip Analysis for Provided Scope Dependencies.
      +  387   +
            */
      +  388  0
           @SuppressWarnings("CanBeFinal")
      +  389   +
           @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false)
      +  390   +
           private boolean skipProvidedScope = false;
      +  391   +
           /**
      +  392   +
            * The data directory, hold DC SQL DB.
      +  393   +
            */
      +  394   +
           @Parameter(property = "dataDirectory", defaultValue = "", required = false)
      +  395   +
           private String dataDirectory;
      +  396   +
           /**
      +  397   +
            * Data Mirror URL for CVE 1.2.
      +  398   +
            */
      +  399   +
           @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false)
      +  400   +
           private String cveUrl12Modified;
      +  401   +
           /**
      +  402   +
            * Data Mirror URL for CVE 2.0.
      +  403   +
            */
      +  404   +
           @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false)
      +  405   +
           private String cveUrl20Modified;
      +  406   +
           /**
      +  407   +
            * Base Data Mirror URL for CVE 1.2.
      +  408   +
            */
      +  409   +
           @Parameter(property = "cveUrl12Base", defaultValue = "", required = false)
      +  410   +
           private String cveUrl12Base;
      +  411   +
           /**
      +  412   +
            * Data Mirror URL for CVE 2.0.
      +  413   +
            */
      +  414   +
           @Parameter(property = "cveUrl20Base", defaultValue = "", required = false)
      +  415   +
           private String cveUrl20Base;
       416  
           /**
       417   -
            * The path to mono for .NET Assembly analysis on non-windows systems.
      +
            * Optionally skip excessive CVE update checks for a designated duration in
       418   -
            */
      +
            * hours.
       419   -
           @Parameter(property = "pathToMono", defaultValue = "", required = false)
      +
            */
       420   -
           private String pathToMono;
      +
           @Parameter(property = "cveValidForHours", defaultValue = "", required = false)
       421   -
       
      +
           private Integer cveValidForHours;
       422   -
           /**
      +
       
       423   -
            * The Proxy URL.
      +
           /**
       424   -
            *
      +
            * The path to mono for .NET Assembly analysis on non-windows systems.
       425   -
            * @deprecated Please use mavenSettings instead
      +
            */
       426   -
            */
      -  427  0
           @SuppressWarnings("CanBeFinal")
      +
           @Parameter(property = "pathToMono", defaultValue = "", required = false)
      +  427   +
           private String pathToMono;
       428   -
           @Parameter(property = "proxyUrl", defaultValue = "", required = false)
      +
       
       429   -
           @Deprecated
      +
           /**
       430   -
           private String proxyUrl = null;
      +
            * The Proxy URL.
       431   -
           /**
      +
            *
       432   -
            * Sets whether or not the external report format should be used.
      +
            * @deprecated Please use mavenSettings instead
       433   -
            *
      -  434   -
            * @deprecated the internal report is no longer supported
      +
            */
      +  434  0
           @SuppressWarnings("CanBeFinal")
       435   -
            */
      -  436  0
           @SuppressWarnings("CanBeFinal")
      +
           @Parameter(property = "proxyUrl", defaultValue = "", required = false)
      +  436   +
           @Deprecated
       437   -
           @Parameter(property = "externalReport")
      +
           private String proxyUrl = null;
       438   -
           @Deprecated
      +
           /**
       439   -
           private String externalReport = null;
      +
            * Sets whether or not the external report format should be used.
       440   -
           // </editor-fold>
      +
            *
       441   -
           //<editor-fold defaultstate="collapsed" desc="Base Maven implementation">
      +
            * @deprecated the internal report is no longer supported
       442   -
       
      -  443   -
           /**
      +
            */
      +  443  0
           @SuppressWarnings("CanBeFinal")
       444   -
            * Executes dependency-check.
      +
           @Parameter(property = "externalReport")
       445   -
            *
      -  446   -
            * @throws MojoExecutionException thrown if there is an exception executing
      -  447   -
            * the mojo
      -  448   -
            * @throws MojoFailureException thrown if dependency-check failed the build
      -  449   -
            */
      -  450   -
           @Override
      -  451   -
           public void execute() throws MojoExecutionException, MojoFailureException {
      -  452  0
               generatingSite = false;
      -  453  0
               if (skip) {
      -  454  0
                   getLog().info("Skipping " + getName(Locale.US));
      -  455   -
               } else {
      -  456  0
                   validateAggregate();
      -  457  0
                   project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory);
      -  458  0
                   runCheck();
      -  459   -
               }
      -  460  0
           }
      -  461   -
       
      -  462   -
           /**
      -  463   -
            * Checks if the aggregate configuration parameter has been set to true. If
      -  464   -
            * it has a MojoExecutionException is thrown because the aggregate
      -  465   -
            * configuration parameter is no longer supported.
      -  466   -
            *
      -  467   -
            * @throws MojoExecutionException thrown if aggregate is set to true
      -  468   -
            */
      -  469   -
           private void validateAggregate() throws MojoExecutionException {
      -  470  0
               if (aggregate != null && aggregate) {
      -  471  0
                   final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. "
      -  472   -
                           + "Please use the aggregate goal instead.";
      -  473  0
                   throw new MojoExecutionException(msg);
      -  474   -
               }
      -  475  0
           }
      -  476   -
       
      -  477   -
           /**
      -  478   -
            * Generates the Dependency-Check Site Report.
      -  479   -
            *
      -  480   -
            * @param sink the sink to write the report to
      -  481   -
            * @param locale the locale to use when generating the report
      -  482   -
            * @throws MavenReportException if a maven report exception occurs
      -  483   -
            * @deprecated use
      -  484   -
            * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)}
      -  485   -
            * instead.
      -  486   -
            */
      -  487   -
           @Override
      -  488  
           @Deprecated
      -  489   -
           public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
      -  490  0
               generate((Sink) sink, locale);
      -  491  0
           }
      -  492   +  446   +
           private String externalReport = null;
      +  447   +
           // </editor-fold>
      +  448   +
           //<editor-fold defaultstate="collapsed" desc="Base Maven implementation">
      +  449  
       
      -  493   +  450  
           /**
      -  494   -
            * A flag indicating whether or not the maven site is being generated.
      -  495   -
            */
      -  496  0
           private boolean generatingSite = false;
      -  497   -
       
      -  498   -
           /**
      -  499   -
            * Returns true if the Maven site is being generated.
      -  500   +  451   +
            * Executes dependency-check.
      +  452  
            *
      +  453   +
            * @throws MojoExecutionException thrown if there is an exception executing
      +  454   +
            * the mojo
      +  455   +
            * @throws MojoFailureException thrown if dependency-check failed the build
      +  456   +
            */
      +  457   +
           @Override
      +  458   +
           public void execute() throws MojoExecutionException, MojoFailureException {
      +  459  0
               generatingSite = false;
      +  460  0
               if (skip) {
      +  461  0
                   getLog().info("Skipping " + getName(Locale.US));
      +  462   +
               } else {
      +  463  0
                   validateAggregate();
      +  464  0
                   project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory);
      +  465  0
                   runCheck();
      +  466   +
               }
      +  467  0
           }
      +  468   +
       
      +  469   +
           /**
      +  470   +
            * Checks if the aggregate configuration parameter has been set to true. If
      +  471   +
            * it has a MojoExecutionException is thrown because the aggregate
      +  472   +
            * configuration parameter is no longer supported.
      +  473   +
            *
      +  474   +
            * @throws MojoExecutionException thrown if aggregate is set to true
      +  475   +
            */
      +  476   +
           private void validateAggregate() throws MojoExecutionException {
      +  477  0
               if (aggregate != null && aggregate) {
      +  478  0
                   final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. "
      +  479   +
                           + "Please use the aggregate goal instead.";
      +  480  0
                   throw new MojoExecutionException(msg);
      +  481   +
               }
      +  482  0
           }
      +  483   +
       
      +  484   +
           /**
      +  485   +
            * Generates the Dependency-Check Site Report.
      +  486   +
            *
      +  487   +
            * @param sink the sink to write the report to
      +  488   +
            * @param locale the locale to use when generating the report
      +  489   +
            * @throws MavenReportException if a maven report exception occurs
      +  490   +
            * @deprecated use
      +  491   +
            * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)}
      +  492   +
            * instead.
      +  493   +
            */
      +  494   +
           @Override
      +  495   +
           @Deprecated
      +  496   +
           public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
      +  497  0
               generate((Sink) sink, locale);
      +  498  0
           }
      +  499   +
       
      +  500   +
           /**
       501   -
            * @return true if the Maven site is being generated
      +
            * A flag indicating whether or not the maven site is being generated.
       502  
            */
      -  503   -
           protected boolean isGeneratingSite() {
      -  504  0
               return generatingSite;
      +  503  0
           private boolean generatingSite = false;
      +  504   +
       
       505   -
           }
      +
           /**
       506   -
       
      +
            * Returns true if the Maven site is being generated.
       507   -
           /**
      +
            *
       508   -
            * Generates the Dependency-Check Site Report.
      +
            * @return true if the Maven site is being generated
       509   -
            *
      +
            */
       510   -
            * @param sink the sink to write the report to
      -  511   -
            * @param locale the locale to use when generating the report
      +
           protected boolean isGeneratingSite() {
      +  511  0
               return generatingSite;
       512   -
            * @throws MavenReportException if a maven report exception occurs
      +
           }
       513   -
            */
      +
       
       514   -
           public void generate(Sink sink, Locale locale) throws MavenReportException {
      -  515  0
               generatingSite = true;
      +
           /**
      +  515   +
            * Generates the Dependency-Check Site Report.
       516   -
               try {
      -  517  0
                   validateAggregate();
      -  518  0
               } catch (MojoExecutionException ex) {
      -  519  0
                   throw new MavenReportException(ex.getMessage());
      -  520  0
               }
      -  521  0
               project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
      -  522   -
               try {
      -  523  0
                   runCheck();
      -  524  0
               } catch (MojoExecutionException ex) {
      -  525  0
                   throw new MavenReportException(ex.getMessage(), ex);
      -  526  0
               } catch (MojoFailureException ex) {
      -  527  0
                   getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build");
      -  528  0
               }
      -  529  0
           }
      -  530   -
       
      -  531   -
           /**
      -  532   -
            * Returns the correct output directory depending on if a site is being
      -  533   -
            * executed or not.
      -  534  
            *
      -  535   -
            * @return the directory to write the report(s)
      -  536   -
            * @throws MojoExecutionException thrown if there is an error loading the
      +  517   +
            * @param sink the sink to write the report to
      +  518   +
            * @param locale the locale to use when generating the report
      +  519   +
            * @throws MavenReportException if a maven report exception occurs
      +  520   +
            */
      +  521   +
           public void generate(Sink sink, Locale locale) throws MavenReportException {
      +  522  0
               generatingSite = true;
      +  523   +
               try {
      +  524  0
                   validateAggregate();
      +  525  0
               } catch (MojoExecutionException ex) {
      +  526  0
                   throw new MavenReportException(ex.getMessage());
      +  527  0
               }
      +  528  0
               project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
      +  529   +
               try {
      +  530  0
                   runCheck();
      +  531  0
               } catch (MojoExecutionException ex) {
      +  532  0
                   throw new MavenReportException(ex.getMessage(), ex);
      +  533  0
               } catch (MojoFailureException ex) {
      +  534  0
                   getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build");
      +  535  0
               }
      +  536  0
           }
       537   -
            * file path
      +
       
       538   -
            */
      +
           /**
       539   -
           protected File getCorrectOutputDirectory() throws MojoExecutionException {
      -  540  0
               return getCorrectOutputDirectory(this.project);
      +
            * Returns the correct output directory depending on if a site is being
      +  540   +
            * executed or not.
       541   -
           }
      +
            *
       542   -
       
      +
            * @return the directory to write the report(s)
       543   -
           /**
      +
            * @throws MojoExecutionException thrown if there is an error loading the
       544   -
            * Returns the correct output directory depending on if a site is being
      +
            * file path
       545   -
            * executed or not.
      +
            */
       546   -
            *
      -  547   -
            * @param current the Maven project to get the output directory from
      +
           protected File getCorrectOutputDirectory() throws MojoExecutionException {
      +  547  0
               return getCorrectOutputDirectory(this.project);
       548   -
            * @return the directory to write the report(s)
      +
           }
       549   -
            */
      +
       
       550   -
           protected File getCorrectOutputDirectory(MavenProject current) {
      -  551  0
               final Object obj = current.getContextValue(getOutputDirectoryContextKey());
      -  552  0
               if (obj != null && obj instanceof File) {
      -  553  0
                   return (File) obj;
      -  554   -
               }
      -  555  0
               File target = new File(current.getBuild().getDirectory());
      -  556  0
               if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) {
      -  557  0
                   target = target.getParentFile();
      -  558   -
               }
      -  559  0
               return target;
      -  560   -
           }
      -  561   -
       
      -  562  
           /**
      -  563   +  551  
            * Returns the correct output directory depending on if a site is being
      -  564   +  552  
            * executed or not.
      -  565   +  553  
            *
      -  566   +  554  
            * @param current the Maven project to get the output directory from
      -  567   +  555  
            * @return the directory to write the report(s)
      -  568   +  556  
            */
      -  569   -
           protected File getDataFile(MavenProject current) {
      -  570  0
               if (getLog().isDebugEnabled()) {
      -  571  0
                   getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey()));
      -  572   +  557   +
           protected File getCorrectOutputDirectory(MavenProject current) {
      +  558  0
               final Object obj = current.getContextValue(getOutputDirectoryContextKey());
      +  559  0
               if (obj != null && obj instanceof File) {
      +  560  0
                   return (File) obj;
      +  561  
               }
      -  573  0
               final Object obj = current.getContextValue(getDataFileContextKey());
      -  574  0
               if (obj != null) {
      -  575  0
                   if (obj instanceof String) {
      -  576  0
                       final File f = new File((String) obj);
      -  577  0
                       return f;
      -  578   -
                   }
      -  579  0
               } else if (getLog().isDebugEnabled()) {
      -  580  0
                   getLog().debug("Context value not found");
      -  581   +  562  0
               File target = new File(current.getBuild().getDirectory());
      +  563  0
               if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) {
      +  564  0
                   target = target.getParentFile();
      +  565  
               }
      -  582  0
               return null;
      -  583   +  566  0
               return target;
      +  567  
           }
      -  584   +  568  
       
      -  585   +  569  
           /**
      -  586   -
            * Scans the project's artifacts and adds them to the engine's dependency
      -  587   -
            * list.
      -  588   +  570   +
            * Returns the correct output directory depending on if a site is being
      +  571   +
            * executed or not.
      +  572  
            *
      -  589   -
            * @param project the project to scan the dependencies of
      -  590   -
            * @param engine the engine to use to scan the dependencies
      -  591   -
            * @return a collection of exceptions that may have occurred while resolving
      -  592   -
            * and scanning the dependencies
      -  593   +  573   +
            * @param current the Maven project to get the output directory from
      +  574   +
            * @return the directory to write the report(s)
      +  575  
            */
      +  576   +
           protected File getDataFile(MavenProject current) {
      +  577  0
               if (getLog().isDebugEnabled()) {
      +  578  0
                   getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey()));
      +  579   +
               }
      +  580  0
               final Object obj = current.getContextValue(getDataFileContextKey());
      +  581  0
               if (obj != null) {
      +  582  0
                   if (obj instanceof String) {
      +  583  0
                       final File f = new File((String) obj);
      +  584  0
                       return f;
      +  585   +
                   }
      +  586  0
               } else if (getLog().isDebugEnabled()) {
      +  587  0
                   getLog().debug("Context value not found");
      +  588   +
               }
      +  589  0
               return null;
      +  590   +
           }
      +  591   +
       
      +  592   +
           /**
      +  593   +
            * Scans the project's artifacts and adds them to the engine's dependency
       594   -
           protected ExceptionCollection scanArtifacts(MavenProject project, MavenEngine engine) {
      +
            * list.
       595   -
               // <editor-fold defaultstate="collapsed" desc="old implementation">
      +
            *
       596   -
               /*
      +
            * @param project the project to scan the dependencies of
       597   -
                   for (Artifact a : project.getArtifacts()) {
      +
            * @param engine the engine to use to scan the dependencies
       598   -
                   if (excludeFromScan(a)) {
      +
            * @return a collection of exceptions that may have occurred while resolving
       599   -
                   continue;
      +
            * and scanning the dependencies
       600   -
                   }
      +
            */
       601   -
                   final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
      +
           protected ExceptionCollection scanArtifacts(MavenProject project, MavenEngine engine) {
       602   -
                   if (deps != null) {
      +
               // <editor-fold defaultstate="collapsed" desc="old implementation">
       603   -
                   if (deps.size() == 1) {
      +
               /*
       604   -
                   final Dependency d = deps.get(0);
      +
                   for (Artifact a : project.getArtifacts()) {
       605   -
                   if (d != null) {
      +
                   if (excludeFromScan(a)) {
       606   -
                   final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
      +
                   continue;
       607   -
                   d.addAsEvidence("pom", ma, Confidence.HIGHEST);
      +
                   }
       608   -
                   d.addProjectReference(project.getName());
      +
                   final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
       609   -
                   if (getLog().isDebugEnabled()) {
      +
                   if (deps != null) {
       610   -
                   getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(),
      +
                   if (deps.size() == 1) {
       611   -
                   d.getDisplayFileName()));
      +
                   final Dependency d = deps.get(0);
       612   -
                   }
      +
                   if (d != null) {
       613   -
                   }
      +
                   final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
       614   -
                   } else if (getLog().isDebugEnabled()) {
      +
                   d.addAsEvidence("pom", ma, Confidence.HIGHEST);
       615   -
                   final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'",
      +
                   d.addProjectReference(project.getName());
       616   -
                   a.getGroupId(), a.getArtifactId(), a.getVersion());
      +
                   if (getLog().isDebugEnabled()) {
       617   -
                   getLog().debug(msg);
      +
                   getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(),
       618   -
                   }
      +
                   d.getDisplayFileName()));
       619  
                   }
       620  
                   }
       621   -
                */
      +
                   } else if (getLog().isDebugEnabled()) {
       622   -
               // </editor-fold>
      +
                   final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'",
       623   -
               try {
      -  624  0
                   final DependencyNode dn = dependencyGraphBuilder.buildDependencyGraph(project, null, reactorProjects);
      -  625  0
                   return collectDependencies(engine, project, dn.getChildren());
      -  626  0
               } catch (DependencyGraphBuilderException ex) {
      -  627  0
                   final String msg = String.format("Unable to build dependency graph on project %s", project.getName());
      -  628  0
                   getLog().debug(msg, ex);
      -  629  0
                   return new ExceptionCollection(msg, ex);
      +
                   a.getGroupId(), a.getArtifactId(), a.getVersion());
      +  624   +
                   getLog().debug(msg);
      +  625   +
                   }
      +  626   +
                   }
      +  627   +
                   }
      +  628   +
                */
      +  629   +
               // </editor-fold>
       630   -
               }
      -  631   -
           }
      -  632   -
       
      -  633   -
           /**
      -  634   -
            * Resolves the projects artifacts using Aether and scans the resulting
      -  635   -
            * dependencies.
      -  636   -
            *
      +
               try {
      +  631  0
                   final DependencyNode dn = dependencyGraphBuilder.buildDependencyGraph(project, null, reactorProjects);
      +  632  0
                   return collectDependencies(engine, project, dn.getChildren());
      +  633  0
               } catch (DependencyGraphBuilderException ex) {
      +  634  0
                   final String msg = String.format("Unable to build dependency graph on project %s", project.getName());
      +  635  0
                   getLog().debug(msg, ex);
      +  636  0
                   return new ExceptionCollection(msg, ex);
       637   -
            * @param engine the core dependency-check engine
      +
               }
       638   -
            * @param project the project being scanned
      +
           }
       639   -
            * @param nodes the list of dependency nodes, generally obtained via the
      +
       
       640   -
            * DependencyGraphBuilder
      +
           /**
       641   -
            * @return a collection of exceptions that may have occurred while resolving
      +
            * Resolves the projects artifacts using Aether and scans the resulting
       642   -
            * and scanning the dependencies
      +
            * dependencies.
       643   -
            */
      +
            *
       644   -
           private ExceptionCollection collectDependencies(MavenEngine engine, MavenProject project, List<DependencyNode> nodes) {
      -  645  0
               ExceptionCollection exCol = null;
      -  646  0
               for (DependencyNode dependencyNode : nodes) {
      -  647  0
                   exCol = collectDependencies(engine, project, dependencyNode.getChildren());
      -  648  0
                   if (excludeFromScan(dependencyNode.getArtifact().getScope())) {
      -  649  0
                       continue;
      +
            * @param engine the core dependency-check engine
      +  645   +
            * @param project the project being scanned
      +  646   +
            * @param nodes the list of dependency nodes, generally obtained via the
      +  647   +
            * DependencyGraphBuilder
      +  648   +
            * @return a collection of exceptions that may have occurred while resolving
      +  649   +
            * and scanning the dependencies
       650   +
            */
      +  651   +
           private ExceptionCollection collectDependencies(MavenEngine engine, MavenProject project, List<DependencyNode> nodes) {
      +  652  0
               ExceptionCollection exCol = null;
      +  653  0
               for (DependencyNode dependencyNode : nodes) {
      +  654  0
                   exCol = collectDependencies(engine, project, dependencyNode.getChildren());
      +  655  0
                   if (excludeFromScan(dependencyNode.getArtifact().getScope())) {
      +  656  0
                       continue;
      +  657  
                   }
      -  651  0
                   final ArtifactRequest request = new ArtifactRequest();
      -  652  0
                   request.setArtifact(new DefaultArtifact(dependencyNode.getArtifact().getId()));
      -  653  0
                   request.setRepositories(remoteRepos);
      -  654   +  658  0
                   final ArtifactRequest request = new ArtifactRequest();
      +  659  0
                   request.setArtifact(new DefaultArtifact(dependencyNode.getArtifact().getId()));
      +  660  0
                   request.setRepositories(remoteRepos);
      +  661  
                   try {
      -  655  0
                       final ArtifactResult result = repoSystem.resolveArtifact(repoSession, request);
      -  656  0
                       if (result.isResolved() && result.getArtifact() != null && result.getArtifact().getFile() != null) {
      -  657  0
                           final List<Dependency> deps = engine.scan(result.getArtifact().getFile().getAbsoluteFile());
      -  658  0
                           if (deps != null) {
      -  659  0
                               if (deps.size() == 1) {
      -  660  0
                                   final Dependency d = deps.get(0);
      -  661  0
                                   if (d != null) {
      -  662  0
                                       final Artifact a = result.getArtifact();
      -  663  0
                                       final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
      -  664  0
                                       d.addAsEvidence("pom", ma, Confidence.HIGHEST);
      -  665  0
                                       d.addProjectReference(project.getName() + ":" + dependencyNode.getArtifact().getScope());
      -  666  0
                                       if (getLog().isDebugEnabled()) {
      -  667  0
                                           getLog().debug(String.format("Adding project reference %s on dependency %s",
      -  668  0
                                                   project.getName(), d.getDisplayFileName()));
      -  669   -
                                       }
      -  670   -
                                   }
      -  671  0
                               } else if (getLog().isDebugEnabled()) {
      -  672  0
                                   final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s' in project %s",
      -  673  0
                                           dependencyNode.getArtifact().getId(), project.getName());
      -  674  0
                                   getLog().debug(msg);
      -  675  0
                               }
      +  662  0
                       final ArtifactResult result = repoSystem.resolveArtifact(repoSession, request);
      +  663  0
                       if (result.isResolved() && result.getArtifact() != null && result.getArtifact().getFile() != null) {
      +  664  0
                           final List<Dependency> deps = engine.scan(result.getArtifact().getFile().getAbsoluteFile(),
      +  665  0
                                   project.getName() + ":" + dependencyNode.getArtifact().getScope());
      +  666  0
                           if (deps != null) {
      +  667  0
                               if (deps.size() == 1) {
      +  668  0
                                   final Dependency d = deps.get(0);
      +  669  0
                                   if (d != null) {
      +  670  0
                                       final Artifact a = result.getArtifact();
      +  671  0
                                       final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
      +  672  0
                                       d.addAsEvidence("pom", ma, Confidence.HIGHEST);
      +  673  0
                                       if (getLog().isDebugEnabled()) {
      +  674  0
                                           getLog().debug(String.format("Adding project reference %s on dependency %s",
      +  675  0
                                                   project.getName(), d.getDisplayFileName()));
       676   +
                                       }
      +  677   +
                                   }
      +  678  0
                               } else if (getLog().isDebugEnabled()) {
      +  679  0
                                   final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s' in project %s",
      +  680  0
                                           dependencyNode.getArtifact().getId(), project.getName());
      +  681  0
                                   getLog().debug(msg);
      +  682  0
                               }
      +  683  
                           } else {
      -  677  0
                               final String msg = String.format("Error resolving '%s' in project %s",
      -  678  0
                                       dependencyNode.getArtifact().getId(), project.getName());
      -  679  0
                               if (exCol == null) {
      -  680  0
                                   exCol = new ExceptionCollection();
      -  681   +  684  0
                               final String msg = String.format("Error resolving '%s' in project %s",
      +  685  0
                                       dependencyNode.getArtifact().getId(), project.getName());
      +  686  0
                               if (exCol == null) {
      +  687  0
                                   exCol = new ExceptionCollection();
      +  688  
                               }
      -  682  0
                               getLog().error(msg);
      -  683  0
                               for (Exception ex : result.getExceptions()) {
      -  684  0
                                   exCol.addException(ex);
      -  685  0
                               }
      -  686   -
                           }
      -  687  0
                       } else {
      -  688  0
                           final String msg = String.format("Unable to resolve '%s' in project %s",
      -  689  0
                                   dependencyNode.getArtifact().getId(), project.getName());
      -  690  0
                           getLog().debug(msg);
      -  691  0
                           if (exCol == null) {
      -  692  0
                               exCol = new ExceptionCollection();
      +  689  0
                               getLog().error(msg);
      +  690  0
                               for (Exception ex : result.getExceptions()) {
      +  691  0
                                   exCol.addException(ex);
      +  692  0
                               }
       693  
                           }
      -  694  0
                           for (Exception ex : result.getExceptions()) {
      -  695  0
                               exCol.addException(ex);
      -  696  0
                           }
      -  697   +  694  0
                       } else {
      +  695  0
                           final String msg = String.format("Unable to resolve '%s' in project %s",
      +  696  0
                                   dependencyNode.getArtifact().getId(), project.getName());
      +  697  0
                           getLog().debug(msg);
      +  698  0
                           if (exCol == null) {
      +  699  0
                               exCol = new ExceptionCollection();
      +  700   +
                           }
      +  701  0
                           for (Exception ex : result.getExceptions()) {
      +  702  0
                               exCol.addException(ex);
      +  703  0
                           }
      +  704  
                       }
      -  698  0
                   } catch (ArtifactResolutionException ex) {
      -  699  0
                       if (exCol == null) {
      -  700  0
                           exCol = new ExceptionCollection();
      -  701   -
                       }
      -  702  0
                       exCol.addException(ex);
      -  703  0
                   }
      -  704  0
               }
      -  705  0
               return exCol;
      -  706   -
           }
      -  707   -
       
      +  705  0
                   } catch (ArtifactResolutionException ex) {
      +  706  0
                       if (exCol == null) {
      +  707  0
                           exCol = new ExceptionCollection();
       708   -
           /**
      -  709   -
            * Executes the dependency-check scan and generates the necassary report.
      -  710   -
            *
      -  711   -
            * @throws MojoExecutionException thrown if there is an exception running
      -  712   -
            * the scan
      +
                       }
      +  709  0
                       exCol.addException(ex);
      +  710  0
                   }
      +  711  0
               }
      +  712  0
               return exCol;
       713   -
            * @throws MojoFailureException thrown if dependency-check is configured to
      +
           }
       714   -
            * fail the build
      -  715   -
            */
      -  716   -
           public abstract void runCheck() throws MojoExecutionException, MojoFailureException;
      -  717  
       
      -  718   +  715  
           /**
      -  719   -
            * Sets the Reporting output directory.
      -  720   +  716   +
            * Executes the dependency-check scan and generates the necassary report.
      +  717  
            *
      +  718   +
            * @throws MojoExecutionException thrown if there is an exception running
      +  719   +
            * the scan
      +  720   +
            * @throws MojoFailureException thrown if dependency-check is configured to
       721   -
            * @param directory the output directory
      +
            * fail the build
       722  
            */
       723   -
           @Override
      +
           public abstract void runCheck() throws MojoExecutionException, MojoFailureException;
       724   -
           public void setReportOutputDirectory(File directory) {
      -  725  0
               reportOutputDirectory = directory;
      -  726  0
           }
      +
       
      +  725   +
           /**
      +  726   +
            * Sets the Reporting output directory.
       727   -
       
      +
            *
       728   -
           /**
      +
            * @param directory the output directory
       729   -
            * Returns the report output directory.
      +
            */
       730   -
            *
      +
           @Override
       731   -
            * @return the report output directory
      -  732   -
            */
      -  733   -
           @Override
      +
           public void setReportOutputDirectory(File directory) {
      +  732  0
               reportOutputDirectory = directory;
      +  733  0
           }
       734   -
           public File getReportOutputDirectory() {
      -  735  0
               return reportOutputDirectory;
      +
       
      +  735   +
           /**
       736   -
           }
      +
            * Returns the report output directory.
       737   -
       
      +
            *
       738   -
           /**
      +
            * @return the report output directory
       739   -
            * Returns the output directory.
      +
            */
       740   -
            *
      +
           @Override
       741   -
            * @return the output directory
      -  742   -
            */
      +
           public File getReportOutputDirectory() {
      +  742  0
               return reportOutputDirectory;
       743   -
           public File getOutputDirectory() {
      -  744  0
               return outputDirectory;
      +
           }
      +  744   +
       
       745   -
           }
      +
           /**
       746   -
       
      +
            * Returns the output directory.
       747   -
           /**
      +
            *
       748   -
            * Returns whether this is an external report. This method always returns
      +
            * @return the output directory
       749   -
            * true.
      +
            */
       750   -
            *
      -  751   -
            * @return <code>true</code>
      +
           public File getOutputDirectory() {
      +  751  0
               return outputDirectory;
       752   -
            */
      +
           }
       753   -
           @Override
      +
       
       754   -
           public final boolean isExternalReport() {
      -  755  0
               return true;
      +
           /**
      +  755   +
            * Returns whether this is an external report. This method always returns
       756   -
           }
      +
            * true.
       757   -
       
      +
            *
       758   -
           /**
      +
            * @return <code>true</code>
       759   -
            * Returns the output name.
      +
            */
       760   -
            *
      +
           @Override
       761   -
            * @return the output name
      -  762   -
            */
      +
           public final boolean isExternalReport() {
      +  762  0
               return true;
       763   -
           @Override
      +
           }
       764   -
           public String getOutputName() {
      -  765  0
               if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) {
      -  766  0
                   return "dependency-check-report";
      -  767  0
               } else if ("XML".equalsIgnoreCase(this.format)) {
      -  768  0
                   return "dependency-check-report.xml#";
      -  769  0
               } else if ("VULN".equalsIgnoreCase(this.format)) {
      -  770  0
                   return "dependency-check-vulnerability";
      -  771   -
               } else {
      -  772  0
                   getLog().warn("Unknown report format used during site generation.");
      -  773  0
                   return "dependency-check-report";
      -  774   -
               }
      -  775   -
           }
      -  776  
       
      -  777   +  765  
           /**
      -  778   -
            * Returns the category name.
      -  779   +  766   +
            * Returns the output name.
      +  767  
            *
      -  780   -
            * @return the category name
      -  781   +  768   +
            * @return the output name
      +  769  
            */
      -  782   +  770  
           @Override
      +  771   +
           public String getOutputName() {
      +  772  0
               if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) {
      +  773  0
                   return "dependency-check-report";
      +  774  0
               } else if ("XML".equalsIgnoreCase(this.format)) {
      +  775  0
                   return "dependency-check-report.xml#";
      +  776  0
               } else if ("VULN".equalsIgnoreCase(this.format)) {
      +  777  0
                   return "dependency-check-vulnerability";
      +  778   +
               } else {
      +  779  0
                   getLog().warn("Unknown report format used during site generation.");
      +  780  0
                   return "dependency-check-report";
      +  781   +
               }
      +  782   +
           }
       783   -
           public String getCategoryName() {
      -  784  0
               return MavenReport.CATEGORY_PROJECT_REPORTS;
      +
       
      +  784   +
           /**
       785   -
           }
      +
            * Returns the category name.
       786   -
           //</editor-fold>
      -  787   -
       
      -  788   -
           /**
      -  789   -
            * Initializes a new <code>MavenEngine</code> that can be used for scanning.
      -  790  
            *
      -  791   -
            * @return a newly instantiated <code>MavenEngine</code>
      +  787   +
            * @return the category name
      +  788   +
            */
      +  789   +
           @Override
      +  790   +
           public String getCategoryName() {
      +  791  0
               return MavenReport.CATEGORY_PROJECT_REPORTS;
       792   -
            * @throws DatabaseException thrown if there is a database exception
      -  793   -
            */
      -  794   -
           protected MavenEngine initializeEngine() throws DatabaseException {
      -  795  0
               populateSettings();
      -  796  0
               return new MavenEngine(this.project, this.reactorProjects);
      -  797  
           }
      -  798   +  793   +
           //</editor-fold>
      +  794  
       
      -  799   +  795  
           /**
      +  796   +
            * Initializes a new <code>MavenEngine</code> that can be used for scanning.
      +  797   +
            *
      +  798   +
            * @return a newly instantiated <code>MavenEngine</code>
      +  799   +
            * @throws DatabaseException thrown if there is a database exception
       800   -
            * Takes the properties supplied and updates the dependency-check settings.
      -  801   -
            * Additionally, this sets the system properties required to change the
      -  802   -
            * proxy url, port, and connection timeout.
      -  803  
            */
      +  801   +
           protected MavenEngine initializeEngine() throws DatabaseException {
      +  802  0
               populateSettings();
      +  803  0
               return new MavenEngine(this.project, this.reactorProjects);
       804   -
           protected void populateSettings() {
      -  805  0
               Settings.initialize();
      -  806  0
               InputStream mojoProperties = null;
      +
           }
      +  805   +
       
      +  806   +
           /**
       807   -
               try {
      -  808  0
                   mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
      -  809  0
                   Settings.mergeProperties(mojoProperties);
      -  810  0
               } catch (IOException ex) {
      -  811  0
                   getLog().warn("Unable to load the dependency-check ant task.properties file.");
      -  812  0
                   if (getLog().isDebugEnabled()) {
      -  813  0
                       getLog().debug("", ex);
      +
            * Takes the properties supplied and updates the dependency-check settings.
      +  808   +
            * Additionally, this sets the system properties required to change the
      +  809   +
            * proxy url, port, and connection timeout.
      +  810   +
            */
      +  811   +
           protected void populateSettings() {
      +  812  0
               Settings.initialize();
      +  813  0
               InputStream mojoProperties = null;
       814   +
               try {
      +  815  0
                   mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
      +  816  0
                   Settings.mergeProperties(mojoProperties);
      +  817  0
               } catch (IOException ex) {
      +  818  0
                   getLog().warn("Unable to load the dependency-check ant task.properties file.");
      +  819  0
                   if (getLog().isDebugEnabled()) {
      +  820  0
                       getLog().debug("", ex);
      +  821  
                   }
      -  815   -
               } finally {
      -  816  0
                   if (mojoProperties != null) {
      -  817   -
                       try {
      -  818  0
                           mojoProperties.close();
      -  819  0
                       } catch (IOException ex) {
      -  820  0
                           if (getLog().isDebugEnabled()) {
      -  821  0
                               getLog().debug("", ex);
       822   -
                           }
      -  823  0
                       }
      +
               } finally {
      +  823  0
                   if (mojoProperties != null) {
       824   -
                   }
      -  825   -
               }
      -  826  0
               Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
      -  827   -
       
      -  828  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental);
      +
                       try {
      +  825  0
                           mojoProperties.close();
      +  826  0
                       } catch (IOException ex) {
      +  827  0
                           if (getLog().isDebugEnabled()) {
      +  828  0
                               getLog().debug("", ex);
       829   -
       
      -  830  0
               if (externalReport != null) {
      -  831  0
                   getLog().warn("The 'externalReport' option was set; this configuration option has been removed. "
      +
                           }
      +  830  0
                       }
      +  831   +
                   }
       832   -
                           + "Please update the dependency-check-maven plugin's configuration");
      -  833  
               }
      +  833  0
               Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
       834  
       
      -  835  0
               if (proxyUrl != null && !proxyUrl.isEmpty()) {
      -  836  0
                   getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead");
      -  837   -
               }
      -  838  0
               final Proxy proxy = getMavenProxy();
      -  839  0
               if (proxy != null) {
      -  840  0
                   Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost());
      -  841  0
                   Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort()));
      -  842  0
                   final String userName = proxy.getUsername();
      -  843  0
                   final String password = proxy.getPassword();
      -  844  0
                   Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName);
      -  845  0
                   Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password);
      -  846  0
                   Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts());
      -  847   -
               }
      -  848   +  835  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental);
      +  836  
       
      -  849  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
      -  850  0
               Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
      -  851   +  837  0
               if (externalReport != null) {
      +  838  0
                   getLog().warn("The 'externalReport' option was set; this configuration option has been removed. "
      +  839   +
                           + "Please update the dependency-check-maven plugin's configuration");
      +  840   +
               }
      +  841  
       
      -  852   +  842  0
               if (proxyUrl != null && !proxyUrl.isEmpty()) {
      +  843  0
                   getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead");
      +  844   +
               }
      +  845  0
               final Proxy proxy = getMavenProxy();
      +  846  0
               if (proxy != null) {
      +  847  0
                   Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost());
      +  848  0
                   Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort()));
      +  849  0
                   final String userName = proxy.getUsername();
      +  850  0
                   final String password = proxy.getPassword();
      +  851  0
                   Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName);
      +  852  0
                   Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password);
      +  853  0
                   Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts());
      +  854   +
               }
      +  855   +
       
      +  856  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
      +  857  0
               Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
      +  858  0
               Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile);
      +  859   +
       
      +  860  
               //File Type Analyzer Settings
      -  853  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
      -  854  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
      -  855  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
      -  856  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
      -  857  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
      -  858  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
      -  859  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
      -  860  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
      -  861  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
      -  862  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
      -  863   +  861  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
      +  862  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
      +  863  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
      +  864  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
      +  865  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
      +  866  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
      +  867  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
      +  868  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
      +  869  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
      +  870  0
               Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
      +  871  
       
      -  864  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled);
      -  865  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled);
      -  866  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled);
      -  867  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled);
      -  868  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled);
      -  869  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled);
      -  870  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled);
      -  871  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled);
      -  872   +  872  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled);
      +  873  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled);
      +  874  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled);
      +  875  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled);
      +  876  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled);
      +  877  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled);
      +  878  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled);
      +  879  0
               Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled);
      +  880  
       
      -  873   +  881  
               //Database configuration
      -  874  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
      -  875  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
      -  876  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
      -  877   -
       
      -  878  0
               if (databaseUser == null && databasePassword == null && serverId != null) {
      -  879  0
                   final Server server = settingsXml.getServer(serverId);
      -  880  0
                   if (server != null) {
      -  881  0
                       databaseUser = server.getUsername();
      -  882   -
                       try {
      -  883   -
                           //The following fix was copied from:
      -  884   -
                           //   https://github.com/bsorrentino/maven-confluence-plugin/blob/master/maven-confluence-reporting-plugin/src/main/java/org/bsc/maven/confluence/plugin/AbstractBaseConfluenceMojo.java
      +  882  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
      +  883  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
      +  884  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
       885   -
                           //
      -  886   -
                           // FIX to resolve
      -  887   -
                           // org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException:
      -  888   -
                           // java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory)
      -  889   -
                           //
      -  890  0
                           if (securityDispatcher instanceof DefaultSecDispatcher) {
      -  891  0
                               ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml");
      +
       
      +  886  0
               if (databaseUser == null && databasePassword == null && serverId != null) {
      +  887  0
                   final Server server = settingsXml.getServer(serverId);
      +  888  0
                   if (server != null) {
      +  889  0
                       databaseUser = server.getUsername();
      +  890   +
                       try {
      +  891   +
                           //The following fix was copied from:
       892   -
                           }
      +
                           //   https://github.com/bsorrentino/maven-confluence-plugin/blob/master/maven-confluence-reporting-plugin/src/main/java/org/bsc/maven/confluence/plugin/AbstractBaseConfluenceMojo.java
       893   -
       
      -  894  0
                           databasePassword = securityDispatcher.decrypt(server.getPassword());
      -  895  0
                       } catch (SecDispatcherException ex) {
      -  896  0
                           if (ex.getCause() instanceof FileNotFoundException
      -  897  0
                                   || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) {
      -  898   -
                               //maybe its not encrypted?
      -  899  0
                               final String tmp = server.getPassword();
      -  900  0
                               if (tmp.startsWith("{") && tmp.endsWith("}")) {
      -  901  0
                                   getLog().error(String.format(
      -  902   -
                                           "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s",
      -  903  0
                                           serverId, ex.getMessage()));
      -  904   -
                               } else {
      -  905  0
                                   databasePassword = tmp;
      -  906   -
                               }
      -  907  0
                           } else {
      -  908  0
                               getLog().error(String.format(
      -  909   -
                                       "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s",
      -  910  0
                                       serverId, ex.getMessage()));
      -  911   +
                           //
      +  894   +
                           // FIX to resolve
      +  895   +
                           // org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException:
      +  896   +
                           // java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory)
      +  897   +
                           //
      +  898  0
                           if (securityDispatcher instanceof DefaultSecDispatcher) {
      +  899  0
                               ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml");
      +  900  
                           }
      -  912  0
                       }
      -  913   -
                   } else {
      -  914  0
                       getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId));
      -  915   -
                   }
      -  916   -
               }
      +  901   +
       
      +  902  0
                           databasePassword = securityDispatcher.decrypt(server.getPassword());
      +  903  0
                       } catch (SecDispatcherException ex) {
      +  904  0
                           if (ex.getCause() instanceof FileNotFoundException
      +  905  0
                                   || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) {
      +  906   +
                               //maybe its not encrypted?
      +  907  0
                               final String tmp = server.getPassword();
      +  908  0
                               if (tmp.startsWith("{") && tmp.endsWith("}")) {
      +  909  0
                                   getLog().error(String.format(
      +  910   +
                                           "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s",
      +  911  0
                                           serverId, ex.getMessage()));
      +  912   +
                               } else {
      +  913  0
                                   databasePassword = tmp;
      +  914   +
                               }
      +  915  0
                           } else {
      +  916  0
                               getLog().error(String.format(
       917   -
       
      -  918  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
      -  919  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
      -  920  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
      +
                                       "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s",
      +  918  0
                                       serverId, ex.getMessage()));
      +  919   +
                           }
      +  920  0
                       }
       921   +
                   } else {
      +  922  0
                       getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId));
      +  923   +
                   }
      +  924   +
               }
      +  925  
       
      -  922  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
      -  923  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
      -  924  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
      -  925  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
      -  926  0
               Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
      -  927   -
       
      -  928  0
           }
      +  926  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
      +  927  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
      +  928  0
               Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
       929  
       
      -  930   -
           /**
      -  931   -
            * Returns the maven proxy.
      -  932   -
            *
      -  933   -
            * @return the maven proxy
      -  934   -
            */
      +  930  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
      +  931  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
      +  932  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
      +  933  0
               Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
      +  934  0
               Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
       935   -
           private Proxy getMavenProxy() {
      -  936  0
               if (mavenSettings != null) {
      -  937  0
                   final List<Proxy> proxies = mavenSettings.getProxies();
      -  938  0
                   if (proxies != null && !proxies.isEmpty()) {
      -  939  0
                       if (mavenSettingsProxyId != null) {
      -  940  0
                           for (Proxy proxy : proxies) {
      -  941  0
                               if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) {
      -  942  0
                                   return proxy;
      +
       
      +  936  0
           }
      +  937   +
       
      +  938   +
           /**
      +  939   +
            * Returns the maven proxy.
      +  940   +
            *
      +  941   +
            * @return the maven proxy
      +  942   +
            */
       943   -
                               }
      -  944  0
                           }
      -  945  0
                       } else if (proxies.size() == 1) {
      -  946  0
                           return proxies.get(0);
      -  947   -
                       } else {
      -  948  0
                           getLog().warn("Multiple proxy definitions exist in the Maven settings. In the dependency-check "
      -  949   -
                                   + "configuration set the mavenSettingsProxyId so that the correct proxy will be used.");
      -  950  0
                           throw new IllegalStateException("Ambiguous proxy definition");
      +
           private Proxy getMavenProxy() {
      +  944  0
               if (mavenSettings != null) {
      +  945  0
                   final List<Proxy> proxies = mavenSettings.getProxies();
      +  946  0
                   if (proxies != null && !proxies.isEmpty()) {
      +  947  0
                       if (mavenSettingsProxyId != null) {
      +  948  0
                           for (Proxy proxy : proxies) {
      +  949  0
                               if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) {
      +  950  0
                                   return proxy;
       951   -
                       }
      -  952   -
                   }
      -  953   -
               }
      -  954  0
               return null;
      +
                               }
      +  952  0
                           }
      +  953  0
                       } else if (proxies.size() == 1) {
      +  954  0
                           return proxies.get(0);
       955   -
           }
      -  956   -
       
      +
                       } else {
      +  956  0
                           getLog().warn("Multiple proxy definitions exist in the Maven settings. In the dependency-check "
       957   -
           /**
      -  958   -
            * Tests is the artifact should be included in the scan (i.e. is the
      +
                                   + "configuration set the mavenSettingsProxyId so that the correct proxy will be used.");
      +  958  0
                           throw new IllegalStateException("Ambiguous proxy definition");
       959   -
            * dependency in a scope that is being scanned).
      +
                       }
       960   -
            *
      +
                   }
       961   -
            * @param scope the scope of the artifact to test
      -  962   -
            * @return <code>true</code> if the artifact is in an excluded scope;
      +
               }
      +  962  0
               return null;
       963   -
            * otherwise <code>false</code>
      +
           }
       964   -
            */
      +
       
       965   -
           protected boolean excludeFromScan(String scope) {
      -  966  0
               if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) {
      -  967  0
                   return true;
      +
           /**
      +  966   +
            * Tests is the artifact should be included in the scan (i.e. is the
      +  967   +
            * dependency in a scope that is being scanned).
       968   -
               }
      -  969  0
               if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) {
      -  970  0
                   return true;
      +
            *
      +  969   +
            * @param scope the scope of the artifact to test
      +  970   +
            * @return <code>true</code> if the artifact is in an excluded scope;
       971   -
               }
      -  972  0
               if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) {
      -  973  0
                   return true;
      -  974   -
               }
      -  975  0
               return false;
      +
            * otherwise <code>false</code>
      +  972   +
            */
      +  973   +
           protected boolean excludeFromScan(String scope) {
      +  974  0
               if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) {
      +  975  0
                   return true;
       976   -
           }
      -  977   -
       
      -  978   -
           /**
      +
               }
      +  977  0
               if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) {
      +  978  0
                   return true;
       979   -
            * Returns a reference to the current project. This method is used instead
      -  980   -
            * of auto-binding the project via component annotation in concrete
      -  981   -
            * implementations of this. If the child has a
      +
               }
      +  980  0
               if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) {
      +  981  0
                   return true;
       982   -
            * <code>@Component MavenProject project;</code> defined then the abstract
      -  983   -
            * class (i.e. this class) will not have access to the current project (just
      +
               }
      +  983  0
               return false;
       984   -
            * the way Maven works with the binding).
      +
           }
       985   -
            *
      +
       
       986   -
            * @return returns a reference to the current project
      +
           /**
       987   -
            */
      +
            * Returns a reference to the current project. This method is used instead
       988   -
           protected MavenProject getProject() {
      -  989  0
               return project;
      +
            * of auto-binding the project via component annotation in concrete
      +  989   +
            * implementations of this. If the child has a
       990   -
           }
      +
            * <code>@Component MavenProject project;</code> defined then the abstract
       991   -
       
      +
            * class (i.e. this class) will not have access to the current project (just
       992   -
           /**
      +
            * the way Maven works with the binding).
       993   -
            * Returns the list of Maven Projects in this build.
      +
            *
       994   -
            *
      +
            * @return returns a reference to the current project
       995   -
            * @return the list of Maven Projects in this build
      +
            */
       996   -
            */
      -  997   -
           protected List<MavenProject> getReactorProjects() {
      -  998  0
               return reactorProjects;
      +
           protected MavenProject getProject() {
      +  997  0
               return project;
      +  998   +
           }
       999   -
           }
      +
       
       1000   -
       
      +
           /**
       1001   -
           /**
      +
            * Returns the list of Maven Projects in this build.
       1002   -
            * Returns the report format.
      +
            *
       1003   -
            *
      +
            * @return the list of Maven Projects in this build
       1004   -
            * @return the report format
      +
            */
       1005   -
            */
      -  1006   -
           protected String getFormat() {
      -  1007  0
               return format;
      +
           protected List<MavenProject> getReactorProjects() {
      +  1006  0
               return reactorProjects;
      +  1007   +
           }
       1008   -
           }
      +
       
       1009   -
       
      +
           /**
       1010   -
           /**
      +
            * Returns the report format.
       1011   -
            * Generates the reports for a given dependency-check engine.
      +
            *
       1012   -
            *
      +
            * @return the report format
       1013   -
            * @param engine a dependency-check engine
      +
            */
       1014   -
            * @param p the Maven project
      -  1015   -
            * @param outputDir the directory path to write the report(s)
      +
           protected String getFormat() {
      +  1015  0
               return format;
       1016   -
            * @throws ReportException thrown if there is an error writing the report
      +
           }
       1017   -
            */
      +
       
       1018   -
           protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException {
      -  1019  0
               DatabaseProperties prop = null;
      -  1020  0
               CveDB cve = null;
      +
           /**
      +  1019   +
            * Generates the reports for a given dependency-check engine.
      +  1020   +
            *
       1021   -
               try {
      -  1022  0
                   cve = new CveDB();
      -  1023  0
                   cve.open();
      -  1024  0
                   prop = cve.getDatabaseProperties();
      -  1025  0
               } catch (DatabaseException ex) {
      -  1026  0
                   if (getLog().isDebugEnabled()) {
      -  1027  0
                       getLog().debug("Unable to retrieve DB Properties", ex);
      -  1028   -
                   }
      +
            * @param engine a dependency-check engine
      +  1022   +
            * @param p the Maven project
      +  1023   +
            * @param outputDir the directory path to write the report(s)
      +  1024   +
            * @throws ReportException thrown if there is an error writing the report
      +  1025   +
            */
      +  1026   +
           protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException {
      +  1027  0
               DatabaseProperties prop = null;
      +  1028  0
               CveDB cve = null;
       1029   -
               } finally {
      -  1030  0
                   if (cve != null) {
      -  1031  0
                       cve.close();
      -  1032   -
                   }
      -  1033   -
               }
      -  1034  0
               final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
      -  1035  
               try {
      -  1036  0
                   r.generateReports(outputDir.getAbsolutePath(), format);
      -  1037  0
               } catch (ReportException ex) {
      -  1038  0
                   final String msg = String.format("Error generating the report for %s", p.getName());
      -  1039  0
                   throw new ReportException(msg, ex);
      -  1040  0
               }
      +  1030  0
                   cve = new CveDB();
      +  1031  0
                   cve.open();
      +  1032  0
                   prop = cve.getDatabaseProperties();
      +  1033  0
               } catch (DatabaseException ex) {
      +  1034  0
                   if (getLog().isDebugEnabled()) {
      +  1035  0
                       getLog().debug("Unable to retrieve DB Properties", ex);
      +  1036   +
                   }
      +  1037   +
               } finally {
      +  1038  0
                   if (cve != null) {
      +  1039  0
                       cve.close();
      +  1040   +
                   }
       1041   -
       
      -  1042  0
           }
      +
               }
      +  1042  0
               final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
       1043   -
       
      -  1044   -
           //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
      -  1045   -
           /**
      -  1046   -
            * Checks to see if a vulnerability has been identified with a CVSS score
      -  1047   -
            * that is above the threshold set in the configuration.
      -  1048   -
            *
      -  1049   -
            * @param dependencies the list of dependency objects
      -  1050   -
            * @throws MojoFailureException thrown if a CVSS score is found that is
      -  1051   -
            * higher then the threshold set
      -  1052   -
            */
      -  1053   -
           protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException {
      -  1054  0
               if (failBuildOnCVSS <= 10) {
      -  1055  0
                   final StringBuilder ids = new StringBuilder();
      -  1056  0
                   for (Dependency d : dependencies) {
      -  1057  0
                       boolean addName = true;
      -  1058  0
                       for (Vulnerability v : d.getVulnerabilities()) {
      -  1059  0
                           if (v.getCvssScore() >= failBuildOnCVSS) {
      -  1060  0
                               if (addName) {
      -  1061  0
                                   addName = false;
      -  1062  0
                                   ids.append(NEW_LINE).append(d.getFileName()).append(": ");
      -  1063  0
                                   ids.append(v.getName());
      -  1064   -
                               } else {
      -  1065  0
                                   ids.append(", ").append(v.getName());
      -  1066   -
                               }
      -  1067   -
                           }
      -  1068  0
                       }
      -  1069  0
                   }
      -  1070  0
                   if (ids.length() > 0) {
      -  1071  0
                       final String msg = String.format("%n%nDependency-Check Failure:%n"
      -  1072   -
                               + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
      -  1073  0
                               + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
      -  1074  0
                       throw new MojoFailureException(msg);
      -  1075   -
                   }
      -  1076   -
               }
      -  1077  0
           }
      -  1078   -
       
      -  1079   -
           /**
      -  1080   -
            * Generates a warning message listing a summary of dependencies and their
      -  1081   -
            * associated CPE and CVE entries.
      -  1082   -
            *
      -  1083   -
            * @param mp the Maven project for which the summary is shown
      -  1084   -
            * @param dependencies a list of dependency objects
      -  1085   -
            */
      -  1086   -
           protected void showSummary(MavenProject mp, List<Dependency> dependencies) {
      -  1087  0
               if (showSummary) {
      -  1088  0
                   final StringBuilder summary = new StringBuilder();
      -  1089  0
                   for (Dependency d : dependencies) {
      -  1090  0
                       boolean firstEntry = true;
      -  1091  0
                       final StringBuilder ids = new StringBuilder();
      -  1092  0
                       for (Vulnerability v : d.getVulnerabilities()) {
      -  1093  0
                           if (firstEntry) {
      -  1094  0
                               firstEntry = false;
      -  1095   -
                           } else {
      -  1096  0
                               ids.append(", ");
      -  1097   -
                           }
      -  1098  0
                           ids.append(v.getName());
      -  1099  0
                       }
      -  1100  0
                       if (ids.length() > 0) {
      -  1101  0
                           summary.append(d.getFileName()).append(" (");
      -  1102  0
                           firstEntry = true;
      -  1103  0
                           for (Identifier id : d.getIdentifiers()) {
      -  1104  0
                               if (firstEntry) {
      -  1105  0
                                   firstEntry = false;
      -  1106   -
                               } else {
      -  1107  0
                                   summary.append(", ");
      -  1108   -
                               }
      -  1109  0
                               summary.append(id.getValue());
      -  1110  0
                           }
      -  1111  0
                           summary.append(") : ").append(ids).append(NEW_LINE);
      -  1112   -
                       }
      -  1113  0
                   }
      -  1114  0
                   if (summary.length() > 0) {
      -  1115  0
                       final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s"
      -  1116  0
                               + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString());
      -  1117  0
                       getLog().warn(msg);
      -  1118   -
                   }
      -  1119   -
               }
      -  1120  0
           }
      -  1121   -
       
      -  1122   -
           //</editor-fold>
      -  1123   -
           //<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file">
      -  1124   -
           /**
      -  1125   -
            * Returns the key used to store the path to the data file that is saved by
      -  1126   -
            * <code>writeDataFile()</code>. This key is used in the
      -  1127   -
            * <code>MavenProject.(set|get)ContextValue</code>.
      -  1128   -
            *
      -  1129   -
            * @return the key used to store the path to the data file
      -  1130   -
            */
      -  1131   -
           protected String getDataFileContextKey() {
      -  1132  0
               return "dependency-check-path-" + dataFileName;
      -  1133   -
           }
      -  1134   -
       
      -  1135   -
           /**
      -  1136   -
            * Returns the key used to store the path to the output directory. When
      -  1137   -
            * generating the report in the <code>executeAggregateReport()</code> the
      -  1138   -
            * output directory should be obtained by using this key.
      -  1139   -
            *
      -  1140   -
            * @return the key used to store the path to the output directory
      -  1141   -
            */
      -  1142   -
           protected String getOutputDirectoryContextKey() {
      -  1143  0
               return "dependency-output-dir-" + dataFileName;
      -  1144   -
           }
      -  1145   -
       
      -  1146   -
           /**
      -  1147   -
            * Writes the scan data to disk. This is used to serialize the scan data
      -  1148   -
            * between the "check" and "aggregate" phase.
      -  1149   -
            *
      -  1150   -
            * @param mp the mMven project for which the data file was created
      -  1151   -
            * @param writeTo the directory to write the data file
      -  1152   -
            * @param dependencies the list of dependencies to serialize
      -  1153   -
            */
      -  1154   -
           protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) {
      -  1155   -
               File file;
      -  1156   -
               //check to see if this was already written out
      -  1157  0
               if (mp.getContextValue(this.getDataFileContextKey()) == null) {
      -  1158  0
                   if (writeTo == null) {
      -  1159  0
                       file = new File(mp.getBuild().getDirectory());
      -  1160  0
                       file = new File(file, dataFileName);
      -  1161   -
                   } else {
      -  1162  0
                       file = new File(writeTo, dataFileName);
      -  1163   -
                   }
      -  1164  0
                   final File parent = file.getParentFile();
      -  1165  0
                   if (!parent.isDirectory() && !parent.mkdirs()) {
      -  1166  0
                       getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.",
      -  1167  0
                               parent.getAbsolutePath()));
      -  1168   -
                   }
      -  1169   -
       
      -  1170  0
                   ObjectOutputStream out = null;
      -  1171   -
                   try {
      -  1172  0
                       if (dependencies != null) {
      -  1173  0
                           out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
      -  1174  0
                           out.writeObject(dependencies);
      -  1175   -
                       }
      -  1176  0
                       if (getLog().isDebugEnabled()) {
      -  1177  0
                           getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s",
      -  1178  0
                                   file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey()));
      -  1179   -
                       }
      -  1180  0
                       mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath());
      -  1181  0
                   } catch (IOException ex) {
      -  1182  0
                       getLog().warn("Unable to create data file used for report aggregation; "
      -  1183   -
                               + "if report aggregation is being used the results may be incomplete.");
      -  1184  0
                       if (getLog().isDebugEnabled()) {
      -  1185  0
                           getLog().debug(ex.getMessage(), ex);
      -  1186   -
                       }
      -  1187   -
                   } finally {
      -  1188  0
                       if (out != null) {
      -  1189   -
                           try {
      -  1190  0
                               out.close();
      -  1191  0
                           } catch (IOException ex) {
      -  1192  0
                               if (getLog().isDebugEnabled()) {
      -  1193  0
                                   getLog().debug("ignore", ex);
      -  1194   -
                               }
      -  1195  0
                           }
      -  1196   -
                       }
      -  1197   -
                   }
      -  1198   -
               }
      -  1199  0
           }
      -  1200   -
       
      -  1201   -
           /**
      -  1202   -
            * Reads the serialized scan data from disk. This is used to serialize the
      -  1203   -
            * scan data between the "check" and "aggregate" phase.
      -  1204   -
            *
      -  1205   -
            * @param project the Maven project to read the data file from
      -  1206   -
            * @return a <code>MavenEngine</code> object populated with dependencies if
      -  1207   -
            * the serialized data file exists; otherwise <code>null</code> is returned
      -  1208   -
            */
      -  1209   -
           protected List<Dependency> readDataFile(MavenProject project) {
      -  1210  0
               final Object oPath = project.getContextValue(this.getDataFileContextKey());
      -  1211  0
               if (oPath == null) {
      -  1212  0
                   return null;
      -  1213   -
               }
      -  1214  0
               List<Dependency> ret = null;
      -  1215  0
               final String path = (String) oPath;
      -  1216   -
               //ObjectInputStream ois = null;
      -  1217  0
               ExpectedOjectInputStream ois = null;
      -  1218  
               try {
      -  1219   -
                   //ois = new ObjectInputStream(new FileInputStream(path));
      -  1220  0
                   ois = new ExpectedOjectInputStream(new FileInputStream(path),
      -  1221   -
                           "java.util.ArrayList",
      -  1222   -
                           "java.util.HashSet",
      -  1223   -
                           "java.util.TreeSet",
      -  1224   -
                           "java.lang.AbstractSet",
      -  1225   -
                           "java.lang.AbstractCollection",
      -  1226   -
                           "java.lang.Enum",
      -  1227   -
                           "org.owasp.dependencycheck.dependency.Confidence",
      -  1228   -
                           "org.owasp.dependencycheck.dependency.Dependency",
      -  1229   -
                           "org.owasp.dependencycheck.dependency.Evidence",
      -  1230   -
                           "org.owasp.dependencycheck.dependency.EvidenceCollection",
      -  1231   -
                           "org.owasp.dependencycheck.dependency.Identifier",
      -  1232   -
                           "org.owasp.dependencycheck.dependency.Reference",
      -  1233   -
                           "org.owasp.dependencycheck.dependency.Vulnerability",
      -  1234   -
                           "org.owasp.dependencycheck.dependency.VulnerabilityComparator",
      -  1235   -
                           "org.owasp.dependencycheck.dependency.VulnerableSoftware",
      -  1236   -
                           "org.owasp.dependencycheck.data.cpe.IndexEntry");
      -  1237   -
                   @SuppressWarnings("unchecked")
      -  1238  0
                   final List<Dependency> depList = (List<Dependency>) ois.readObject();
      -  1239  0
                   ret = depList;
      -  1240  0
               } catch (FileNotFoundException ex) {
      -  1241   -
                   //TODO fix logging
      -  1242  0
                   getLog().error("", ex);
      -  1243  0
               } catch (IOException ex) {
      -  1244  0
                   getLog().error("", ex);
      -  1245  0
               } catch (ClassNotFoundException ex) {
      -  1246  0
                   getLog().error("", ex);
      -  1247   -
               } finally {
      -  1248  0
                   if (ois != null) {
      -  1249   -
                       try {
      -  1250  0
                           ois.close();
      -  1251  0
                       } catch (IOException ex) {
      -  1252  0
                           getLog().error("", ex);
      -  1253  0
                       }
      -  1254   -
                   }
      -  1255   -
               }
      -  1256  0
               return ret;
      -  1257   -
           }
      -  1258   -
           //</editor-fold>
      -  1259   +  1044  0
                   r.generateReports(outputDir.getAbsolutePath(), format);
      +  1045  0
               } catch (ReportException ex) {
      +  1046  0
                   final String msg = String.format("Error generating the report for %s", p.getName());
      +  1047  0
                   throw new ReportException(msg, ex);
      +  1048  0
               }
      +  1049  
       
      -  1260   +  1050  0
           }
      +  1051   +
       
      +  1052   +
           //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
      +  1053   +
           /**
      +  1054   +
            * Checks to see if a vulnerability has been identified with a CVSS score
      +  1055   +
            * that is above the threshold set in the configuration.
      +  1056   +
            *
      +  1057   +
            * @param dependencies the list of dependency objects
      +  1058   +
            * @throws MojoFailureException thrown if a CVSS score is found that is
      +  1059   +
            * higher then the threshold set
      +  1060   +
            */
      +  1061   +
           protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException {
      +  1062  0
               if (failBuildOnCVSS <= 10) {
      +  1063  0
                   final StringBuilder ids = new StringBuilder();
      +  1064  0
                   for (Dependency d : dependencies) {
      +  1065  0
                       boolean addName = true;
      +  1066  0
                       for (Vulnerability v : d.getVulnerabilities()) {
      +  1067  0
                           if (v.getCvssScore() >= failBuildOnCVSS) {
      +  1068  0
                               if (addName) {
      +  1069  0
                                   addName = false;
      +  1070  0
                                   ids.append(NEW_LINE).append(d.getFileName()).append(": ");
      +  1071  0
                                   ids.append(v.getName());
      +  1072   +
                               } else {
      +  1073  0
                                   ids.append(", ").append(v.getName());
      +  1074   +
                               }
      +  1075   +
                           }
      +  1076  0
                       }
      +  1077  0
                   }
      +  1078  0
                   if (ids.length() > 0) {
      +  1079  0
                       final String msg = String.format("%n%nDependency-Check Failure:%n"
      +  1080   +
                               + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
      +  1081  0
                               + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
      +  1082  0
                       throw new MojoFailureException(msg);
      +  1083   +
                   }
      +  1084   +
               }
      +  1085  0
           }
      +  1086   +
       
      +  1087   +
           /**
      +  1088   +
            * Generates a warning message listing a summary of dependencies and their
      +  1089   +
            * associated CPE and CVE entries.
      +  1090   +
            *
      +  1091   +
            * @param mp the Maven project for which the summary is shown
      +  1092   +
            * @param dependencies a list of dependency objects
      +  1093   +
            */
      +  1094   +
           protected void showSummary(MavenProject mp, List<Dependency> dependencies) {
      +  1095  0
               if (showSummary) {
      +  1096  0
                   final StringBuilder summary = new StringBuilder();
      +  1097  0
                   for (Dependency d : dependencies) {
      +  1098  0
                       boolean firstEntry = true;
      +  1099  0
                       final StringBuilder ids = new StringBuilder();
      +  1100  0
                       for (Vulnerability v : d.getVulnerabilities()) {
      +  1101  0
                           if (firstEntry) {
      +  1102  0
                               firstEntry = false;
      +  1103   +
                           } else {
      +  1104  0
                               ids.append(", ");
      +  1105   +
                           }
      +  1106  0
                           ids.append(v.getName());
      +  1107  0
                       }
      +  1108  0
                       if (ids.length() > 0) {
      +  1109  0
                           summary.append(d.getFileName()).append(" (");
      +  1110  0
                           firstEntry = true;
      +  1111  0
                           for (Identifier id : d.getIdentifiers()) {
      +  1112  0
                               if (firstEntry) {
      +  1113  0
                                   firstEntry = false;
      +  1114   +
                               } else {
      +  1115  0
                                   summary.append(", ");
      +  1116   +
                               }
      +  1117  0
                               summary.append(id.getValue());
      +  1118  0
                           }
      +  1119  0
                           summary.append(") : ").append(ids).append(NEW_LINE);
      +  1120   +
                       }
      +  1121  0
                   }
      +  1122  0
                   if (summary.length() > 0) {
      +  1123  0
                       final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s"
      +  1124  0
                               + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString());
      +  1125  0
                       getLog().warn(msg);
      +  1126   +
                   }
      +  1127   +
               }
      +  1128  0
           }
      +  1129   +
       
      +  1130   +
           //</editor-fold>
      +  1131   +
           //<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file">
      +  1132   +
           /**
      +  1133   +
            * Returns the key used to store the path to the data file that is saved by
      +  1134   +
            * <code>writeDataFile()</code>. This key is used in the
      +  1135   +
            * <code>MavenProject.(set|get)ContextValue</code>.
      +  1136   +
            *
      +  1137   +
            * @return the key used to store the path to the data file
      +  1138   +
            */
      +  1139   +
           protected String getDataFileContextKey() {
      +  1140  0
               return "dependency-check-path-" + dataFileName;
      +  1141   +
           }
      +  1142   +
       
      +  1143   +
           /**
      +  1144   +
            * Returns the key used to store the path to the output directory. When
      +  1145   +
            * generating the report in the <code>executeAggregateReport()</code> the
      +  1146   +
            * output directory should be obtained by using this key.
      +  1147   +
            *
      +  1148   +
            * @return the key used to store the path to the output directory
      +  1149   +
            */
      +  1150   +
           protected String getOutputDirectoryContextKey() {
      +  1151  0
               return "dependency-output-dir-" + dataFileName;
      +  1152   +
           }
      +  1153   +
       
      +  1154   +
           /**
      +  1155   +
            * Writes the scan data to disk. This is used to serialize the scan data
      +  1156   +
            * between the "check" and "aggregate" phase.
      +  1157   +
            *
      +  1158   +
            * @param mp the mMven project for which the data file was created
      +  1159   +
            * @param writeTo the directory to write the data file
      +  1160   +
            * @param dependencies the list of dependencies to serialize
      +  1161   +
            */
      +  1162   +
           protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) {
      +  1163   +
               File file;
      +  1164   +
               //check to see if this was already written out
      +  1165  0
               if (mp.getContextValue(this.getDataFileContextKey()) == null) {
      +  1166  0
                   if (writeTo == null) {
      +  1167  0
                       file = new File(mp.getBuild().getDirectory());
      +  1168  0
                       file = new File(file, dataFileName);
      +  1169   +
                   } else {
      +  1170  0
                       file = new File(writeTo, dataFileName);
      +  1171   +
                   }
      +  1172  0
                   final File parent = file.getParentFile();
      +  1173  0
                   if (!parent.isDirectory() && !parent.mkdirs()) {
      +  1174  0
                       getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.",
      +  1175  0
                               parent.getAbsolutePath()));
      +  1176   +
                   }
      +  1177   +
       
      +  1178  0
                   ObjectOutputStream out = null;
      +  1179   +
                   try {
      +  1180  0
                       if (dependencies != null) {
      +  1181  0
                           out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
      +  1182  0
                           out.writeObject(dependencies);
      +  1183   +
                       }
      +  1184  0
                       if (getLog().isDebugEnabled()) {
      +  1185  0
                           getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s",
      +  1186  0
                                   file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey()));
      +  1187   +
                       }
      +  1188  0
                       mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath());
      +  1189  0
                   } catch (IOException ex) {
      +  1190  0
                       getLog().warn("Unable to create data file used for report aggregation; "
      +  1191   +
                               + "if report aggregation is being used the results may be incomplete.");
      +  1192  0
                       if (getLog().isDebugEnabled()) {
      +  1193  0
                           getLog().debug(ex.getMessage(), ex);
      +  1194   +
                       }
      +  1195   +
                   } finally {
      +  1196  0
                       if (out != null) {
      +  1197   +
                           try {
      +  1198  0
                               out.close();
      +  1199  0
                           } catch (IOException ex) {
      +  1200  0
                               if (getLog().isDebugEnabled()) {
      +  1201  0
                                   getLog().debug("ignore", ex);
      +  1202   +
                               }
      +  1203  0
                           }
      +  1204   +
                       }
      +  1205   +
                   }
      +  1206   +
               }
      +  1207  0
           }
      +  1208   +
       
      +  1209   +
           /**
      +  1210   +
            * Reads the serialized scan data from disk. This is used to serialize the
      +  1211   +
            * scan data between the "check" and "aggregate" phase.
      +  1212   +
            *
      +  1213   +
            * @param project the Maven project to read the data file from
      +  1214   +
            * @return a <code>MavenEngine</code> object populated with dependencies if
      +  1215   +
            * the serialized data file exists; otherwise <code>null</code> is returned
      +  1216   +
            */
      +  1217   +
           protected List<Dependency> readDataFile(MavenProject project) {
      +  1218  0
               final Object oPath = project.getContextValue(this.getDataFileContextKey());
      +  1219  0
               if (oPath == null) {
      +  1220  0
                   return null;
      +  1221   +
               }
      +  1222  0
               List<Dependency> ret = null;
      +  1223  0
               final String path = (String) oPath;
      +  1224   +
               //ObjectInputStream ois = null;
      +  1225  0
               ExpectedOjectInputStream ois = null;
      +  1226   +
               try {
      +  1227   +
                   //ois = new ObjectInputStream(new FileInputStream(path));
      +  1228  0
                   ois = new ExpectedOjectInputStream(new FileInputStream(path),
      +  1229   +
                           "java.util.ArrayList",
      +  1230   +
                           "java.util.HashSet",
      +  1231   +
                           "java.util.TreeSet",
      +  1232   +
                           "java.lang.AbstractSet",
      +  1233   +
                           "java.lang.AbstractCollection",
      +  1234   +
                           "java.lang.Enum",
      +  1235   +
                           "org.owasp.dependencycheck.dependency.Confidence",
      +  1236   +
                           "org.owasp.dependencycheck.dependency.Dependency",
      +  1237   +
                           "org.owasp.dependencycheck.dependency.Evidence",
      +  1238   +
                           "org.owasp.dependencycheck.dependency.EvidenceCollection",
      +  1239   +
                           "org.owasp.dependencycheck.dependency.Identifier",
      +  1240   +
                           "org.owasp.dependencycheck.dependency.Reference",
      +  1241   +
                           "org.owasp.dependencycheck.dependency.Vulnerability",
      +  1242   +
                           "org.owasp.dependencycheck.dependency.VulnerabilityComparator",
      +  1243   +
                           "org.owasp.dependencycheck.dependency.VulnerableSoftware",
      +  1244   +
                           "org.owasp.dependencycheck.data.cpe.IndexEntry");
      +  1245   +
                   @SuppressWarnings("unchecked")
      +  1246  0
                   final List<Dependency> depList = (List<Dependency>) ois.readObject();
      +  1247  0
                   ret = depList;
      +  1248  0
               } catch (FileNotFoundException ex) {
      +  1249   +
                   //TODO fix logging
      +  1250  0
                   getLog().error("", ex);
      +  1251  0
               } catch (IOException ex) {
      +  1252  0
                   getLog().error("", ex);
      +  1253  0
               } catch (ClassNotFoundException ex) {
      +  1254  0
                   getLog().error("", ex);
      +  1255   +
               } finally {
      +  1256  0
                   if (ois != null) {
      +  1257   +
                       try {
      +  1258  0
                           ois.close();
      +  1259  0
                       } catch (IOException ex) {
      +  1260  0
                           getLog().error("", ex);
      +  1261  0
                       }
      +  1262   +
                   }
      +  1263   +
               }
      +  1264  0
               return ret;
      +  1265   +
           }
      +  1266   +
           //</editor-fold>
      +  1267   +
       
      +  1268  
       }
      - + diff --git a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.CheckMojo.html b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.CheckMojo.html index 93804a910..f282e35ac 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.CheckMojo.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.CheckMojo.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      CheckMojo
      0%
      0/47
      0%
      0/28
      6
      CheckMojo
      0%
      0/46
      0%
      0/28
      6
       
      @@ -170,7 +170,7 @@  82  0
                       getLog().debug("Database connection error", ex);
       83  
                   }
      -  84  0
                   final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
      +  84  0
                   final String msg = "An exception occurred connecting to the local database. Please see the log file for more details.";
       85  0
                   if (this.isFailOnError()) {
       86  0
                       throw new MojoExecutionException(msg, ex);
       87   @@ -188,7 +188,7 @@  96  0
                           engine.analyzeDependencies();
       97  0
                       } catch (ExceptionCollection ex) {
       98  0
                           if (this.isFailOnError() && ex.isFatal()) {
      -  99  0
                               throw new MojoExecutionException("One or more exceptions occured during analysis", ex);
      +  99  0
                               throw new MojoExecutionException("One or more exceptions occurred during analysis", ex);
       100  
                           }
       101  0
                           exCol = ex;
      @@ -209,11 +209,12 @@  113  
                               }
       114  0
                           }
      -  115  0
                           writeDataFile(getProject(), null, engine.getDependencies());
      +  115   +
                           //writeDataFile(getProject(), null, engine.getDependencies());
       116  0
                           showSummary(getProject(), engine.getDependencies());
       117  0
                           checkForFailure(engine.getDependencies());
       118  0
                           if (exCol != null && this.isFailOnError()) {
      -  119  0
                               throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
      +  119  0
                               throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
       120  
                           }
       121   @@ -290,6 +291,6 @@
       }
      - + diff --git a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.HelpMojo.html b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.HelpMojo.html index 50fa47a62..9264bb52d 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.HelpMojo.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.HelpMojo.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      HelpMojo
      0%
      0/157
      0%
      0/108
      5.467
      HelpMojo
      0%
      0/159
      0%
      0/110
      5.533
       
      @@ -474,302 +474,308 @@  275  0
               String parameterDescription = getValue( parameter, "description" );
       276  
       
      -  277  0
               Element fieldConfigurationElement = (Element) findSingleChild( configurationElement, parameterName );
      -  278   -
       
      -  279  0
               String parameterDefaultValue = "";
      -  280  0
               if ( fieldConfigurationElement != null && fieldConfigurationElement.hasAttribute( "default-value" ) )
      +  277  0
               Element fieldConfigurationElement = null;
      +  278  0
               if ( configurationElement != null )
      +  279   +
               {
      +  280  0
                 fieldConfigurationElement =  (Element) findSingleChild( configurationElement, parameterName );
       281   -
               {
      -  282  0
                   parameterDefaultValue = " (Default: " + fieldConfigurationElement.getAttribute( "default-value" ) + ")";
      -  283  
               }
      -  284  0
               append( sb, parameterName + parameterDefaultValue, 2 );
      -  285  0
               Node deprecated = findSingleChild( parameter, "deprecated" );
      -  286  0
               if ( ( deprecated != null ) && isNotEmpty( deprecated.getTextContent() ) )
      +  282   +
       
      +  283  0
               String parameterDefaultValue = "";
      +  284  0
               if ( fieldConfigurationElement != null && fieldConfigurationElement.hasAttribute( "default-value" ) )
      +  285   +
               {
      +  286  0
                   parameterDefaultValue = " (Default: " + fieldConfigurationElement.getAttribute( "default-value" ) + ")";
       287   -
               {
      -  288  0
                   append( sb, "Deprecated. " + deprecated.getTextContent(), 3 );
      -  289  0
                   append( sb, "", 0 );
      -  290  
               }
      -  291  0
               append( sb, parameterDescription, 3 );
      -  292  0
               if ( "true".equals( getValue( parameter, "required" ) ) )
      -  293   +  288  0
               append( sb, parameterName + parameterDefaultValue, 2 );
      +  289  0
               Node deprecated = findSingleChild( parameter, "deprecated" );
      +  290  0
               if ( ( deprecated != null ) && isNotEmpty( deprecated.getTextContent() ) )
      +  291  
               {
      -  294  0
                   append( sb, "Required: Yes", 3 );
      -  295   +  292  0
                   append( sb, "Deprecated. " + deprecated.getTextContent(), 3 );
      +  293  0
                   append( sb, "", 0 );
      +  294  
               }
      -  296  0
               if ( ( fieldConfigurationElement != null ) && isNotEmpty( fieldConfigurationElement.getTextContent() ) )
      +  295  0
               append( sb, parameterDescription, 3 );
      +  296  0
               if ( "true".equals( getValue( parameter, "required" ) ) )
       297  
               {
      -  298  0
                   String property = getPropertyFromExpression( fieldConfigurationElement.getTextContent() );
      -  299  0
                   append( sb, "User property: " + property, 3 );
      -  300   +  298  0
                   append( sb, "Required: Yes", 3 );
      +  299  
               }
      +  300  0
               if ( ( fieldConfigurationElement != null ) && isNotEmpty( fieldConfigurationElement.getTextContent() ) )
       301   -
       
      -  302  0
               append( sb, "", 0 );
      -  303  0
           }
      +
               {
      +  302  0
                   String property = getPropertyFromExpression( fieldConfigurationElement.getTextContent() );
      +  303  0
                   append( sb, "User property: " + property, 3 );
       304   -
       
      -  305   -
           /**
      -  306   -
            * <p>Repeat a String <code>n</code> times to form a new string.</p>
      -  307   -
            *
      -  308   -
            * @param str    String to repeat
      -  309   -
            * @param repeat number of times to repeat str
      -  310   -
            * @return String with repeated String
      -  311   -
            * @throws NegativeArraySizeException if <code>repeat < 0</code>
      -  312   -
            * @throws NullPointerException       if str is <code>null</code>
      -  313   -
            */
      -  314   -
           private static String repeat( String str, int repeat )
      -  315   -
           {
      -  316  0
               StringBuilder buffer = new StringBuilder( repeat * str.length() );
      -  317   -
       
      -  318  0
               for ( int i = 0; i < repeat; i++ )
      -  319   -
               {
      -  320  0
                   buffer.append( str );
      -  321  
               }
      -  322   +  305  
       
      -  323  0
               return buffer.toString();
      -  324   -
           }
      -  325   +  306  0
               append( sb, "", 0 );
      +  307  0
           }
      +  308  
       
      -  326   +  309  
           /**
      -  327   -
            * Append a description to the buffer by respecting the indentSize and lineLength parameters.
      -  328   -
            * <b>Note</b>: The last character is always a new line.
      -  329   +  310   +
            * <p>Repeat a String <code>n</code> times to form a new string.</p>
      +  311  
            *
      -  330   -
            * @param sb          The buffer to append the description, not <code>null</code>.
      -  331   -
            * @param description The description, not <code>null</code>.
      -  332   -
            * @param indent      The base indentation level of each line, must not be negative.
      -  333   +  312   +
            * @param str    String to repeat
      +  313   +
            * @param repeat number of times to repeat str
      +  314   +
            * @return String with repeated String
      +  315   +
            * @throws NegativeArraySizeException if <code>repeat &lt; 0</code>
      +  316   +
            * @throws NullPointerException       if str is <code>null</code>
      +  317  
            */
      -  334   -
           private void append( StringBuilder sb, String description, int indent )
      -  335   +  318   +
           private static String repeat( String str, int repeat )
      +  319  
           {
      -  336  0
               for ( String line : toLines( description, indent, indentSize, lineLength ) )
      -  337   +  320  0
               StringBuilder buffer = new StringBuilder( repeat * str.length() );
      +  321   +
       
      +  322  0
               for ( int i = 0; i < repeat; i++ )
      +  323  
               {
      -  338  0
                   sb.append( line ).append( '\n' );
      -  339  0
               }
      -  340  0
           }
      -  341   +  324  0
                   buffer.append( str );
      +  325   +
               }
      +  326  
       
      -  342   +  327  0
               return buffer.toString();
      +  328   +
           }
      +  329   +
       
      +  330  
           /**
      -  343   -
            * Splits the specified text into lines of convenient display length.
      -  344   +  331   +
            * Append a description to the buffer by respecting the indentSize and lineLength parameters.
      +  332   +
            * <b>Note</b>: The last character is always a new line.
      +  333  
            *
      -  345   -
            * @param text       The text to split into lines, must not be <code>null</code>.
      -  346   -
            * @param indent     The base indentation level of each line, must not be negative.
      -  347   -
            * @param indentSize The size of each indentation, must not be negative.
      -  348   -
            * @param lineLength The length of the line, must not be negative.
      -  349   -
            * @return The sequence of display lines, never <code>null</code>.
      -  350   -
            * @throws NegativeArraySizeException if <code>indent < 0</code>
      -  351   +  334   +
            * @param sb          The buffer to append the description, not <code>null</code>.
      +  335   +
            * @param description The description, not <code>null</code>.
      +  336   +
            * @param indent      The base indentation level of each line, must not be negative.
      +  337  
            */
      -  352   -
           private static List<String> toLines( String text, int indent, int indentSize, int lineLength )
      -  353   +  338   +
           private void append( StringBuilder sb, String description, int indent )
      +  339  
           {
      -  354  0
               List<String> lines = new ArrayList<String>();
      +  340  0
               for ( String line : toLines( description, indent, indentSize, lineLength ) )
      +  341   +
               {
      +  342  0
                   sb.append( line ).append( '\n' );
      +  343  0
               }
      +  344  0
           }
      +  345   +
       
      +  346   +
           /**
      +  347   +
            * Splits the specified text into lines of convenient display length.
      +  348   +
            *
      +  349   +
            * @param text       The text to split into lines, must not be <code>null</code>.
      +  350   +
            * @param indent     The base indentation level of each line, must not be negative.
      +  351   +
            * @param indentSize The size of each indentation, must not be negative.
      +  352   +
            * @param lineLength The length of the line, must not be negative.
      +  353   +
            * @return The sequence of display lines, never <code>null</code>.
      +  354   +
            * @throws NegativeArraySizeException if <code>indent < 0</code>
       355   -
       
      -  356  0
               String ind = repeat( "\t", indent );
      +
            */
      +  356   +
           private static List<String> toLines( String text, int indent, int indentSize, int lineLength )
       357   -
       
      -  358  0
               String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
      +
           {
      +  358  0
               List<String> lines = new ArrayList<String>();
       359  
       
      -  360  0
               for ( String plainLine : plainLines )
      +  360  0
               String ind = repeat( "\t", indent );
       361   -
               {
      -  362  0
                   toLines( lines, ind + plainLine, indentSize, lineLength );
      +
       
      +  362  0
               String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
       363   -
               }
      -  364  
       
      -  365  0
               return lines;
      -  366   -
           }
      -  367   -
       
      -  368   -
           /**
      -  369   -
            * Adds the specified line to the output sequence, performing line wrapping if necessary.
      -  370   -
            *
      -  371   -
            * @param lines      The sequence of display lines, must not be <code>null</code>.
      -  372   -
            * @param line       The line to add, must not be <code>null</code>.
      -  373   -
            * @param indentSize The size of each indentation, must not be negative.
      -  374   -
            * @param lineLength The length of the line, must not be negative.
      -  375   -
            */
      -  376   -
           private static void toLines( List<String> lines, String line, int indentSize, int lineLength )
      -  377   -
           {
      -  378  0
               int lineIndent = getIndentLevel( line );
      -  379  0
               StringBuilder buf = new StringBuilder( 256 );
      -  380   -
       
      -  381  0
               String[] tokens = line.split( " +" );
      -  382   -
       
      -  383  0
               for ( String token : tokens )
      -  384   +  364  0
               for ( String plainLine : plainLines )
      +  365  
               {
      -  385  0
                   if ( buf.length() > 0 )
      +  366  0
                   toLines( lines, ind + plainLine, indentSize, lineLength );
      +  367   +
               }
      +  368   +
       
      +  369  0
               return lines;
      +  370   +
           }
      +  371   +
       
      +  372   +
           /**
      +  373   +
            * Adds the specified line to the output sequence, performing line wrapping if necessary.
      +  374   +
            *
      +  375   +
            * @param lines      The sequence of display lines, must not be <code>null</code>.
      +  376   +
            * @param line       The line to add, must not be <code>null</code>.
      +  377   +
            * @param indentSize The size of each indentation, must not be negative.
      +  378   +
            * @param lineLength The length of the line, must not be negative.
      +  379   +
            */
      +  380   +
           private static void toLines( List<String> lines, String line, int indentSize, int lineLength )
      +  381   +
           {
      +  382  0
               int lineIndent = getIndentLevel( line );
      +  383  0
               StringBuilder buf = new StringBuilder( 256 );
      +  384   +
       
      +  385  0
               String[] tokens = line.split( " +" );
       386   -
                   {
      -  387  0
                       if ( buf.length() + token.length() >= lineLength )
      +
       
      +  387  0
               for ( String token : tokens )
       388   -
                       {
      -  389  0
                           lines.add( buf.toString() );
      -  390  0
                           buf.setLength( 0 );
      -  391  0
                           buf.append( repeat( " ", lineIndent * indentSize ) );
      +
               {
      +  389  0
                   if ( buf.length() > 0 )
      +  390   +
                   {
      +  391  0
                       if ( buf.length() + token.length() >= lineLength )
       392   -
                       }
      -  393   -
                       else
      -  394  
                       {
      -  395  0
                           buf.append( ' ' );
      +  393  0
                           lines.add( buf.toString() );
      +  394  0
                           buf.setLength( 0 );
      +  395  0
                           buf.append( repeat( " ", lineIndent * indentSize ) );
       396  
                       }
       397   -
                   }
      +
                       else
       398   -
       
      -  399  0
                   for ( int j = 0; j < token.length(); j++ )
      -  400   -
                   {
      -  401  0
                       char c = token.charAt( j );
      -  402  0
                       if ( c == '\t' )
      -  403  
                       {
      -  404  0
                           buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
      -  405   +  399  0
                           buf.append( ' ' );
      +  400  
                       }
      -  406  0
                       else if ( c == '\u00A0' )
      +  401   +
                   }
      +  402   +
       
      +  403  0
                   for ( int j = 0; j < token.length(); j++ )
      +  404   +
                   {
      +  405  0
                       char c = token.charAt( j );
      +  406  0
                       if ( c == '\t' )
       407  
                       {
      -  408  0
                           buf.append( ' ' );
      +  408  0
                           buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
       409  
                       }
      -  410   -
                       else
      +  410  0
                       else if ( c == '\u00A0' )
       411  
                       {
      -  412  0
                           buf.append( c );
      +  412  0
                           buf.append( ' ' );
       413  
                       }
       414   -
                   }
      +
                       else
       415   -
               }
      -  416  0
               lines.add( buf.toString() );
      -  417  0
           }
      +
                       {
      +  416  0
                           buf.append( c );
      +  417   +
                       }
       418   -
       
      +
                   }
       419   -
           /**
      -  420   -
            * Gets the indentation level of the specified line.
      -  421   -
            *
      -  422   -
            * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
      -  423   -
            * @return The indentation level of the line.
      -  424   -
            */
      -  425   -
           private static int getIndentLevel( String line )
      -  426   -
           {
      -  427  0
               int level = 0;
      -  428  0
               for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
      -  429   -
               {
      -  430  0
                   level++;
      -  431  
               }
      -  432  0
               for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
      +  420  0
               lines.add( buf.toString() );
      +  421  0
           }
      +  422   +
       
      +  423   +
           /**
      +  424   +
            * Gets the indentation level of the specified line.
      +  425   +
            *
      +  426   +
            * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
      +  427   +
            * @return The indentation level of the line.
      +  428   +
            */
      +  429   +
           private static int getIndentLevel( String line )
      +  430   +
           {
      +  431  0
               int level = 0;
      +  432  0
               for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
       433  
               {
      -  434  0
                   if ( line.charAt( i ) == '\t' )
      +  434  0
                   level++;
       435   -
                   {
      -  436  0
                       level++;
      -  437  0
                       break;
      -  438   -
                   }
      -  439  
               }
      -  440  0
               return level;
      -  441   -
           }
      -  442   -
           
      -  443   -
           private String getPropertyFromExpression( String expression )
      -  444   -
           {
      -  445  0
               if ( expression != null && expression.startsWith( "${" ) && expression.endsWith( "}" )
      -  446  0
                   && !expression.substring( 2 ).contains( "${" ) )
      -  447   +  436  0
               for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
      +  437  
               {
      -  448   -
                   // expression="${xxx}" -> property="xxx"
      -  449  0
                   return expression.substring( 2, expression.length() - 1 );
      -  450   +  438  0
                   if ( line.charAt( i ) == '\t' )
      +  439   +
                   {
      +  440  0
                       level++;
      +  441  0
                       break;
      +  442   +
                   }
      +  443  
               }
      -  451   -
               // no property can be extracted
      -  452  0
               return null;
      -  453   +  444  0
               return level;
      +  445  
           }
      +  446   +
           
      +  447   +
           private String getPropertyFromExpression( String expression )
      +  448   +
           {
      +  449  0
               if ( expression != null && expression.startsWith( "${" ) && expression.endsWith( "}" )
      +  450  0
                   && !expression.substring( 2 ).contains( "${" ) )
      +  451   +
               {
      +  452   +
                   // expression="${xxx}" -> property="xxx"
      +  453  0
                   return expression.substring( 2, expression.length() - 1 );
       454   +
               }
      +  455   +
               // no property can be extracted
      +  456  0
               return null;
      +  457   +
           }
      +  458  
       }
      - + diff --git a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.MavenEngine.html b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.MavenEngine.html index cadafd591..964923203 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.MavenEngine.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.MavenEngine.html @@ -433,6 +433,6 @@
       }
      - + diff --git a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.PurgeMojo.html b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.PurgeMojo.html index 08ef1af31..67f49f415 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.PurgeMojo.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.PurgeMojo.html @@ -241,6 +241,6 @@
       }
      - + diff --git a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.UpdateMojo.html b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.UpdateMojo.html index 18161461b..eac6ad72e 100644 --- a/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.UpdateMojo.html +++ b/dependency-check-maven/cobertura/org.owasp.dependencycheck.maven.UpdateMojo.html @@ -155,14 +155,14 @@  72  0
                       getLog().debug("Database connection error", ex);
       73  
                   }
      -  74  0
                   final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
      +  74  0
                   final String msg = "An exception occurred connecting to the local database. Please see the log file for more details.";
       75  0
                   if (this.isFailOnError()) {
       76  0
                       throw new MojoExecutionException(msg, ex);
       77  
                   }
       78  0
                   getLog().error(msg);
       79  0
               } catch (UpdateException ex) {
      -  80  0
                   final String msg = "An exception occured while downloading updates. Please see the log file for more details.";
      +  80  0
                   final String msg = "An exception occurred while downloading updates. Please see the log file for more details.";
       81  0
                   if (this.isFailOnError()) {
       82  0
                       throw new MojoExecutionException(msg, ex);
       83   @@ -223,6 +223,6 @@
       }
      - + diff --git a/dependency-check-maven/configuration.html b/dependency-check-maven/configuration.html index 83c0060d6..95c291d8d 100644 --- a/dependency-check-maven/configuration.html +++ b/dependency-check-maven/configuration.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Goals @@ -52,7 +52,7 @@ @@ -314,6 +314,15 @@ +hintsFile + +The file path to the XML hints file - used to resolve false negatives + +  + + + + enableExperimental Enable the experimental analyzers. If not enabled the experimental analyzers (see below) will not be loaded or used. diff --git a/dependency-check-maven/dependency-analysis.html b/dependency-check-maven/dependency-analysis.html index 8696f6f6b..708a09f25 100644 --- a/dependency-check-maven/dependency-analysis.html +++ b/dependency-check-maven/dependency-analysis.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Dependencies Report @@ -52,7 +52,7 @@ @@ -253,7 +253,7 @@ org.owasp dependency-check-core -1.4.3 +1.4.4 compile jar @@ -261,7 +261,7 @@ org.owasp dependency-check-utils -1.4.3 +1.4.4 compile jar @@ -293,7 +293,7 @@ org.apache.maven.plugin-tools maven-plugin-annotations -3.4 +3.5 provided jar diff --git a/dependency-check-maven/dependency-updates-report.html b/dependency-check-maven/dependency-updates-report.html index ce2ebea0e..a7962c01e 100644 --- a/dependency-check-maven/dependency-updates-report.html +++ b/dependency-check-maven/dependency-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Dependency Updates Report @@ -52,7 +52,7 @@ @@ -244,7 +244,7 @@ # of dependencies using the latest version available -23 +24 # of dependencies where the next version available is smaller than an incremental version update @@ -252,7 +252,7 @@ # of dependencies where the next version available is an incremental version update -1 +0 # of dependencies where the next version available is a minor version update @@ -325,15 +325,15 @@ 1.4.177 - + com.sun.mail mailapi -1.5.5 +1.5.6 jar -1.5.6 + @@ -529,16 +529,16 @@ - + org.apache.maven.plugin-tools maven-plugin-annotations -3.4 +3.5 jar -3.5 + @@ -613,7 +613,7 @@ 1.25 - + org.jsoup jsoup 1.9.2 @@ -622,7 +622,7 @@ jar - +1.10.1 @@ -691,7 +691,7 @@ org.owasp dependency-check-core -1.4.3 +1.4.4 compile jar @@ -703,7 +703,7 @@ org.owasp dependency-check-utils -1.4.3 +1.4.4 compile jar @@ -824,13 +824,13 @@ jar Newer versions -1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192 Latest Minor +1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192
      1.4.193 Latest Minor

      com.sun.mail:mailapi

      - + @@ -839,7 +839,7 @@ - + @@ -848,10 +848,7 @@ - - - -
      Status There is at least one newer incremental version available. Incremental updates are typically passive.
       No newer versions available.
      Group Id com.sun.mail
      mailapi
      Current Version1.5.5
      1.5.6
      Scope
      Typejar
      Newer versions1.5.6 Next Incremental
      +jar

      commons-cli:commons-cli

      @@ -1049,7 +1046,7 @@ -
      jar
      Newer versions3.4 Next Minor
      +3.4 Next Minor
      3.5 Latest Minor

      org.apache.lucene:lucene-analyzers-common

      @@ -1076,7 +1073,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-core

      @@ -1103,7 +1100,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-queryparser

      @@ -1130,7 +1127,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-test-framework

      @@ -1157,7 +1154,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.maven:maven-core

      @@ -1259,7 +1256,7 @@
      - + @@ -1268,7 +1265,7 @@ - + @@ -1277,10 +1274,7 @@ - - - -
      Status There is at least one newer minor version available. Minor updates are sometimes passive.
       No newer versions available.
      Group Id org.apache.maven.plugin-tools
      maven-plugin-annotations
      Current Version3.4
      3.5
      Scope
      Typejar
      Newer versions3.5 Next Minor
      +jar

      org.apache.maven.reporting:maven-reporting-api

      @@ -1430,13 +1424,13 @@ -
      jar
      Newer versions1.25 Next Minor
      1.26
      1.27 Latest Minor
      +1.25 Next Minor
      1.26
      1.27
      1.28
      1.29 Latest Minor

      org.jsoup:jsoup

      - + @@ -1454,7 +1448,10 @@ -
      Status No newer versions available.
       There is at least one newer minor version available. Minor updates are sometimes passive.
      Group Id org.jsoup
      Typejar
      +jar + +Newer versions +1.10.1 Next Minor

      org.owasp:dependency-check-core

      @@ -1469,7 +1466,7 @@ - + @@ -1493,7 +1490,7 @@ - + diff --git a/dependency-check-maven/findbugs.html b/dependency-check-maven/findbugs.html index 06a743941..fd5656dce 100644 --- a/dependency-check-maven/findbugs.html +++ b/dependency-check-maven/findbugs.html @@ -1,13 +1,13 @@ - + dependency-check-maven – FindBugs Bug Detector Report @@ -52,7 +52,7 @@ @@ -252,7 +252,7 @@ - +
      dependency-check-core
      Current Version1.4.3
      1.4.4
      Scope compile
      dependency-check-utils
      Current Version1.4.3
      1.4.4
      Scope compile
      Errors Missing Classes
      107 0 0 0
      diff --git a/dependency-check-maven/help-mojo.html b/dependency-check-maven/help-mojo.html index 453718592..407f1ef01 100644 --- a/dependency-check-maven/help-mojo.html +++ b/dependency-check-maven/help-mojo.html @@ -1,13 +1,13 @@ - + dependency-check-maven – dependency-check:help @@ -52,7 +52,7 @@ @@ -153,7 +153,7 @@

      Full name:

      -

      org.owasp:dependency-check-maven:1.4.3:help

      +

      org.owasp:dependency-check-maven:1.4.4:help

      Description:

      @@ -163,11 +163,6 @@ Call mvn dependency-check:help -Ddetail=true

      Attributes:

      -
        - -
      • The goal is thread-safe and supports parallel builds.
      • -
      -

      Optional Parameters

      @@ -193,7 +188,7 @@ Call mvn dependency-check:help -Ddetail=true - If true, display all settable properties for each -goal.
      Default value is: false.
      User property is: detail. +goal.
      Default value is: false.
      User property is: detail.
      @@ -205,7 +200,7 @@ goal.
      Default value is: false.
      User property is - The name of the goal for which to show help. If unspecified, all -goals will be displayed.
      User property is: goal. +goals will be displayed.
      User property is: goal.
      @@ -216,7 +211,7 @@ goals will be displayed.
      User property is: goal. - -The number of spaces per indentation level, should be positive.
      Default value is: 2.
      User property is: indentSize. +The number of spaces per indentation level, should be positive.
      Default value is: 2.
      User property is: indentSize.
      @@ -227,7 +222,7 @@ goals will be displayed.
      User property is: goal. - -The maximum length of a display line, should be positive.
      Default value is: 80.
      User property is: lineLength. +The maximum length of a display line, should be positive.
      Default value is: 80.
      User property is: lineLength.
      diff --git a/dependency-check-maven/index.html b/dependency-check-maven/index.html index dc0f2d26c..3bfb05b44 100644 --- a/dependency-check-maven/index.html +++ b/dependency-check-maven/index.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Usage @@ -52,7 +52,7 @@ @@ -145,9 +145,9 @@

      Usage

      -

      Dependency-check-maven is very simple to utilize and can be used as a stand-alone plugin or as part of the site plugin.

      +

      Dependency-check-maven is very simple to utilize and can be used as a stand-alone plug-in or as part of the site plug-in. The plug-in requires Maven 3.1 or higher.

      It is important to understand that the first time this task is executed it may take 20 minutes or more as it downloads and processes the data from the National Vulnerability Database (NVD) hosted by NIST: https://nvd.nist.gov

      -

      After the first batch download, as long as the plugin is executed at least once every seven days the update will only take a few seconds.

      +

      After the first batch download, as long as the plug-in is executed at least once every seven days the update will only take a few seconds.

      Example 1:

      @@ -163,7 +163,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> <executions> <execution> <goals> @@ -193,7 +193,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> <reportSets> <reportSet> <reports> @@ -223,7 +223,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> <configuration> <failBuildOnCVSS>8</failBuildOnCVSS> </configuration> @@ -256,7 +256,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> <configuration> <skipProvidedScope>true</skipProvidedScope> <skipRuntimeScope>true</skipRuntimeScope> @@ -290,7 +290,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> <configuration> <cveUrl12Modified>http://internal-mirror.mycorp.com/downloads/nist/nvdcve-Modified.xml.gz</cveUrl12Modified> <cveUrl20Modified>http://internal-mirror.mycorp.com/downloads/nist/nvdcve-2.0-Modified.xml.gz</cveUrl20Modified> @@ -326,7 +326,7 @@ <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> <executions> <execution> <goals> diff --git a/dependency-check-maven/integration.html b/dependency-check-maven/integration.html index cfc4e9cd8..c7fa350b7 100644 --- a/dependency-check-maven/integration.html +++ b/dependency-check-maven/integration.html @@ -1,13 +1,13 @@ - + dependency-check-maven – CI Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-maven/issue-tracking.html b/dependency-check-maven/issue-tracking.html index bfdfa116b..d1238415d 100644 --- a/dependency-check-maven/issue-tracking.html +++ b/dependency-check-maven/issue-tracking.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Issue Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-maven/license.html b/dependency-check-maven/license.html index 8eb17df6c..212380ab2 100644 --- a/dependency-check-maven/license.html +++ b/dependency-check-maven/license.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Project Licenses @@ -52,7 +52,7 @@ diff --git a/dependency-check-maven/mail-lists.html b/dependency-check-maven/mail-lists.html index d2ca2b677..abde2f6a7 100644 --- a/dependency-check-maven/mail-lists.html +++ b/dependency-check-maven/mail-lists.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Project Mailing Lists @@ -52,7 +52,7 @@ diff --git a/dependency-check-maven/plugin-info.html b/dependency-check-maven/plugin-info.html index b7d5ad8eb..26a6542bc 100644 --- a/dependency-check-maven/plugin-info.html +++ b/dependency-check-maven/plugin-info.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Plugin Documentation @@ -52,7 +52,7 @@ @@ -277,7 +277,7 @@ have any known published vulnerabilities. - + @@ -299,7 +299,7 @@ have any known published vulnerabilities.
      Maven2.0
      3.1
      JDK 1.6
      <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </plugin> ... </plugins> @@ -309,7 +309,7 @@ have any known published vulnerabilities. <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </plugin> ... </plugins> @@ -321,7 +321,7 @@ have any known published vulnerabilities. <plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </plugin> ... </plugins> diff --git a/dependency-check-maven/plugin-updates-report.html b/dependency-check-maven/plugin-updates-report.html index 7887ce529..254e46d71 100644 --- a/dependency-check-maven/plugin-updates-report.html +++ b/dependency-check-maven/plugin-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Plugin Updates Report @@ -52,7 +52,7 @@ @@ -412,7 +412,7 @@ org.apache.maven.plugins maven-resources-plugin -3.0.0 +3.0.1 @@ -495,7 +495,7 @@ org.apache.maven.plugins maven-plugin-plugin -3.4 +3.5 @@ -708,7 +708,7 @@ maven-plugin-plugin Current Version -3.4
      +3.5

      Plugin org.apache.maven.plugins:maven-release-plugin

      @@ -738,7 +738,7 @@ -
      maven-resources-plugin
      Current Version3.0.0
      +3.0.1

      Plugin org.apache.maven.plugins:maven-site-plugin

      diff --git a/dependency-check-maven/pmd.html b/dependency-check-maven/pmd.html index a06b11df1..215eee404 100644 --- a/dependency-check-maven/pmd.html +++ b/dependency-check-maven/pmd.html @@ -1,13 +1,13 @@ - + dependency-check-maven – PMD Results @@ -52,7 +52,7 @@ @@ -250,7 +250,7 @@ -
      Line
      Useless parentheses.897
      +905 diff --git a/dependency-check-maven/project-info.html b/dependency-check-maven/project-info.html index 48e1f8459..c18ba2e70 100644 --- a/dependency-check-maven/project-info.html +++ b/dependency-check-maven/project-info.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Project Information @@ -52,7 +52,7 @@ diff --git a/dependency-check-maven/project-reports.html b/dependency-check-maven/project-reports.html index ee18b2287..5845083ff 100644 --- a/dependency-check-maven/project-reports.html +++ b/dependency-check-maven/project-reports.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Generated Reports @@ -52,7 +52,7 @@ diff --git a/dependency-check-maven/project-summary.html b/dependency-check-maven/project-summary.html index 5fb857130..ccba2a134 100644 --- a/dependency-check-maven/project-summary.html +++ b/dependency-check-maven/project-summary.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Project Summary @@ -52,7 +52,7 @@ @@ -238,7 +238,7 @@ dependency-check-maven Version -1.4.3 +1.4.4 Type maven-plugin diff --git a/dependency-check-maven/purge-mojo.html b/dependency-check-maven/purge-mojo.html index 69ee01173..2268b2483 100644 --- a/dependency-check-maven/purge-mojo.html +++ b/dependency-check-maven/purge-mojo.html @@ -1,13 +1,13 @@ - + dependency-check-maven – dependency-check:purge @@ -52,7 +52,7 @@ @@ -155,7 +155,7 @@

      Full name:

      -

      org.owasp:dependency-check-maven:1.4.3:purge

      +

      org.owasp:dependency-check-maven:1.4.4:purge

      Description:

      @@ -196,7 +196,7 @@ - -Sets whether or not the external report format should be used.
      Default value is: dependency-check.ser.
      User property is: metaFileName. +Sets whether or not the external report format should be used.
      Default value is: dependency-check.ser.
      User property is: metaFileName.
      @@ -209,7 +209,7 @@ Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since -the CVSS scores are 0-10, by default the build will never fail.
      Default value is: 11.
      User property is: failBuildOnCVSS. +the CVSS scores are 0-10, by default the build will never fail.
      Default value is: 11.
      User property is: failBuildOnCVSS.
      @@ -220,7 +220,7 @@ the CVSS scores are 0-10, by default the build will never fail.
      Default - -Sets whether or not the external report format should be used.
      Default value is: true.
      User property is: failOnError. +Sets whether or not the external report format should be used.
      Default value is: true.
      User property is: failOnError.
      @@ -233,7 +233,7 @@ the CVSS scores are 0-10, by default the build will never fail.
      Default The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site -plug-in unless the externalReport is set to true. Default is HTML.
      Default value is: HTML.
      User property is: format. +plug-in unless the externalReport is set to true. Default is HTML.
      Default value is: HTML.
      User property is: format.
      @@ -256,7 +256,7 @@ plug-in unless the externalReport is set to true. Default is HTML.
      Defau - Specifies the destination directory for the generated -Dependency-Check report. This generally maps to "target/site".
      User property is: project.reporting.outputDirectory. +Dependency-Check report. This generally maps to "target/site".
      User property is: project.reporting.outputDirectory.
      @@ -285,7 +285,7 @@ Dependency-Check report. This generally maps to "target/site".
      - -Deprecated. use the aggregate goal instead
      User property is: aggregate. +Deprecated. use the aggregate goal instead
      User property is: aggregate.
      @@ -296,7 +296,7 @@ Dependency-Check report. This generally maps to "target/site".
      - -Whether or not the Archive Analyzer is enabled.
      User property is: archiveAnalyzerEnabled. +Whether or not the Archive Analyzer is enabled.
      User property is: archiveAnalyzerEnabled.
      @@ -307,7 +307,7 @@ Dependency-Check report. This generally maps to "target/site".
      - -Whether or not the .NET Assembly Analyzer is enabled.
      User property is: assemblyAnalyzerEnabled. +Whether or not the .NET Assembly Analyzer is enabled.
      User property is: assemblyAnalyzerEnabled.
      @@ -319,7 +319,7 @@ Dependency-Check report. This generally maps to "target/site".
      - Sets whether auto-updating of the NVD CVE/CPE data is enabled. It -is not recommended that this be turned to false. Default is true.
      User property is: autoUpdate. +is not recommended that this be turned to false. Default is true.
      User property is: autoUpdate.
      @@ -330,7 +330,7 @@ is not recommended that this be turned to false. Default is true.
      User p - -Sets whether or not the autoconf Analyzer should be used.
      User property is: autoconfAnalyzerEnabled. +Sets whether or not the autoconf Analyzer should be used.
      User property is: autoconfAnalyzerEnabled.
      @@ -341,7 +341,7 @@ is not recommended that this be turned to false. Default is true.
      User p - -Whether or not the Central Analyzer is enabled.
      User property is: centralAnalyzerEnabled. +Whether or not the Central Analyzer is enabled.
      User property is: centralAnalyzerEnabled.
      @@ -352,7 +352,7 @@ is not recommended that this be turned to false. Default is true.
      User p - -Sets whether or not the CMake Analyzer should be used.
      User property is: cmakeAnalyzerEnabled. +Sets whether or not the CMake Analyzer should be used.
      User property is: cmakeAnalyzerEnabled.
      @@ -364,7 +364,7 @@ is not recommended that this be turned to false. Default is true.
      User p - Sets whether or not the PHP Composer Lock File Analyzer should be -used.
      User property is: composerAnalyzerEnabled. +used.
      User property is: composerAnalyzerEnabled.
      @@ -375,7 +375,7 @@ used.
      User property is: composerAnalyzerEnabled. - -The database connection string.
      User property is: connectionString. +The database connection string.
      User property is: connectionString.
      @@ -386,7 +386,7 @@ used.
      User property is: composerAnalyzerEnabled. - -The Connection Timeout.
      User property is: connectionTimeout. +The Connection Timeout.
      User property is: connectionTimeout.
      @@ -397,7 +397,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Base Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Base. +Base Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Base.
      @@ -408,7 +408,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Modified. +Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Modified.
      @@ -419,7 +419,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Base. +Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Base.
      @@ -430,7 +430,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Modified. +Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Modified.
      @@ -442,7 +442,7 @@ used.
      User property is: composerAnalyzerEnabled. - Optionally skip excessive CVE update checks for a designated -duration in hours.
      User property is: cveValidForHours. +duration in hours.
      User property is: cveValidForHours.
      @@ -453,7 +453,7 @@ duration in hours.
      User property is: cveValidForHours. - -The data directory, hold DC SQL DB.
      User property is: dataDirectory. +The data directory, hold DC SQL DB.
      User property is: dataDirectory.
      @@ -464,7 +464,7 @@ duration in hours.
      User property is: cveValidForHours. - -The database driver name. An example would be org.h2.Driver.
      User property is: databaseDriverName. +The database driver name. An example would be org.h2.Driver.
      User property is: databaseDriverName.
      @@ -475,7 +475,7 @@ duration in hours.
      User property is: cveValidForHours. - -The path to the database driver if it is not on the class path.
      User property is: databaseDriverPath. +The path to the database driver if it is not on the class path.
      User property is: databaseDriverPath.
      @@ -486,7 +486,7 @@ duration in hours.
      User property is: cveValidForHours. - -The password to use when connecting to the database.
      User property is: databasePassword. +The password to use when connecting to the database.
      User property is: databasePassword.
      @@ -497,7 +497,7 @@ duration in hours.
      User property is: cveValidForHours. - -The database user name.
      User property is: databaseUser. +The database user name.
      User property is: databaseUser.
      @@ -508,7 +508,7 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether Experimental analyzers are enabled. Default is false.
      User property is: enableExperimental. +Sets whether Experimental analyzers are enabled. Default is false.
      User property is: enableExperimental.
      @@ -519,21 +519,32 @@ duration in hours.
      User property is: cveValidForHours. - -Deprecated. the internal report is no longer supported
      User property is: externalReport. +Deprecated. the internal report is no longer supported
      User property is: externalReport.
      +hintsFile + +String + +- + +The path to the hints file.
      User property is: hintsFile.
      + + + + jarAnalyzerEnabled Boolean - -Whether or not the Jar Analyzer is enabled.
      User property is: jarAnalyzerEnabled. +Whether or not the Jar Analyzer is enabled.
      User property is: jarAnalyzerEnabled.
      - + mavenSettings @@ -541,10 +552,10 @@ duration in hours.
      User property is: cveValidForHours. - -The Maven settings.
      Default value is: ${settings}.
      User property is: mavenSettings. +The Maven settings.
      Default value is: ${settings}.
      User property is: mavenSettings.
      - + mavenSettingsProxyId @@ -552,10 +563,10 @@ duration in hours.
      User property is: cveValidForHours. - -The maven settings proxy id.
      User property is: mavenSettingsProxyId. +The maven settings proxy id.
      User property is: mavenSettingsProxyId.
      - + nexusAnalyzerEnabled @@ -563,10 +574,10 @@ duration in hours.
      User property is: cveValidForHours. - -Whether or not the Nexus Analyzer is enabled.
      User property is: nexusAnalyzerEnabled. +Whether or not the Nexus Analyzer is enabled.
      User property is: nexusAnalyzerEnabled.
      - + nexusUrl @@ -575,10 +586,10 @@ duration in hours.
      User property is: cveValidForHours. - The URL of a Nexus server's REST API end point -(http://domain/nexus/service/local).
      User property is: nexusUrl. +(http://domain/nexus/service/local).
      User property is: nexusUrl.
      - + nexusUsesProxy @@ -586,10 +597,10 @@ duration in hours.
      User property is: cveValidForHours. - -Whether or not the configured proxy is used to connect to Nexus.
      User property is: nexusUsesProxy. +Whether or not the configured proxy is used to connect to Nexus.
      User property is: nexusUsesProxy.
      - + nodeAnalyzerEnabled @@ -597,10 +608,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether or not the Node.js Analyzer should be used.
      User property is: nodeAnalyzerEnabled. +Sets whether or not the Node.js Analyzer should be used.
      User property is: nodeAnalyzerEnabled.
      - + nuspecAnalyzerEnabled @@ -608,10 +619,10 @@ duration in hours.
      User property is: cveValidForHours. - -Whether or not the .NET Nuspec Analyzer is enabled.
      User property is: nuspecAnalyzerEnabled. +Whether or not the .NET Nuspec Analyzer is enabled.
      User property is: nuspecAnalyzerEnabled.
      - + opensslAnalyzerEnabled @@ -619,10 +630,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether or not the openssl Analyzer should be used.
      User property is: opensslAnalyzerEnabled. +Sets whether or not the openssl Analyzer should be used.
      User property is: opensslAnalyzerEnabled.
      - + pathToMono @@ -630,10 +641,10 @@ duration in hours.
      User property is: cveValidForHours. - -The path to mono for .NET Assembly analysis on non-windows systems.
      User property is: pathToMono. +The path to mono for .NET Assembly analysis on non-windows systems.
      User property is: pathToMono.
      - + proxyUrl @@ -641,10 +652,10 @@ duration in hours.
      User property is: cveValidForHours. - -Deprecated. Please use mavenSettings instead
      User property is: proxyUrl. +Deprecated. Please use mavenSettings instead
      User property is: proxyUrl.
      - + pyDistributionAnalyzerEnabled @@ -652,10 +663,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether the Python Distribution Analyzer will be used.
      User property is: pyDistributionAnalyzerEnabled. +Sets whether the Python Distribution Analyzer will be used.
      User property is: pyDistributionAnalyzerEnabled.
      - + pyPackageAnalyzerEnabled @@ -663,10 +674,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether the Python Package Analyzer will be used.
      User property is: pyPackageAnalyzerEnabled. +Sets whether the Python Package Analyzer will be used.
      User property is: pyPackageAnalyzerEnabled.
      - + rubygemsAnalyzerEnabled @@ -674,10 +685,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether the Ruby Gemspec Analyzer will be used.
      User property is: rubygemsAnalyzerEnabled. +Sets whether the Ruby Gemspec Analyzer will be used.
      User property is: rubygemsAnalyzerEnabled.
      - + serverId @@ -686,10 +697,10 @@ duration in hours.
      User property is: cveValidForHours. - The server id in the settings.xml; used to retrieve encrypted -passwords from the settings.xml.
      User property is: serverId. +passwords from the settings.xml.
      User property is: serverId.
      - + showSummary @@ -697,10 +708,10 @@ passwords from the settings.xml.
      User property is: serverId - -Flag indicating whether or not to show a summary in the output.
      Default value is: true.
      User property is: showSummary. +Flag indicating whether or not to show a summary in the output.
      Default value is: true.
      User property is: showSummary.
      - + skip @@ -708,10 +719,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Dependency Check altogether.
      Default value is: false.
      User property is: dependency-check.skip. +Skip Dependency Check altogether.
      Default value is: false.
      User property is: dependency-check.skip.
      - + skipProvidedScope @@ -719,10 +730,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Analysis for Provided Scope Dependencies.
      Default value is: false.
      User property is: skipProvidedScope. +Skip Analysis for Provided Scope Dependencies.
      Default value is: false.
      User property is: skipProvidedScope.
      - + skipRuntimeScope @@ -730,10 +741,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Analysis for Runtime Scope Dependencies.
      Default value is: false.
      User property is: skipRuntimeScope. +Skip Analysis for Runtime Scope Dependencies.
      Default value is: false.
      User property is: skipRuntimeScope.
      - + skipTestScope @@ -741,10 +752,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Analysis for Test Scope Dependencies.
      Default value is: true.
      User property is: skipTestScope. +Skip Analysis for Test Scope Dependencies.
      Default value is: true.
      User property is: skipTestScope.
      - + suppressionFile @@ -752,10 +763,10 @@ passwords from the settings.xml.
      User property is: serverId - -The path to the suppression file.
      User property is: suppressionFile. +The path to the suppression file.
      User property is: suppressionFile.
      - + zipExtensions @@ -764,7 +775,7 @@ passwords from the settings.xml.
      User property is: serverId - A comma-separated list of file extensions to add to analysis next -to jar, zip, ....
      User property is: zipExtensions. +to jar, zip, ....
      User property is: zipExtensions.
      @@ -1103,6 +1114,18 @@ plug-in unless the externalReport is set to true. Default is HTML.
    59. Default: HTML

    60. +

      hintsFile:

      + +
      The path to the hints file.
      + +
        + +
      • Type: java.lang.String
      • + +
      • Required: No
      • + +
      • User Property: hintsFile
      • +

      jarAnalyzerEnabled:

      Whether or not the Jar Analyzer is enabled.
      diff --git a/dependency-check-maven/source-repository.html b/dependency-check-maven/source-repository.html index 5cb65077c..1f036ca39 100644 --- a/dependency-check-maven/source-repository.html +++ b/dependency-check-maven/source-repository.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Source Code Management @@ -52,7 +52,7 @@ diff --git a/dependency-check-maven/surefire-report.html b/dependency-check-maven/surefire-report.html index a2f737f90..21e8b30d7 100644 --- a/dependency-check-maven/surefire-report.html +++ b/dependency-check-maven/surefire-report.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Surefire Report @@ -52,7 +52,7 @@ @@ -273,7 +273,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.354
      +0.833

      Note: failures are anticipated and checked for with assertions while errors are unanticipated.


      Package List

      @@ -294,7 +294,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.354
      +0.833

      Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.

      org.owasp.dependencycheck.maven

      @@ -316,7 +316,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.354

      +0.833

      Test Cases

      [Summary] [Package List] [Test Cases]

      diff --git a/dependency-check-maven/taglist.html b/dependency-check-maven/taglist.html index b84688b0b..dc953e7c6 100644 --- a/dependency-check-maven/taglist.html +++ b/dependency-check-maven/taglist.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Tag List report @@ -52,7 +52,7 @@ @@ -259,7 +259,7 @@ Line fix logging -1241
      +1249 diff --git a/dependency-check-maven/team-list.html b/dependency-check-maven/team-list.html index e58aa7bb9..ef05e5ce0 100644 --- a/dependency-check-maven/team-list.html +++ b/dependency-check-maven/team-list.html @@ -1,13 +1,13 @@ - + dependency-check-maven – Project Team @@ -52,7 +52,7 @@ diff --git a/dependency-check-maven/update-only-mojo.html b/dependency-check-maven/update-only-mojo.html index fd8ce1734..93451c609 100644 --- a/dependency-check-maven/update-only-mojo.html +++ b/dependency-check-maven/update-only-mojo.html @@ -1,13 +1,13 @@ - + dependency-check-maven – dependency-check:update-only @@ -52,7 +52,7 @@ @@ -155,7 +155,7 @@

      Full name:

      -

      org.owasp:dependency-check-maven:1.4.3:update-only

      +

      org.owasp:dependency-check-maven:1.4.4:update-only

      Description:

      @@ -197,7 +197,7 @@ have any known published vulnerabilities. - -Sets whether or not the external report format should be used.
      Default value is: dependency-check.ser.
      User property is: metaFileName. +Sets whether or not the external report format should be used.
      Default value is: dependency-check.ser.
      User property is: metaFileName.
      @@ -210,7 +210,7 @@ have any known published vulnerabilities. Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since -the CVSS scores are 0-10, by default the build will never fail.
      Default value is: 11.
      User property is: failBuildOnCVSS. +the CVSS scores are 0-10, by default the build will never fail.
      Default value is: 11.
      User property is: failBuildOnCVSS.
      @@ -221,7 +221,7 @@ the CVSS scores are 0-10, by default the build will never fail.
      Default - -Sets whether or not the external report format should be used.
      Default value is: true.
      User property is: failOnError. +Sets whether or not the external report format should be used.
      Default value is: true.
      User property is: failOnError.
      @@ -234,7 +234,7 @@ the CVSS scores are 0-10, by default the build will never fail.
      Default The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site -plug-in unless the externalReport is set to true. Default is HTML.
      Default value is: HTML.
      User property is: format. +plug-in unless the externalReport is set to true. Default is HTML.
      Default value is: HTML.
      User property is: format.
      @@ -257,7 +257,7 @@ plug-in unless the externalReport is set to true. Default is HTML.
      Defau - Specifies the destination directory for the generated -Dependency-Check report. This generally maps to "target/site".
      User property is: project.reporting.outputDirectory. +Dependency-Check report. This generally maps to "target/site".
      User property is: project.reporting.outputDirectory.
      @@ -286,7 +286,7 @@ Dependency-Check report. This generally maps to "target/site".
      - -Deprecated. use the aggregate goal instead
      User property is: aggregate. +Deprecated. use the aggregate goal instead
      User property is: aggregate.
      @@ -297,7 +297,7 @@ Dependency-Check report. This generally maps to "target/site".
      - -Whether or not the Archive Analyzer is enabled.
      User property is: archiveAnalyzerEnabled. +Whether or not the Archive Analyzer is enabled.
      User property is: archiveAnalyzerEnabled.
      @@ -308,7 +308,7 @@ Dependency-Check report. This generally maps to "target/site".
      - -Whether or not the .NET Assembly Analyzer is enabled.
      User property is: assemblyAnalyzerEnabled. +Whether or not the .NET Assembly Analyzer is enabled.
      User property is: assemblyAnalyzerEnabled.
      @@ -320,7 +320,7 @@ Dependency-Check report. This generally maps to "target/site".
      - Sets whether auto-updating of the NVD CVE/CPE data is enabled. It -is not recommended that this be turned to false. Default is true.
      User property is: autoUpdate. +is not recommended that this be turned to false. Default is true.
      User property is: autoUpdate.
      @@ -331,7 +331,7 @@ is not recommended that this be turned to false. Default is true.
      User p - -Sets whether or not the autoconf Analyzer should be used.
      User property is: autoconfAnalyzerEnabled. +Sets whether or not the autoconf Analyzer should be used.
      User property is: autoconfAnalyzerEnabled.
      @@ -342,7 +342,7 @@ is not recommended that this be turned to false. Default is true.
      User p - -Whether or not the Central Analyzer is enabled.
      User property is: centralAnalyzerEnabled. +Whether or not the Central Analyzer is enabled.
      User property is: centralAnalyzerEnabled.
      @@ -353,7 +353,7 @@ is not recommended that this be turned to false. Default is true.
      User p - -Sets whether or not the CMake Analyzer should be used.
      User property is: cmakeAnalyzerEnabled. +Sets whether or not the CMake Analyzer should be used.
      User property is: cmakeAnalyzerEnabled.
      @@ -365,7 +365,7 @@ is not recommended that this be turned to false. Default is true.
      User p - Sets whether or not the PHP Composer Lock File Analyzer should be -used.
      User property is: composerAnalyzerEnabled. +used.
      User property is: composerAnalyzerEnabled.
      @@ -376,7 +376,7 @@ used.
      User property is: composerAnalyzerEnabled. - -The database connection string.
      User property is: connectionString. +The database connection string.
      User property is: connectionString.
      @@ -387,7 +387,7 @@ used.
      User property is: composerAnalyzerEnabled. - -The Connection Timeout.
      User property is: connectionTimeout. +The Connection Timeout.
      User property is: connectionTimeout.
      @@ -398,7 +398,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Base Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Base. +Base Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Base.
      @@ -409,7 +409,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Modified. +Data Mirror URL for CVE 1.2.
      User property is: cveUrl12Modified.
      @@ -420,7 +420,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Base. +Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Base.
      @@ -431,7 +431,7 @@ used.
      User property is: composerAnalyzerEnabled. - -Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Modified. +Data Mirror URL for CVE 2.0.
      User property is: cveUrl20Modified.
      @@ -443,7 +443,7 @@ used.
      User property is: composerAnalyzerEnabled. - Optionally skip excessive CVE update checks for a designated -duration in hours.
      User property is: cveValidForHours. +duration in hours.
      User property is: cveValidForHours.
      @@ -454,7 +454,7 @@ duration in hours.
      User property is: cveValidForHours. - -The data directory, hold DC SQL DB.
      User property is: dataDirectory. +The data directory, hold DC SQL DB.
      User property is: dataDirectory.
      @@ -465,7 +465,7 @@ duration in hours.
      User property is: cveValidForHours. - -The database driver name. An example would be org.h2.Driver.
      User property is: databaseDriverName. +The database driver name. An example would be org.h2.Driver.
      User property is: databaseDriverName.
      @@ -476,7 +476,7 @@ duration in hours.
      User property is: cveValidForHours. - -The path to the database driver if it is not on the class path.
      User property is: databaseDriverPath. +The path to the database driver if it is not on the class path.
      User property is: databaseDriverPath.
      @@ -487,7 +487,7 @@ duration in hours.
      User property is: cveValidForHours. - -The password to use when connecting to the database.
      User property is: databasePassword. +The password to use when connecting to the database.
      User property is: databasePassword.
      @@ -498,7 +498,7 @@ duration in hours.
      User property is: cveValidForHours. - -The database user name.
      User property is: databaseUser. +The database user name.
      User property is: databaseUser.
      @@ -509,7 +509,7 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether Experimental analyzers are enabled. Default is false.
      User property is: enableExperimental. +Sets whether Experimental analyzers are enabled. Default is false.
      User property is: enableExperimental.
      @@ -520,21 +520,32 @@ duration in hours.
      User property is: cveValidForHours. - -Deprecated. the internal report is no longer supported
      User property is: externalReport. +Deprecated. the internal report is no longer supported
      User property is: externalReport.
      +hintsFile + +String + +- + +The path to the hints file.
      User property is: hintsFile.
      + + + + jarAnalyzerEnabled Boolean - -Whether or not the Jar Analyzer is enabled.
      User property is: jarAnalyzerEnabled. +Whether or not the Jar Analyzer is enabled.
      User property is: jarAnalyzerEnabled.
      - + mavenSettings @@ -542,10 +553,10 @@ duration in hours.
      User property is: cveValidForHours. - -The Maven settings.
      Default value is: ${settings}.
      User property is: mavenSettings. +The Maven settings.
      Default value is: ${settings}.
      User property is: mavenSettings.
      - + mavenSettingsProxyId @@ -553,10 +564,10 @@ duration in hours.
      User property is: cveValidForHours. - -The maven settings proxy id.
      User property is: mavenSettingsProxyId. +The maven settings proxy id.
      User property is: mavenSettingsProxyId.
      - + nexusAnalyzerEnabled @@ -564,10 +575,10 @@ duration in hours.
      User property is: cveValidForHours. - -Whether or not the Nexus Analyzer is enabled.
      User property is: nexusAnalyzerEnabled. +Whether or not the Nexus Analyzer is enabled.
      User property is: nexusAnalyzerEnabled.
      - + nexusUrl @@ -576,10 +587,10 @@ duration in hours.
      User property is: cveValidForHours. - The URL of a Nexus server's REST API end point -(http://domain/nexus/service/local).
      User property is: nexusUrl. +(http://domain/nexus/service/local).
      User property is: nexusUrl.
      - + nexusUsesProxy @@ -587,10 +598,10 @@ duration in hours.
      User property is: cveValidForHours. - -Whether or not the configured proxy is used to connect to Nexus.
      User property is: nexusUsesProxy. +Whether or not the configured proxy is used to connect to Nexus.
      User property is: nexusUsesProxy.
      - + nodeAnalyzerEnabled @@ -598,10 +609,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether or not the Node.js Analyzer should be used.
      User property is: nodeAnalyzerEnabled. +Sets whether or not the Node.js Analyzer should be used.
      User property is: nodeAnalyzerEnabled.
      - + nuspecAnalyzerEnabled @@ -609,10 +620,10 @@ duration in hours.
      User property is: cveValidForHours. - -Whether or not the .NET Nuspec Analyzer is enabled.
      User property is: nuspecAnalyzerEnabled. +Whether or not the .NET Nuspec Analyzer is enabled.
      User property is: nuspecAnalyzerEnabled.
      - + opensslAnalyzerEnabled @@ -620,10 +631,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether or not the openssl Analyzer should be used.
      User property is: opensslAnalyzerEnabled. +Sets whether or not the openssl Analyzer should be used.
      User property is: opensslAnalyzerEnabled.
      - + pathToMono @@ -631,10 +642,10 @@ duration in hours.
      User property is: cveValidForHours. - -The path to mono for .NET Assembly analysis on non-windows systems.
      User property is: pathToMono. +The path to mono for .NET Assembly analysis on non-windows systems.
      User property is: pathToMono.
      - + proxyUrl @@ -642,10 +653,10 @@ duration in hours.
      User property is: cveValidForHours. - -Deprecated. Please use mavenSettings instead
      User property is: proxyUrl. +Deprecated. Please use mavenSettings instead
      User property is: proxyUrl.
      - + pyDistributionAnalyzerEnabled @@ -653,10 +664,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether the Python Distribution Analyzer will be used.
      User property is: pyDistributionAnalyzerEnabled. +Sets whether the Python Distribution Analyzer will be used.
      User property is: pyDistributionAnalyzerEnabled.
      - + pyPackageAnalyzerEnabled @@ -664,10 +675,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether the Python Package Analyzer will be used.
      User property is: pyPackageAnalyzerEnabled. +Sets whether the Python Package Analyzer will be used.
      User property is: pyPackageAnalyzerEnabled.
      - + rubygemsAnalyzerEnabled @@ -675,10 +686,10 @@ duration in hours.
      User property is: cveValidForHours. - -Sets whether the Ruby Gemspec Analyzer will be used.
      User property is: rubygemsAnalyzerEnabled. +Sets whether the Ruby Gemspec Analyzer will be used.
      User property is: rubygemsAnalyzerEnabled.
      - + serverId @@ -687,10 +698,10 @@ duration in hours.
      User property is: cveValidForHours. - The server id in the settings.xml; used to retrieve encrypted -passwords from the settings.xml.
      User property is: serverId. +passwords from the settings.xml.
      User property is: serverId.
      - + showSummary @@ -698,10 +709,10 @@ passwords from the settings.xml.
      User property is: serverId - -Flag indicating whether or not to show a summary in the output.
      Default value is: true.
      User property is: showSummary. +Flag indicating whether or not to show a summary in the output.
      Default value is: true.
      User property is: showSummary.
      - + skip @@ -709,10 +720,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Dependency Check altogether.
      Default value is: false.
      User property is: dependency-check.skip. +Skip Dependency Check altogether.
      Default value is: false.
      User property is: dependency-check.skip.
      - + skipProvidedScope @@ -720,10 +731,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Analysis for Provided Scope Dependencies.
      Default value is: false.
      User property is: skipProvidedScope. +Skip Analysis for Provided Scope Dependencies.
      Default value is: false.
      User property is: skipProvidedScope.
      - + skipRuntimeScope @@ -731,10 +742,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Analysis for Runtime Scope Dependencies.
      Default value is: false.
      User property is: skipRuntimeScope. +Skip Analysis for Runtime Scope Dependencies.
      Default value is: false.
      User property is: skipRuntimeScope.
      - + skipTestScope @@ -742,10 +753,10 @@ passwords from the settings.xml.
      User property is: serverId - -Skip Analysis for Test Scope Dependencies.
      Default value is: true.
      User property is: skipTestScope. +Skip Analysis for Test Scope Dependencies.
      Default value is: true.
      User property is: skipTestScope.
      - + suppressionFile @@ -753,10 +764,10 @@ passwords from the settings.xml.
      User property is: serverId - -The path to the suppression file.
      User property is: suppressionFile. +The path to the suppression file.
      User property is: suppressionFile.
      - + zipExtensions @@ -765,7 +776,7 @@ passwords from the settings.xml.
      User property is: serverId - A comma-separated list of file extensions to add to analysis next -to jar, zip, ....
      User property is: zipExtensions. +to jar, zip, ....
      User property is: zipExtensions.
      @@ -1104,6 +1115,18 @@ plug-in unless the externalReport is set to true. Default is HTML.
    61. Default: HTML

    62. +

      hintsFile:

      + +
      The path to the hints file.
      + +
        + +
      • Type: java.lang.String
      • + +
      • Required: No
      • + +
      • User Property: hintsFile
      • +

      jarAnalyzerEnabled:

      Whether or not the Jar Analyzer is enabled.
      diff --git a/dependency-check-maven/xref-test/index.html b/dependency-check-maven/xref-test/index.html index 35f4c3952..8afcccc99 100644 --- a/dependency-check-maven/xref-test/index.html +++ b/dependency-check-maven/xref-test/index.html @@ -4,7 +4,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference + Dependency-Check Maven Plugin 1.4.4 Reference diff --git a/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/package-frame.html b/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/package-frame.html index 5d43458b4..8384aa170 100644 --- a/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/package-frame.html +++ b/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference Package org.owasp.dependencycheck.maven + Dependency-Check Maven Plugin 1.4.4 Reference Package org.owasp.dependencycheck.maven diff --git a/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/package-summary.html b/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/package-summary.html index 14de4149a..51b996362 100644 --- a/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/package-summary.html +++ b/dependency-check-maven/xref-test/org/owasp/dependencycheck/maven/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference Package org.owasp.dependencycheck.maven + Dependency-Check Maven Plugin 1.4.4 Reference Package org.owasp.dependencycheck.maven diff --git a/dependency-check-maven/xref-test/overview-frame.html b/dependency-check-maven/xref-test/overview-frame.html index ac70d26af..8f1a95365 100644 --- a/dependency-check-maven/xref-test/overview-frame.html +++ b/dependency-check-maven/xref-test/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference + Dependency-Check Maven Plugin 1.4.4 Reference diff --git a/dependency-check-maven/xref-test/overview-summary.html b/dependency-check-maven/xref-test/overview-summary.html index 84884c7cb..85e4b25c2 100644 --- a/dependency-check-maven/xref-test/overview-summary.html +++ b/dependency-check-maven/xref-test/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference + Dependency-Check Maven Plugin 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Maven Plugin 1.4.3 Reference

      +

      Dependency-Check Maven Plugin 1.4.4 Reference

      diff --git a/dependency-check-maven/xref/allclasses-frame.html b/dependency-check-maven/xref/allclasses-frame.html index e06fbf0ef..effb61c92 100644 --- a/dependency-check-maven/xref/allclasses-frame.html +++ b/dependency-check-maven/xref/allclasses-frame.html @@ -25,18 +25,9 @@
    63. MavenEngine -
    64. -
    65. - MavenLoggerAdapter -
    66. -
    67. - MavenLoggerFactory
    68. PurgeMojo -
    69. -
    70. - StaticLoggerBinder
    71. UpdateMojo diff --git a/dependency-check-maven/xref/index.html b/dependency-check-maven/xref/index.html index 35f4c3952..8afcccc99 100644 --- a/dependency-check-maven/xref/index.html +++ b/dependency-check-maven/xref/index.html @@ -4,7 +4,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference + Dependency-Check Maven Plugin 1.4.4 Reference diff --git a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/AggregateMojo.html b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/AggregateMojo.html index 0614078b2..369acd8be 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/AggregateMojo.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/AggregateMojo.html @@ -131,9 +131,9 @@ 123 exCol.addException(ex); 124 } 125 if (this.isFailOnError()) { -126 throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); +126 throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol); 127 } else { -128 getLog().debug("One or more exceptions occured during dependency-check analysis", exCol); +128 getLog().debug("One or more exceptions occurred during dependency-check analysis", exCol); 129 } 130 } 131 showSummary(this.getProject(), engine.getDependencies()); @@ -248,7 +248,7 @@ 240 if (getLog().isDebugEnabled()) { 241 getLog().debug("Database connection error", ex); 242 } -243 final String msg = "An exception occured connecting to the local database. Please see the log file for more details."; +243 final String msg = "An exception occurred connecting to the local database. Please see the log file for more details."; 244 if (this.isFailOnError()) { 245 throw new MojoExecutionException(msg, ex); 246 } diff --git a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html index a55dc16f6..7cbd85d57 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html @@ -214,1058 +214,1066 @@ 206 */ 207 @Parameter(property = "suppressionFile", defaultValue = "", required = false) 208 private String suppressionFile; -209 /** -210 * Flag indicating whether or not to show a summary in the output. -211 */ -212 @SuppressWarnings("CanBeFinal") -213 @Parameter(property = "showSummary", defaultValue = "true", required = false) -214 private boolean showSummary = true; +209 +210 /** +211 * The path to the hints file. +212 */ +213 @Parameter(property = "hintsFile", defaultValue = "", required = false) +214 private String hintsFile; 215 216 /** -217 * Whether or not the Jar Analyzer is enabled. +217 * Flag indicating whether or not to show a summary in the output. 218 */ -219 @Parameter(property = "jarAnalyzerEnabled", required = false) -220 private Boolean jarAnalyzerEnabled; -221 -222 /** -223 * Whether or not the Archive Analyzer is enabled. -224 */ -225 @Parameter(property = "archiveAnalyzerEnabled", required = false) -226 private Boolean archiveAnalyzerEnabled; -227 -228 /** -229 * Sets whether the Python Distribution Analyzer will be used. -230 */ -231 @Parameter(property = "pyDistributionAnalyzerEnabled", required = false) -232 private Boolean pyDistributionAnalyzerEnabled; -233 /** -234 * Sets whether the Python Package Analyzer will be used. -235 */ -236 @Parameter(property = "pyPackageAnalyzerEnabled", required = false) -237 private Boolean pyPackageAnalyzerEnabled; -238 /** -239 * Sets whether the Ruby Gemspec Analyzer will be used. -240 */ -241 @Parameter(property = "rubygemsAnalyzerEnabled", required = false) -242 private Boolean rubygemsAnalyzerEnabled; -243 /** -244 * Sets whether or not the openssl Analyzer should be used. -245 */ -246 @Parameter(property = "opensslAnalyzerEnabled", required = false) -247 private Boolean opensslAnalyzerEnabled; -248 /** -249 * Sets whether or not the CMake Analyzer should be used. -250 */ -251 @Parameter(property = "cmakeAnalyzerEnabled", required = false) -252 private Boolean cmakeAnalyzerEnabled; -253 /** -254 * Sets whether or not the autoconf Analyzer should be used. -255 */ -256 @Parameter(property = "autoconfAnalyzerEnabled", required = false) -257 private Boolean autoconfAnalyzerEnabled; -258 /** -259 * Sets whether or not the PHP Composer Lock File Analyzer should be used. -260 */ -261 @Parameter(property = "composerAnalyzerEnabled", required = false) -262 private Boolean composerAnalyzerEnabled; -263 /** -264 * Sets whether or not the Node.js Analyzer should be used. -265 */ -266 @Parameter(property = "nodeAnalyzerEnabled", required = false) -267 private Boolean nodeAnalyzerEnabled; -268 -269 /** -270 * Whether or not the .NET Assembly Analyzer is enabled. -271 */ -272 @Parameter(property = "assemblyAnalyzerEnabled", required = false) -273 private Boolean assemblyAnalyzerEnabled; -274 -275 /** -276 * Whether or not the .NET Nuspec Analyzer is enabled. -277 */ -278 @Parameter(property = "nuspecAnalyzerEnabled", required = false) -279 private Boolean nuspecAnalyzerEnabled; -280 -281 /** -282 * Whether or not the Central Analyzer is enabled. -283 */ -284 @Parameter(property = "centralAnalyzerEnabled", required = false) -285 private Boolean centralAnalyzerEnabled; -286 -287 /** -288 * Whether or not the Nexus Analyzer is enabled. -289 */ -290 @Parameter(property = "nexusAnalyzerEnabled", required = false) -291 private Boolean nexusAnalyzerEnabled; -292 -293 /** -294 * The URL of a Nexus server's REST API end point -295 * (http://domain/nexus/service/local). +219 @SuppressWarnings("CanBeFinal") +220 @Parameter(property = "showSummary", defaultValue = "true", required = false) +221 private boolean showSummary = true; +222 +223 /** +224 * Whether or not the Jar Analyzer is enabled. +225 */ +226 @Parameter(property = "jarAnalyzerEnabled", required = false) +227 private Boolean jarAnalyzerEnabled; +228 +229 /** +230 * Whether or not the Archive Analyzer is enabled. +231 */ +232 @Parameter(property = "archiveAnalyzerEnabled", required = false) +233 private Boolean archiveAnalyzerEnabled; +234 +235 /** +236 * Sets whether the Python Distribution Analyzer will be used. +237 */ +238 @Parameter(property = "pyDistributionAnalyzerEnabled", required = false) +239 private Boolean pyDistributionAnalyzerEnabled; +240 /** +241 * Sets whether the Python Package Analyzer will be used. +242 */ +243 @Parameter(property = "pyPackageAnalyzerEnabled", required = false) +244 private Boolean pyPackageAnalyzerEnabled; +245 /** +246 * Sets whether the Ruby Gemspec Analyzer will be used. +247 */ +248 @Parameter(property = "rubygemsAnalyzerEnabled", required = false) +249 private Boolean rubygemsAnalyzerEnabled; +250 /** +251 * Sets whether or not the openssl Analyzer should be used. +252 */ +253 @Parameter(property = "opensslAnalyzerEnabled", required = false) +254 private Boolean opensslAnalyzerEnabled; +255 /** +256 * Sets whether or not the CMake Analyzer should be used. +257 */ +258 @Parameter(property = "cmakeAnalyzerEnabled", required = false) +259 private Boolean cmakeAnalyzerEnabled; +260 /** +261 * Sets whether or not the autoconf Analyzer should be used. +262 */ +263 @Parameter(property = "autoconfAnalyzerEnabled", required = false) +264 private Boolean autoconfAnalyzerEnabled; +265 /** +266 * Sets whether or not the PHP Composer Lock File Analyzer should be used. +267 */ +268 @Parameter(property = "composerAnalyzerEnabled", required = false) +269 private Boolean composerAnalyzerEnabled; +270 /** +271 * Sets whether or not the Node.js Analyzer should be used. +272 */ +273 @Parameter(property = "nodeAnalyzerEnabled", required = false) +274 private Boolean nodeAnalyzerEnabled; +275 +276 /** +277 * Whether or not the .NET Assembly Analyzer is enabled. +278 */ +279 @Parameter(property = "assemblyAnalyzerEnabled", required = false) +280 private Boolean assemblyAnalyzerEnabled; +281 +282 /** +283 * Whether or not the .NET Nuspec Analyzer is enabled. +284 */ +285 @Parameter(property = "nuspecAnalyzerEnabled", required = false) +286 private Boolean nuspecAnalyzerEnabled; +287 +288 /** +289 * Whether or not the Central Analyzer is enabled. +290 */ +291 @Parameter(property = "centralAnalyzerEnabled", required = false) +292 private Boolean centralAnalyzerEnabled; +293 +294 /** +295 * Whether or not the Nexus Analyzer is enabled. 296 */ -297 @Parameter(property = "nexusUrl", required = false) -298 private String nexusUrl; -299 /** -300 * Whether or not the configured proxy is used to connect to Nexus. -301 */ -302 @Parameter(property = "nexusUsesProxy", required = false) -303 private Boolean nexusUsesProxy; -304 /** -305 * The database connection string. -306 */ -307 @Parameter(property = "connectionString", defaultValue = "", required = false) -308 private String connectionString; -309 -310 /** -311 * Returns the connection string. -312 * -313 * @return the connection string -314 */ -315 protected String getConnectionString() { -316 return connectionString; -317 } -318 /** -319 * The database driver name. An example would be org.h2.Driver. -320 */ -321 @Parameter(property = "databaseDriverName", defaultValue = "", required = false) -322 private String databaseDriverName; -323 /** -324 * The path to the database driver if it is not on the class path. -325 */ -326 @Parameter(property = "databaseDriverPath", defaultValue = "", required = false) -327 private String databaseDriverPath; -328 /** -329 * The server id in the settings.xml; used to retrieve encrypted passwords -330 * from the settings.xml. -331 */ -332 @Parameter(property = "serverId", defaultValue = "", required = false) -333 private String serverId; -334 /** -335 * A reference to the settings.xml settings. -336 */ -337 @Parameter(defaultValue = "${settings}", readonly = true, required = true) -338 private org.apache.maven.settings.Settings settingsXml; -339 /** -340 * The security dispatcher that can decrypt passwords in the settings.xml. -341 */ -342 @Component(role = SecDispatcher.class, hint = "default") -343 private SecDispatcher securityDispatcher; -344 /** -345 * The database user name. -346 */ -347 @Parameter(property = "databaseUser", defaultValue = "", required = false) -348 private String databaseUser; -349 /** -350 * The password to use when connecting to the database. -351 */ -352 @Parameter(property = "databasePassword", defaultValue = "", required = false) -353 private String databasePassword; -354 /** -355 * A comma-separated list of file extensions to add to analysis next to jar, -356 * zip, .... -357 */ -358 @Parameter(property = "zipExtensions", required = false) -359 private String zipExtensions; -360 /** -361 * Skip Dependency Check altogether. -362 */ -363 @SuppressWarnings("CanBeFinal") -364 @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false) -365 private boolean skip = false; -366 /** -367 * Skip Analysis for Test Scope Dependencies. -368 */ -369 @SuppressWarnings("CanBeFinal") -370 @Parameter(property = "skipTestScope", defaultValue = "true", required = false) -371 private boolean skipTestScope = true; -372 /** -373 * Skip Analysis for Runtime Scope Dependencies. -374 */ -375 @SuppressWarnings("CanBeFinal") -376 @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false) -377 private boolean skipRuntimeScope = false; -378 /** -379 * Skip Analysis for Provided Scope Dependencies. -380 */ -381 @SuppressWarnings("CanBeFinal") -382 @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false) -383 private boolean skipProvidedScope = false; -384 /** -385 * The data directory, hold DC SQL DB. -386 */ -387 @Parameter(property = "dataDirectory", defaultValue = "", required = false) -388 private String dataDirectory; -389 /** -390 * Data Mirror URL for CVE 1.2. -391 */ -392 @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false) -393 private String cveUrl12Modified; -394 /** -395 * Data Mirror URL for CVE 2.0. -396 */ -397 @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false) -398 private String cveUrl20Modified; -399 /** -400 * Base Data Mirror URL for CVE 1.2. -401 */ -402 @Parameter(property = "cveUrl12Base", defaultValue = "", required = false) -403 private String cveUrl12Base; -404 /** -405 * Data Mirror URL for CVE 2.0. -406 */ -407 @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) -408 private String cveUrl20Base; -409 /** -410 * Optionally skip excessive CVE update checks for a designated duration in -411 * hours. -412 */ -413 @Parameter(property = "cveValidForHours", defaultValue = "", required = false) -414 private Integer cveValidForHours; -415 +297 @Parameter(property = "nexusAnalyzerEnabled", required = false) +298 private Boolean nexusAnalyzerEnabled; +299 +300 /** +301 * The URL of a Nexus server's REST API end point +302 * (http://domain/nexus/service/local). +303 */ +304 @Parameter(property = "nexusUrl", required = false) +305 private String nexusUrl; +306 /** +307 * Whether or not the configured proxy is used to connect to Nexus. +308 */ +309 @Parameter(property = "nexusUsesProxy", required = false) +310 private Boolean nexusUsesProxy; +311 /** +312 * The database connection string. +313 */ +314 @Parameter(property = "connectionString", defaultValue = "", required = false) +315 private String connectionString; +316 +317 /** +318 * Returns the connection string. +319 * +320 * @return the connection string +321 */ +322 protected String getConnectionString() { +323 return connectionString; +324 } +325 /** +326 * The database driver name. An example would be org.h2.Driver. +327 */ +328 @Parameter(property = "databaseDriverName", defaultValue = "", required = false) +329 private String databaseDriverName; +330 /** +331 * The path to the database driver if it is not on the class path. +332 */ +333 @Parameter(property = "databaseDriverPath", defaultValue = "", required = false) +334 private String databaseDriverPath; +335 /** +336 * The server id in the settings.xml; used to retrieve encrypted passwords +337 * from the settings.xml. +338 */ +339 @Parameter(property = "serverId", defaultValue = "", required = false) +340 private String serverId; +341 /** +342 * A reference to the settings.xml settings. +343 */ +344 @Parameter(defaultValue = "${settings}", readonly = true, required = true) +345 private org.apache.maven.settings.Settings settingsXml; +346 /** +347 * The security dispatcher that can decrypt passwords in the settings.xml. +348 */ +349 @Component(role = SecDispatcher.class, hint = "default") +350 private SecDispatcher securityDispatcher; +351 /** +352 * The database user name. +353 */ +354 @Parameter(property = "databaseUser", defaultValue = "", required = false) +355 private String databaseUser; +356 /** +357 * The password to use when connecting to the database. +358 */ +359 @Parameter(property = "databasePassword", defaultValue = "", required = false) +360 private String databasePassword; +361 /** +362 * A comma-separated list of file extensions to add to analysis next to jar, +363 * zip, .... +364 */ +365 @Parameter(property = "zipExtensions", required = false) +366 private String zipExtensions; +367 /** +368 * Skip Dependency Check altogether. +369 */ +370 @SuppressWarnings("CanBeFinal") +371 @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false) +372 private boolean skip = false; +373 /** +374 * Skip Analysis for Test Scope Dependencies. +375 */ +376 @SuppressWarnings("CanBeFinal") +377 @Parameter(property = "skipTestScope", defaultValue = "true", required = false) +378 private boolean skipTestScope = true; +379 /** +380 * Skip Analysis for Runtime Scope Dependencies. +381 */ +382 @SuppressWarnings("CanBeFinal") +383 @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false) +384 private boolean skipRuntimeScope = false; +385 /** +386 * Skip Analysis for Provided Scope Dependencies. +387 */ +388 @SuppressWarnings("CanBeFinal") +389 @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false) +390 private boolean skipProvidedScope = false; +391 /** +392 * The data directory, hold DC SQL DB. +393 */ +394 @Parameter(property = "dataDirectory", defaultValue = "", required = false) +395 private String dataDirectory; +396 /** +397 * Data Mirror URL for CVE 1.2. +398 */ +399 @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false) +400 private String cveUrl12Modified; +401 /** +402 * Data Mirror URL for CVE 2.0. +403 */ +404 @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false) +405 private String cveUrl20Modified; +406 /** +407 * Base Data Mirror URL for CVE 1.2. +408 */ +409 @Parameter(property = "cveUrl12Base", defaultValue = "", required = false) +410 private String cveUrl12Base; +411 /** +412 * Data Mirror URL for CVE 2.0. +413 */ +414 @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) +415 private String cveUrl20Base; 416 /** -417 * The path to mono for .NET Assembly analysis on non-windows systems. -418 */ -419 @Parameter(property = "pathToMono", defaultValue = "", required = false) -420 private String pathToMono; -421 -422 /** -423 * The Proxy URL. -424 * -425 * @deprecated Please use mavenSettings instead -426 */ -427 @SuppressWarnings("CanBeFinal") -428 @Parameter(property = "proxyUrl", defaultValue = "", required = false) -429 @Deprecated -430 private String proxyUrl = null; -431 /** -432 * Sets whether or not the external report format should be used. -433 * -434 * @deprecated the internal report is no longer supported -435 */ -436 @SuppressWarnings("CanBeFinal") -437 @Parameter(property = "externalReport") -438 @Deprecated -439 private String externalReport = null; -440 // </editor-fold> -441 //<editor-fold defaultstate="collapsed" desc="Base Maven implementation"> -442 -443 /** -444 * Executes dependency-check. -445 * -446 * @throws MojoExecutionException thrown if there is an exception executing -447 * the mojo -448 * @throws MojoFailureException thrown if dependency-check failed the build -449 */ -450 @Override -451 public void execute() throws MojoExecutionException, MojoFailureException { -452 generatingSite = false; -453 if (skip) { -454 getLog().info("Skipping " + getName(Locale.US)); -455 } else { -456 validateAggregate(); -457 project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory); -458 runCheck(); -459 } -460 } -461 -462 /** -463 * Checks if the aggregate configuration parameter has been set to true. If -464 * it has a MojoExecutionException is thrown because the aggregate -465 * configuration parameter is no longer supported. -466 * -467 * @throws MojoExecutionException thrown if aggregate is set to true -468 */ -469 private void validateAggregate() throws MojoExecutionException { -470 if (aggregate != null && aggregate) { -471 final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. " -472 + "Please use the aggregate goal instead."; -473 throw new MojoExecutionException(msg); -474 } -475 } -476 -477 /** -478 * Generates the Dependency-Check Site Report. -479 * -480 * @param sink the sink to write the report to -481 * @param locale the locale to use when generating the report -482 * @throws MavenReportException if a maven report exception occurs -483 * @deprecated use -484 * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)} -485 * instead. -486 */ -487 @Override -488 @Deprecated -489 public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException { -490 generate((Sink) sink, locale); -491 } -492 -493 /** -494 * A flag indicating whether or not the maven site is being generated. -495 */ -496 private boolean generatingSite = false; -497 -498 /** -499 * Returns true if the Maven site is being generated. -500 * -501 * @return true if the Maven site is being generated +417 * Optionally skip excessive CVE update checks for a designated duration in +418 * hours. +419 */ +420 @Parameter(property = "cveValidForHours", defaultValue = "", required = false) +421 private Integer cveValidForHours; +422 +423 /** +424 * The path to mono for .NET Assembly analysis on non-windows systems. +425 */ +426 @Parameter(property = "pathToMono", defaultValue = "", required = false) +427 private String pathToMono; +428 +429 /** +430 * The Proxy URL. +431 * +432 * @deprecated Please use mavenSettings instead +433 */ +434 @SuppressWarnings("CanBeFinal") +435 @Parameter(property = "proxyUrl", defaultValue = "", required = false) +436 @Deprecated +437 private String proxyUrl = null; +438 /** +439 * Sets whether or not the external report format should be used. +440 * +441 * @deprecated the internal report is no longer supported +442 */ +443 @SuppressWarnings("CanBeFinal") +444 @Parameter(property = "externalReport") +445 @Deprecated +446 private String externalReport = null; +447 // </editor-fold> +448 //<editor-fold defaultstate="collapsed" desc="Base Maven implementation"> +449 +450 /** +451 * Executes dependency-check. +452 * +453 * @throws MojoExecutionException thrown if there is an exception executing +454 * the mojo +455 * @throws MojoFailureException thrown if dependency-check failed the build +456 */ +457 @Override +458 public void execute() throws MojoExecutionException, MojoFailureException { +459 generatingSite = false; +460 if (skip) { +461 getLog().info("Skipping " + getName(Locale.US)); +462 } else { +463 validateAggregate(); +464 project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory); +465 runCheck(); +466 } +467 } +468 +469 /** +470 * Checks if the aggregate configuration parameter has been set to true. If +471 * it has a MojoExecutionException is thrown because the aggregate +472 * configuration parameter is no longer supported. +473 * +474 * @throws MojoExecutionException thrown if aggregate is set to true +475 */ +476 private void validateAggregate() throws MojoExecutionException { +477 if (aggregate != null && aggregate) { +478 final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. " +479 + "Please use the aggregate goal instead."; +480 throw new MojoExecutionException(msg); +481 } +482 } +483 +484 /** +485 * Generates the Dependency-Check Site Report. +486 * +487 * @param sink the sink to write the report to +488 * @param locale the locale to use when generating the report +489 * @throws MavenReportException if a maven report exception occurs +490 * @deprecated use +491 * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)} +492 * instead. +493 */ +494 @Override +495 @Deprecated +496 public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException { +497 generate((Sink) sink, locale); +498 } +499 +500 /** +501 * A flag indicating whether or not the maven site is being generated. 502 */ -503 protected boolean isGeneratingSite() { -504 return generatingSite; -505 } -506 -507 /** -508 * Generates the Dependency-Check Site Report. -509 * -510 * @param sink the sink to write the report to -511 * @param locale the locale to use when generating the report -512 * @throws MavenReportException if a maven report exception occurs -513 */ -514 public void generate(Sink sink, Locale locale) throws MavenReportException { -515 generatingSite = true; -516 try { -517 validateAggregate(); -518 } catch (MojoExecutionException ex) { -519 throw new MavenReportException(ex.getMessage()); -520 } -521 project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory()); -522 try { -523 runCheck(); -524 } catch (MojoExecutionException ex) { -525 throw new MavenReportException(ex.getMessage(), ex); -526 } catch (MojoFailureException ex) { -527 getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build"); -528 } -529 } -530 -531 /** -532 * Returns the correct output directory depending on if a site is being -533 * executed or not. -534 * -535 * @return the directory to write the report(s) -536 * @throws MojoExecutionException thrown if there is an error loading the -537 * file path -538 */ -539 protected File getCorrectOutputDirectory() throws MojoExecutionException { -540 return getCorrectOutputDirectory(this.project); -541 } -542 -543 /** -544 * Returns the correct output directory depending on if a site is being -545 * executed or not. -546 * -547 * @param current the Maven project to get the output directory from -548 * @return the directory to write the report(s) -549 */ -550 protected File getCorrectOutputDirectory(MavenProject current) { -551 final Object obj = current.getContextValue(getOutputDirectoryContextKey()); -552 if (obj != null && obj instanceof File) { -553 return (File) obj; -554 } -555 File target = new File(current.getBuild().getDirectory()); -556 if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) { -557 target = target.getParentFile(); -558 } -559 return target; -560 } -561 -562 /** -563 * Returns the correct output directory depending on if a site is being -564 * executed or not. -565 * -566 * @param current the Maven project to get the output directory from -567 * @return the directory to write the report(s) -568 */ -569 protected File getDataFile(MavenProject current) { -570 if (getLog().isDebugEnabled()) { -571 getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey())); -572 } -573 final Object obj = current.getContextValue(getDataFileContextKey()); -574 if (obj != null) { -575 if (obj instanceof String) { -576 final File f = new File((String) obj); -577 return f; -578 } -579 } else if (getLog().isDebugEnabled()) { -580 getLog().debug("Context value not found"); -581 } -582 return null; -583 } -584 -585 /** -586 * Scans the project's artifacts and adds them to the engine's dependency -587 * list. -588 * -589 * @param project the project to scan the dependencies of -590 * @param engine the engine to use to scan the dependencies -591 * @return a collection of exceptions that may have occurred while resolving -592 * and scanning the dependencies -593 */ -594 protected ExceptionCollection scanArtifacts(MavenProject project, MavenEngine engine) { -595 // <editor-fold defaultstate="collapsed" desc="old implementation"> -596 /* -597 for (Artifact a : project.getArtifacts()) { -598 if (excludeFromScan(a)) { -599 continue; -600 } -601 final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile()); -602 if (deps != null) { -603 if (deps.size() == 1) { -604 final Dependency d = deps.get(0); -605 if (d != null) { -606 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); -607 d.addAsEvidence("pom", ma, Confidence.HIGHEST); -608 d.addProjectReference(project.getName()); -609 if (getLog().isDebugEnabled()) { -610 getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(), -611 d.getDisplayFileName())); -612 } -613 } -614 } else if (getLog().isDebugEnabled()) { -615 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", -616 a.getGroupId(), a.getArtifactId(), a.getVersion()); -617 getLog().debug(msg); -618 } +503 private boolean generatingSite = false; +504 +505 /** +506 * Returns true if the Maven site is being generated. +507 * +508 * @return true if the Maven site is being generated +509 */ +510 protected boolean isGeneratingSite() { +511 return generatingSite; +512 } +513 +514 /** +515 * Generates the Dependency-Check Site Report. +516 * +517 * @param sink the sink to write the report to +518 * @param locale the locale to use when generating the report +519 * @throws MavenReportException if a maven report exception occurs +520 */ +521 public void generate(Sink sink, Locale locale) throws MavenReportException { +522 generatingSite = true; +523 try { +524 validateAggregate(); +525 } catch (MojoExecutionException ex) { +526 throw new MavenReportException(ex.getMessage()); +527 } +528 project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory()); +529 try { +530 runCheck(); +531 } catch (MojoExecutionException ex) { +532 throw new MavenReportException(ex.getMessage(), ex); +533 } catch (MojoFailureException ex) { +534 getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build"); +535 } +536 } +537 +538 /** +539 * Returns the correct output directory depending on if a site is being +540 * executed or not. +541 * +542 * @return the directory to write the report(s) +543 * @throws MojoExecutionException thrown if there is an error loading the +544 * file path +545 */ +546 protected File getCorrectOutputDirectory() throws MojoExecutionException { +547 return getCorrectOutputDirectory(this.project); +548 } +549 +550 /** +551 * Returns the correct output directory depending on if a site is being +552 * executed or not. +553 * +554 * @param current the Maven project to get the output directory from +555 * @return the directory to write the report(s) +556 */ +557 protected File getCorrectOutputDirectory(MavenProject current) { +558 final Object obj = current.getContextValue(getOutputDirectoryContextKey()); +559 if (obj != null && obj instanceof File) { +560 return (File) obj; +561 } +562 File target = new File(current.getBuild().getDirectory()); +563 if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) { +564 target = target.getParentFile(); +565 } +566 return target; +567 } +568 +569 /** +570 * Returns the correct output directory depending on if a site is being +571 * executed or not. +572 * +573 * @param current the Maven project to get the output directory from +574 * @return the directory to write the report(s) +575 */ +576 protected File getDataFile(MavenProject current) { +577 if (getLog().isDebugEnabled()) { +578 getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey())); +579 } +580 final Object obj = current.getContextValue(getDataFileContextKey()); +581 if (obj != null) { +582 if (obj instanceof String) { +583 final File f = new File((String) obj); +584 return f; +585 } +586 } else if (getLog().isDebugEnabled()) { +587 getLog().debug("Context value not found"); +588 } +589 return null; +590 } +591 +592 /** +593 * Scans the project's artifacts and adds them to the engine's dependency +594 * list. +595 * +596 * @param project the project to scan the dependencies of +597 * @param engine the engine to use to scan the dependencies +598 * @return a collection of exceptions that may have occurred while resolving +599 * and scanning the dependencies +600 */ +601 protected ExceptionCollection scanArtifacts(MavenProject project, MavenEngine engine) { +602 // <editor-fold defaultstate="collapsed" desc="old implementation"> +603 /* +604 for (Artifact a : project.getArtifacts()) { +605 if (excludeFromScan(a)) { +606 continue; +607 } +608 final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile()); +609 if (deps != null) { +610 if (deps.size() == 1) { +611 final Dependency d = deps.get(0); +612 if (d != null) { +613 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); +614 d.addAsEvidence("pom", ma, Confidence.HIGHEST); +615 d.addProjectReference(project.getName()); +616 if (getLog().isDebugEnabled()) { +617 getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(), +618 d.getDisplayFileName())); 619 } 620 } -621 */ -622 // </editor-fold> -623 try { -624 final DependencyNode dn = dependencyGraphBuilder.buildDependencyGraph(project, null, reactorProjects); -625 return collectDependencies(engine, project, dn.getChildren()); -626 } catch (DependencyGraphBuilderException ex) { -627 final String msg = String.format("Unable to build dependency graph on project %s", project.getName()); -628 getLog().debug(msg, ex); -629 return new ExceptionCollection(msg, ex); -630 } -631 } -632 -633 /** -634 * Resolves the projects artifacts using Aether and scans the resulting -635 * dependencies. -636 * -637 * @param engine the core dependency-check engine -638 * @param project the project being scanned -639 * @param nodes the list of dependency nodes, generally obtained via the -640 * DependencyGraphBuilder -641 * @return a collection of exceptions that may have occurred while resolving -642 * and scanning the dependencies -643 */ -644 private ExceptionCollection collectDependencies(MavenEngine engine, MavenProject project, List<DependencyNode> nodes) { -645 ExceptionCollection exCol = null; -646 for (DependencyNode dependencyNode : nodes) { -647 exCol = collectDependencies(engine, project, dependencyNode.getChildren()); -648 if (excludeFromScan(dependencyNode.getArtifact().getScope())) { -649 continue; -650 } -651 final ArtifactRequest request = new ArtifactRequest(); -652 request.setArtifact(new DefaultArtifact(dependencyNode.getArtifact().getId())); -653 request.setRepositories(remoteRepos); -654 try { -655 final ArtifactResult result = repoSystem.resolveArtifact(repoSession, request); -656 if (result.isResolved() && result.getArtifact() != null && result.getArtifact().getFile() != null) { -657 final List<Dependency> deps = engine.scan(result.getArtifact().getFile().getAbsoluteFile()); -658 if (deps != null) { -659 if (deps.size() == 1) { -660 final Dependency d = deps.get(0); -661 if (d != null) { -662 final Artifact a = result.getArtifact(); -663 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); -664 d.addAsEvidence("pom", ma, Confidence.HIGHEST); -665 d.addProjectReference(project.getName() + ":" + dependencyNode.getArtifact().getScope()); -666 if (getLog().isDebugEnabled()) { -667 getLog().debug(String.format("Adding project reference %s on dependency %s", -668 project.getName(), d.getDisplayFileName())); -669 } -670 } -671 } else if (getLog().isDebugEnabled()) { -672 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s' in project %s", -673 dependencyNode.getArtifact().getId(), project.getName()); -674 getLog().debug(msg); -675 } -676 } else { -677 final String msg = String.format("Error resolving '%s' in project %s", -678 dependencyNode.getArtifact().getId(), project.getName()); -679 if (exCol == null) { -680 exCol = new ExceptionCollection(); -681 } -682 getLog().error(msg); -683 for (Exception ex : result.getExceptions()) { -684 exCol.addException(ex); -685 } -686 } -687 } else { -688 final String msg = String.format("Unable to resolve '%s' in project %s", -689 dependencyNode.getArtifact().getId(), project.getName()); -690 getLog().debug(msg); -691 if (exCol == null) { -692 exCol = new ExceptionCollection(); +621 } else if (getLog().isDebugEnabled()) { +622 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", +623 a.getGroupId(), a.getArtifactId(), a.getVersion()); +624 getLog().debug(msg); +625 } +626 } +627 } +628 */ +629 // </editor-fold> +630 try { +631 final DependencyNode dn = dependencyGraphBuilder.buildDependencyGraph(project, null, reactorProjects); +632 return collectDependencies(engine, project, dn.getChildren()); +633 } catch (DependencyGraphBuilderException ex) { +634 final String msg = String.format("Unable to build dependency graph on project %s", project.getName()); +635 getLog().debug(msg, ex); +636 return new ExceptionCollection(msg, ex); +637 } +638 } +639 +640 /** +641 * Resolves the projects artifacts using Aether and scans the resulting +642 * dependencies. +643 * +644 * @param engine the core dependency-check engine +645 * @param project the project being scanned +646 * @param nodes the list of dependency nodes, generally obtained via the +647 * DependencyGraphBuilder +648 * @return a collection of exceptions that may have occurred while resolving +649 * and scanning the dependencies +650 */ +651 private ExceptionCollection collectDependencies(MavenEngine engine, MavenProject project, List<DependencyNode> nodes) { +652 ExceptionCollection exCol = null; +653 for (DependencyNode dependencyNode : nodes) { +654 exCol = collectDependencies(engine, project, dependencyNode.getChildren()); +655 if (excludeFromScan(dependencyNode.getArtifact().getScope())) { +656 continue; +657 } +658 final ArtifactRequest request = new ArtifactRequest(); +659 request.setArtifact(new DefaultArtifact(dependencyNode.getArtifact().getId())); +660 request.setRepositories(remoteRepos); +661 try { +662 final ArtifactResult result = repoSystem.resolveArtifact(repoSession, request); +663 if (result.isResolved() && result.getArtifact() != null && result.getArtifact().getFile() != null) { +664 final List<Dependency> deps = engine.scan(result.getArtifact().getFile().getAbsoluteFile(), +665 project.getName() + ":" + dependencyNode.getArtifact().getScope()); +666 if (deps != null) { +667 if (deps.size() == 1) { +668 final Dependency d = deps.get(0); +669 if (d != null) { +670 final Artifact a = result.getArtifact(); +671 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); +672 d.addAsEvidence("pom", ma, Confidence.HIGHEST); +673 if (getLog().isDebugEnabled()) { +674 getLog().debug(String.format("Adding project reference %s on dependency %s", +675 project.getName(), d.getDisplayFileName())); +676 } +677 } +678 } else if (getLog().isDebugEnabled()) { +679 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s' in project %s", +680 dependencyNode.getArtifact().getId(), project.getName()); +681 getLog().debug(msg); +682 } +683 } else { +684 final String msg = String.format("Error resolving '%s' in project %s", +685 dependencyNode.getArtifact().getId(), project.getName()); +686 if (exCol == null) { +687 exCol = new ExceptionCollection(); +688 } +689 getLog().error(msg); +690 for (Exception ex : result.getExceptions()) { +691 exCol.addException(ex); +692 } 693 } -694 for (Exception ex : result.getExceptions()) { -695 exCol.addException(ex); -696 } -697 } -698 } catch (ArtifactResolutionException ex) { -699 if (exCol == null) { -700 exCol = new ExceptionCollection(); -701 } -702 exCol.addException(ex); -703 } -704 } -705 return exCol; -706 } -707 -708 /** -709 * Executes the dependency-check scan and generates the necassary report. -710 * -711 * @throws MojoExecutionException thrown if there is an exception running -712 * the scan -713 * @throws MojoFailureException thrown if dependency-check is configured to -714 * fail the build -715 */ -716 public abstract void runCheck() throws MojoExecutionException, MojoFailureException; -717 -718 /** -719 * Sets the Reporting output directory. -720 * -721 * @param directory the output directory +694 } else { +695 final String msg = String.format("Unable to resolve '%s' in project %s", +696 dependencyNode.getArtifact().getId(), project.getName()); +697 getLog().debug(msg); +698 if (exCol == null) { +699 exCol = new ExceptionCollection(); +700 } +701 for (Exception ex : result.getExceptions()) { +702 exCol.addException(ex); +703 } +704 } +705 } catch (ArtifactResolutionException ex) { +706 if (exCol == null) { +707 exCol = new ExceptionCollection(); +708 } +709 exCol.addException(ex); +710 } +711 } +712 return exCol; +713 } +714 +715 /** +716 * Executes the dependency-check scan and generates the necassary report. +717 * +718 * @throws MojoExecutionException thrown if there is an exception running +719 * the scan +720 * @throws MojoFailureException thrown if dependency-check is configured to +721 * fail the build 722 */ -723 @Override -724 public void setReportOutputDirectory(File directory) { -725 reportOutputDirectory = directory; -726 } -727 -728 /** -729 * Returns the report output directory. -730 * -731 * @return the report output directory -732 */ -733 @Override -734 public File getReportOutputDirectory() { -735 return reportOutputDirectory; -736 } -737 -738 /** -739 * Returns the output directory. -740 * -741 * @return the output directory -742 */ -743 public File getOutputDirectory() { -744 return outputDirectory; -745 } -746 -747 /** -748 * Returns whether this is an external report. This method always returns -749 * true. -750 * -751 * @return <code>true</code> -752 */ -753 @Override -754 public final boolean isExternalReport() { -755 return true; -756 } -757 -758 /** -759 * Returns the output name. -760 * -761 * @return the output name -762 */ -763 @Override -764 public String getOutputName() { -765 if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) { -766 return "dependency-check-report"; -767 } else if ("XML".equalsIgnoreCase(this.format)) { -768 return "dependency-check-report.xml#"; -769 } else if ("VULN".equalsIgnoreCase(this.format)) { -770 return "dependency-check-vulnerability"; -771 } else { -772 getLog().warn("Unknown report format used during site generation."); +723 public abstract void runCheck() throws MojoExecutionException, MojoFailureException; +724 +725 /** +726 * Sets the Reporting output directory. +727 * +728 * @param directory the output directory +729 */ +730 @Override +731 public void setReportOutputDirectory(File directory) { +732 reportOutputDirectory = directory; +733 } +734 +735 /** +736 * Returns the report output directory. +737 * +738 * @return the report output directory +739 */ +740 @Override +741 public File getReportOutputDirectory() { +742 return reportOutputDirectory; +743 } +744 +745 /** +746 * Returns the output directory. +747 * +748 * @return the output directory +749 */ +750 public File getOutputDirectory() { +751 return outputDirectory; +752 } +753 +754 /** +755 * Returns whether this is an external report. This method always returns +756 * true. +757 * +758 * @return <code>true</code> +759 */ +760 @Override +761 public final boolean isExternalReport() { +762 return true; +763 } +764 +765 /** +766 * Returns the output name. +767 * +768 * @return the output name +769 */ +770 @Override +771 public String getOutputName() { +772 if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) { 773 return "dependency-check-report"; -774 } -775 } -776 -777 /** -778 * Returns the category name. -779 * -780 * @return the category name -781 */ -782 @Override -783 public String getCategoryName() { -784 return MavenReport.CATEGORY_PROJECT_REPORTS; -785 } -786 //</editor-fold> -787 -788 /** -789 * Initializes a new <code>MavenEngine</code> that can be used for scanning. -790 * -791 * @return a newly instantiated <code>MavenEngine</code> -792 * @throws DatabaseException thrown if there is a database exception -793 */ -794 protected MavenEngine initializeEngine() throws DatabaseException { -795 populateSettings(); -796 return new MavenEngine(this.project, this.reactorProjects); -797 } -798 -799 /** -800 * Takes the properties supplied and updates the dependency-check settings. -801 * Additionally, this sets the system properties required to change the -802 * proxy url, port, and connection timeout. -803 */ -804 protected void populateSettings() { -805 Settings.initialize(); -806 InputStream mojoProperties = null; -807 try { -808 mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); -809 Settings.mergeProperties(mojoProperties); -810 } catch (IOException ex) { -811 getLog().warn("Unable to load the dependency-check ant task.properties file."); -812 if (getLog().isDebugEnabled()) { -813 getLog().debug("", ex); -814 } -815 } finally { -816 if (mojoProperties != null) { -817 try { -818 mojoProperties.close(); -819 } catch (IOException ex) { -820 if (getLog().isDebugEnabled()) { -821 getLog().debug("", ex); -822 } -823 } -824 } -825 } -826 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); -827 -828 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); -829 -830 if (externalReport != null) { -831 getLog().warn("The 'externalReport' option was set; this configuration option has been removed. " -832 + "Please update the dependency-check-maven plugin's configuration"); -833 } +774 } else if ("XML".equalsIgnoreCase(this.format)) { +775 return "dependency-check-report.xml#"; +776 } else if ("VULN".equalsIgnoreCase(this.format)) { +777 return "dependency-check-vulnerability"; +778 } else { +779 getLog().warn("Unknown report format used during site generation."); +780 return "dependency-check-report"; +781 } +782 } +783 +784 /** +785 * Returns the category name. +786 * +787 * @return the category name +788 */ +789 @Override +790 public String getCategoryName() { +791 return MavenReport.CATEGORY_PROJECT_REPORTS; +792 } +793 //</editor-fold> +794 +795 /** +796 * Initializes a new <code>MavenEngine</code> that can be used for scanning. +797 * +798 * @return a newly instantiated <code>MavenEngine</code> +799 * @throws DatabaseException thrown if there is a database exception +800 */ +801 protected MavenEngine initializeEngine() throws DatabaseException { +802 populateSettings(); +803 return new MavenEngine(this.project, this.reactorProjects); +804 } +805 +806 /** +807 * Takes the properties supplied and updates the dependency-check settings. +808 * Additionally, this sets the system properties required to change the +809 * proxy url, port, and connection timeout. +810 */ +811 protected void populateSettings() { +812 Settings.initialize(); +813 InputStream mojoProperties = null; +814 try { +815 mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); +816 Settings.mergeProperties(mojoProperties); +817 } catch (IOException ex) { +818 getLog().warn("Unable to load the dependency-check ant task.properties file."); +819 if (getLog().isDebugEnabled()) { +820 getLog().debug("", ex); +821 } +822 } finally { +823 if (mojoProperties != null) { +824 try { +825 mojoProperties.close(); +826 } catch (IOException ex) { +827 if (getLog().isDebugEnabled()) { +828 getLog().debug("", ex); +829 } +830 } +831 } +832 } +833 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); 834 -835 if (proxyUrl != null && !proxyUrl.isEmpty()) { -836 getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead"); -837 } -838 final Proxy proxy = getMavenProxy(); -839 if (proxy != null) { -840 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost()); -841 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort())); -842 final String userName = proxy.getUsername(); -843 final String password = proxy.getPassword(); -844 Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName); -845 Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password); -846 Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts()); -847 } -848 -849 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); -850 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); -851 -852 //File Type Analyzer Settings -853 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); -854 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); -855 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); -856 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); -857 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); -858 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); -859 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); -860 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); -861 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); -862 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); -863 -864 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); -865 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); -866 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); -867 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); -868 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); -869 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); -870 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); -871 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); -872 -873 //Database configuration -874 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); -875 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); -876 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); -877 -878 if (databaseUser == null && databasePassword == null && serverId != null) { -879 final Server server = settingsXml.getServer(serverId); -880 if (server != null) { -881 databaseUser = server.getUsername(); -882 try { -883 //The following fix was copied from: -884 // https://github.com/bsorrentino/maven-confluence-plugin/blob/master/maven-confluence-reporting-plugin/src/main/java/org/bsc/maven/confluence/plugin/AbstractBaseConfluenceMojo.java -885 // -886 // FIX to resolve -887 // org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: -888 // java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory) -889 // -890 if (securityDispatcher instanceof DefaultSecDispatcher) { -891 ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml"); -892 } -893 -894 databasePassword = securityDispatcher.decrypt(server.getPassword()); -895 } catch (SecDispatcherException ex) { -896 if (ex.getCause() instanceof FileNotFoundException -897 || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) { -898 //maybe its not encrypted? -899 final String tmp = server.getPassword(); -900 if (tmp.startsWith("{") && tmp.endsWith("}")) { -901 getLog().error(String.format( -902 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", -903 serverId, ex.getMessage())); -904 } else { -905 databasePassword = tmp; -906 } -907 } else { -908 getLog().error(String.format( -909 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", -910 serverId, ex.getMessage())); -911 } -912 } -913 } else { -914 getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId)); -915 } -916 } -917 -918 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); -919 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); -920 Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory); -921 -922 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); -923 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); -924 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); -925 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); -926 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); -927 -928 } +835 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); +836 +837 if (externalReport != null) { +838 getLog().warn("The 'externalReport' option was set; this configuration option has been removed. " +839 + "Please update the dependency-check-maven plugin's configuration"); +840 } +841 +842 if (proxyUrl != null && !proxyUrl.isEmpty()) { +843 getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead"); +844 } +845 final Proxy proxy = getMavenProxy(); +846 if (proxy != null) { +847 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost()); +848 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort())); +849 final String userName = proxy.getUsername(); +850 final String password = proxy.getPassword(); +851 Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName); +852 Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password); +853 Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts()); +854 } +855 +856 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); +857 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); +858 Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile); +859 +860 //File Type Analyzer Settings +861 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); +862 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); +863 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); +864 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); +865 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); +866 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); +867 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); +868 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); +869 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); +870 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); +871 +872 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); +873 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); +874 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); +875 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); +876 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); +877 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); +878 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); +879 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); +880 +881 //Database configuration +882 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); +883 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); +884 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); +885 +886 if (databaseUser == null && databasePassword == null && serverId != null) { +887 final Server server = settingsXml.getServer(serverId); +888 if (server != null) { +889 databaseUser = server.getUsername(); +890 try { +891 //The following fix was copied from: +892 // https://github.com/bsorrentino/maven-confluence-plugin/blob/master/maven-confluence-reporting-plugin/src/main/java/org/bsc/maven/confluence/plugin/AbstractBaseConfluenceMojo.java +893 // +894 // FIX to resolve +895 // org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: +896 // java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory) +897 // +898 if (securityDispatcher instanceof DefaultSecDispatcher) { +899 ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml"); +900 } +901 +902 databasePassword = securityDispatcher.decrypt(server.getPassword()); +903 } catch (SecDispatcherException ex) { +904 if (ex.getCause() instanceof FileNotFoundException +905 || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) { +906 //maybe its not encrypted? +907 final String tmp = server.getPassword(); +908 if (tmp.startsWith("{") && tmp.endsWith("}")) { +909 getLog().error(String.format( +910 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", +911 serverId, ex.getMessage())); +912 } else { +913 databasePassword = tmp; +914 } +915 } else { +916 getLog().error(String.format( +917 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", +918 serverId, ex.getMessage())); +919 } +920 } +921 } else { +922 getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId)); +923 } +924 } +925 +926 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); +927 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); +928 Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory); 929 -930 /** -931 * Returns the maven proxy. -932 * -933 * @return the maven proxy -934 */ -935 private Proxy getMavenProxy() { -936 if (mavenSettings != null) { -937 final List<Proxy> proxies = mavenSettings.getProxies(); -938 if (proxies != null && !proxies.isEmpty()) { -939 if (mavenSettingsProxyId != null) { -940 for (Proxy proxy : proxies) { -941 if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) { -942 return proxy; -943 } -944 } -945 } else if (proxies.size() == 1) { -946 return proxies.get(0); -947 } else { -948 getLog().warn("Multiple proxy definitions exist in the Maven settings. In the dependency-check " -949 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used."); -950 throw new IllegalStateException("Ambiguous proxy definition"); -951 } -952 } -953 } -954 return null; -955 } -956 -957 /** -958 * Tests is the artifact should be included in the scan (i.e. is the -959 * dependency in a scope that is being scanned). -960 * -961 * @param scope the scope of the artifact to test -962 * @return <code>true</code> if the artifact is in an excluded scope; -963 * otherwise <code>false</code> -964 */ -965 protected boolean excludeFromScan(String scope) { -966 if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) { -967 return true; -968 } -969 if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) { -970 return true; -971 } -972 if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) { -973 return true; -974 } -975 return false; -976 } -977 -978 /** -979 * Returns a reference to the current project. This method is used instead -980 * of auto-binding the project via component annotation in concrete -981 * implementations of this. If the child has a -982 * <code>@Component MavenProject project;</code> defined then the abstract -983 * class (i.e. this class) will not have access to the current project (just -984 * the way Maven works with the binding). -985 * -986 * @return returns a reference to the current project -987 */ -988 protected MavenProject getProject() { -989 return project; -990 } -991 -992 /** -993 * Returns the list of Maven Projects in this build. -994 * -995 * @return the list of Maven Projects in this build -996 */ -997 protected List<MavenProject> getReactorProjects() { -998 return reactorProjects; -999 } -1000 -1001 /** -1002 * Returns the report format. -1003 * -1004 * @return the report format -1005 */ -1006 protected String getFormat() { -1007 return format; -1008 } -1009 -1010 /** -1011 * Generates the reports for a given dependency-check engine. -1012 * -1013 * @param engine a dependency-check engine -1014 * @param p the Maven project -1015 * @param outputDir the directory path to write the report(s) -1016 * @throws ReportException thrown if there is an error writing the report -1017 */ -1018 protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException { -1019 DatabaseProperties prop = null; -1020 CveDB cve = null; -1021 try { -1022 cve = new CveDB(); -1023 cve.open(); -1024 prop = cve.getDatabaseProperties(); -1025 } catch (DatabaseException ex) { -1026 if (getLog().isDebugEnabled()) { -1027 getLog().debug("Unable to retrieve DB Properties", ex); -1028 } -1029 } finally { -1030 if (cve != null) { -1031 cve.close(); -1032 } -1033 } -1034 final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop); -1035 try { -1036 r.generateReports(outputDir.getAbsolutePath(), format); -1037 } catch (ReportException ex) { -1038 final String msg = String.format("Error generating the report for %s", p.getName()); -1039 throw new ReportException(msg, ex); -1040 } -1041 -1042 } -1043 -1044 //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary"> -1045 /** -1046 * Checks to see if a vulnerability has been identified with a CVSS score -1047 * that is above the threshold set in the configuration. -1048 * -1049 * @param dependencies the list of dependency objects -1050 * @throws MojoFailureException thrown if a CVSS score is found that is -1051 * higher then the threshold set -1052 */ -1053 protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException { -1054 if (failBuildOnCVSS <= 10) { -1055 final StringBuilder ids = new StringBuilder(); -1056 for (Dependency d : dependencies) { -1057 boolean addName = true; -1058 for (Vulnerability v : d.getVulnerabilities()) { -1059 if (v.getCvssScore() >= failBuildOnCVSS) { -1060 if (addName) { -1061 addName = false; -1062 ids.append(NEW_LINE).append(d.getFileName()).append(": "); -1063 ids.append(v.getName()); -1064 } else { -1065 ids.append(", ").append(v.getName()); -1066 } -1067 } -1068 } -1069 } -1070 if (ids.length() > 0) { -1071 final String msg = String.format("%n%nDependency-Check Failure:%n" -1072 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" -1073 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); -1074 throw new MojoFailureException(msg); -1075 } -1076 } -1077 } -1078 -1079 /** -1080 * Generates a warning message listing a summary of dependencies and their -1081 * associated CPE and CVE entries. -1082 * -1083 * @param mp the Maven project for which the summary is shown -1084 * @param dependencies a list of dependency objects -1085 */ -1086 protected void showSummary(MavenProject mp, List<Dependency> dependencies) { -1087 if (showSummary) { -1088 final StringBuilder summary = new StringBuilder(); -1089 for (Dependency d : dependencies) { -1090 boolean firstEntry = true; -1091 final StringBuilder ids = new StringBuilder(); -1092 for (Vulnerability v : d.getVulnerabilities()) { -1093 if (firstEntry) { -1094 firstEntry = false; -1095 } else { -1096 ids.append(", "); -1097 } -1098 ids.append(v.getName()); -1099 } -1100 if (ids.length() > 0) { -1101 summary.append(d.getFileName()).append(" ("); -1102 firstEntry = true; -1103 for (Identifier id : d.getIdentifiers()) { -1104 if (firstEntry) { -1105 firstEntry = false; -1106 } else { -1107 summary.append(", "); -1108 } -1109 summary.append(id.getValue()); -1110 } -1111 summary.append(") : ").append(ids).append(NEW_LINE); -1112 } -1113 } -1114 if (summary.length() > 0) { -1115 final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s" -1116 + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString()); -1117 getLog().warn(msg); -1118 } -1119 } -1120 } -1121 -1122 //</editor-fold> -1123 //<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file"> -1124 /** -1125 * Returns the key used to store the path to the data file that is saved by -1126 * <code>writeDataFile()</code>. This key is used in the -1127 * <code>MavenProject.(set|get)ContextValue</code>. -1128 * -1129 * @return the key used to store the path to the data file -1130 */ -1131 protected String getDataFileContextKey() { -1132 return "dependency-check-path-" + dataFileName; -1133 } -1134 -1135 /** -1136 * Returns the key used to store the path to the output directory. When -1137 * generating the report in the <code>executeAggregateReport()</code> the -1138 * output directory should be obtained by using this key. -1139 * -1140 * @return the key used to store the path to the output directory -1141 */ -1142 protected String getOutputDirectoryContextKey() { -1143 return "dependency-output-dir-" + dataFileName; -1144 } -1145 -1146 /** -1147 * Writes the scan data to disk. This is used to serialize the scan data -1148 * between the "check" and "aggregate" phase. -1149 * -1150 * @param mp the mMven project for which the data file was created -1151 * @param writeTo the directory to write the data file -1152 * @param dependencies the list of dependencies to serialize -1153 */ -1154 protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) { -1155 File file; -1156 //check to see if this was already written out -1157 if (mp.getContextValue(this.getDataFileContextKey()) == null) { -1158 if (writeTo == null) { -1159 file = new File(mp.getBuild().getDirectory()); -1160 file = new File(file, dataFileName); -1161 } else { -1162 file = new File(writeTo, dataFileName); -1163 } -1164 final File parent = file.getParentFile(); -1165 if (!parent.isDirectory() && !parent.mkdirs()) { -1166 getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.", -1167 parent.getAbsolutePath())); -1168 } -1169 -1170 ObjectOutputStream out = null; -1171 try { -1172 if (dependencies != null) { -1173 out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); -1174 out.writeObject(dependencies); -1175 } -1176 if (getLog().isDebugEnabled()) { -1177 getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s", -1178 file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey())); -1179 } -1180 mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath()); -1181 } catch (IOException ex) { -1182 getLog().warn("Unable to create data file used for report aggregation; " -1183 + "if report aggregation is being used the results may be incomplete."); +930 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); +931 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); +932 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); +933 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); +934 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); +935 +936 } +937 +938 /** +939 * Returns the maven proxy. +940 * +941 * @return the maven proxy +942 */ +943 private Proxy getMavenProxy() { +944 if (mavenSettings != null) { +945 final List<Proxy> proxies = mavenSettings.getProxies(); +946 if (proxies != null && !proxies.isEmpty()) { +947 if (mavenSettingsProxyId != null) { +948 for (Proxy proxy : proxies) { +949 if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) { +950 return proxy; +951 } +952 } +953 } else if (proxies.size() == 1) { +954 return proxies.get(0); +955 } else { +956 getLog().warn("Multiple proxy definitions exist in the Maven settings. In the dependency-check " +957 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used."); +958 throw new IllegalStateException("Ambiguous proxy definition"); +959 } +960 } +961 } +962 return null; +963 } +964 +965 /** +966 * Tests is the artifact should be included in the scan (i.e. is the +967 * dependency in a scope that is being scanned). +968 * +969 * @param scope the scope of the artifact to test +970 * @return <code>true</code> if the artifact is in an excluded scope; +971 * otherwise <code>false</code> +972 */ +973 protected boolean excludeFromScan(String scope) { +974 if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) { +975 return true; +976 } +977 if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) { +978 return true; +979 } +980 if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) { +981 return true; +982 } +983 return false; +984 } +985 +986 /** +987 * Returns a reference to the current project. This method is used instead +988 * of auto-binding the project via component annotation in concrete +989 * implementations of this. If the child has a +990 * <code>@Component MavenProject project;</code> defined then the abstract +991 * class (i.e. this class) will not have access to the current project (just +992 * the way Maven works with the binding). +993 * +994 * @return returns a reference to the current project +995 */ +996 protected MavenProject getProject() { +997 return project; +998 } +999 +1000 /** +1001 * Returns the list of Maven Projects in this build. +1002 * +1003 * @return the list of Maven Projects in this build +1004 */ +1005 protected List<MavenProject> getReactorProjects() { +1006 return reactorProjects; +1007 } +1008 +1009 /** +1010 * Returns the report format. +1011 * +1012 * @return the report format +1013 */ +1014 protected String getFormat() { +1015 return format; +1016 } +1017 +1018 /** +1019 * Generates the reports for a given dependency-check engine. +1020 * +1021 * @param engine a dependency-check engine +1022 * @param p the Maven project +1023 * @param outputDir the directory path to write the report(s) +1024 * @throws ReportException thrown if there is an error writing the report +1025 */ +1026 protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException { +1027 DatabaseProperties prop = null; +1028 CveDB cve = null; +1029 try { +1030 cve = new CveDB(); +1031 cve.open(); +1032 prop = cve.getDatabaseProperties(); +1033 } catch (DatabaseException ex) { +1034 if (getLog().isDebugEnabled()) { +1035 getLog().debug("Unable to retrieve DB Properties", ex); +1036 } +1037 } finally { +1038 if (cve != null) { +1039 cve.close(); +1040 } +1041 } +1042 final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop); +1043 try { +1044 r.generateReports(outputDir.getAbsolutePath(), format); +1045 } catch (ReportException ex) { +1046 final String msg = String.format("Error generating the report for %s", p.getName()); +1047 throw new ReportException(msg, ex); +1048 } +1049 +1050 } +1051 +1052 //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary"> +1053 /** +1054 * Checks to see if a vulnerability has been identified with a CVSS score +1055 * that is above the threshold set in the configuration. +1056 * +1057 * @param dependencies the list of dependency objects +1058 * @throws MojoFailureException thrown if a CVSS score is found that is +1059 * higher then the threshold set +1060 */ +1061 protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException { +1062 if (failBuildOnCVSS <= 10) { +1063 final StringBuilder ids = new StringBuilder(); +1064 for (Dependency d : dependencies) { +1065 boolean addName = true; +1066 for (Vulnerability v : d.getVulnerabilities()) { +1067 if (v.getCvssScore() >= failBuildOnCVSS) { +1068 if (addName) { +1069 addName = false; +1070 ids.append(NEW_LINE).append(d.getFileName()).append(": "); +1071 ids.append(v.getName()); +1072 } else { +1073 ids.append(", ").append(v.getName()); +1074 } +1075 } +1076 } +1077 } +1078 if (ids.length() > 0) { +1079 final String msg = String.format("%n%nDependency-Check Failure:%n" +1080 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" +1081 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); +1082 throw new MojoFailureException(msg); +1083 } +1084 } +1085 } +1086 +1087 /** +1088 * Generates a warning message listing a summary of dependencies and their +1089 * associated CPE and CVE entries. +1090 * +1091 * @param mp the Maven project for which the summary is shown +1092 * @param dependencies a list of dependency objects +1093 */ +1094 protected void showSummary(MavenProject mp, List<Dependency> dependencies) { +1095 if (showSummary) { +1096 final StringBuilder summary = new StringBuilder(); +1097 for (Dependency d : dependencies) { +1098 boolean firstEntry = true; +1099 final StringBuilder ids = new StringBuilder(); +1100 for (Vulnerability v : d.getVulnerabilities()) { +1101 if (firstEntry) { +1102 firstEntry = false; +1103 } else { +1104 ids.append(", "); +1105 } +1106 ids.append(v.getName()); +1107 } +1108 if (ids.length() > 0) { +1109 summary.append(d.getFileName()).append(" ("); +1110 firstEntry = true; +1111 for (Identifier id : d.getIdentifiers()) { +1112 if (firstEntry) { +1113 firstEntry = false; +1114 } else { +1115 summary.append(", "); +1116 } +1117 summary.append(id.getValue()); +1118 } +1119 summary.append(") : ").append(ids).append(NEW_LINE); +1120 } +1121 } +1122 if (summary.length() > 0) { +1123 final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s" +1124 + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString()); +1125 getLog().warn(msg); +1126 } +1127 } +1128 } +1129 +1130 //</editor-fold> +1131 //<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file"> +1132 /** +1133 * Returns the key used to store the path to the data file that is saved by +1134 * <code>writeDataFile()</code>. This key is used in the +1135 * <code>MavenProject.(set|get)ContextValue</code>. +1136 * +1137 * @return the key used to store the path to the data file +1138 */ +1139 protected String getDataFileContextKey() { +1140 return "dependency-check-path-" + dataFileName; +1141 } +1142 +1143 /** +1144 * Returns the key used to store the path to the output directory. When +1145 * generating the report in the <code>executeAggregateReport()</code> the +1146 * output directory should be obtained by using this key. +1147 * +1148 * @return the key used to store the path to the output directory +1149 */ +1150 protected String getOutputDirectoryContextKey() { +1151 return "dependency-output-dir-" + dataFileName; +1152 } +1153 +1154 /** +1155 * Writes the scan data to disk. This is used to serialize the scan data +1156 * between the "check" and "aggregate" phase. +1157 * +1158 * @param mp the mMven project for which the data file was created +1159 * @param writeTo the directory to write the data file +1160 * @param dependencies the list of dependencies to serialize +1161 */ +1162 protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) { +1163 File file; +1164 //check to see if this was already written out +1165 if (mp.getContextValue(this.getDataFileContextKey()) == null) { +1166 if (writeTo == null) { +1167 file = new File(mp.getBuild().getDirectory()); +1168 file = new File(file, dataFileName); +1169 } else { +1170 file = new File(writeTo, dataFileName); +1171 } +1172 final File parent = file.getParentFile(); +1173 if (!parent.isDirectory() && !parent.mkdirs()) { +1174 getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.", +1175 parent.getAbsolutePath())); +1176 } +1177 +1178 ObjectOutputStream out = null; +1179 try { +1180 if (dependencies != null) { +1181 out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); +1182 out.writeObject(dependencies); +1183 } 1184 if (getLog().isDebugEnabled()) { -1185 getLog().debug(ex.getMessage(), ex); -1186 } -1187 } finally { -1188 if (out != null) { -1189 try { -1190 out.close(); -1191 } catch (IOException ex) { -1192 if (getLog().isDebugEnabled()) { -1193 getLog().debug("ignore", ex); -1194 } -1195 } -1196 } -1197 } -1198 } -1199 } -1200 -1201 /** -1202 * Reads the serialized scan data from disk. This is used to serialize the -1203 * scan data between the "check" and "aggregate" phase. -1204 * -1205 * @param project the Maven project to read the data file from -1206 * @return a <code>MavenEngine</code> object populated with dependencies if -1207 * the serialized data file exists; otherwise <code>null</code> is returned -1208 */ -1209 protected List<Dependency> readDataFile(MavenProject project) { -1210 final Object oPath = project.getContextValue(this.getDataFileContextKey()); -1211 if (oPath == null) { -1212 return null; -1213 } -1214 List<Dependency> ret = null; -1215 final String path = (String) oPath; -1216 //ObjectInputStream ois = null; -1217 ExpectedOjectInputStream ois = null; -1218 try { -1219 //ois = new ObjectInputStream(new FileInputStream(path)); -1220 ois = new ExpectedOjectInputStream(new FileInputStream(path), -1221 "java.util.ArrayList", -1222 "java.util.HashSet", -1223 "java.util.TreeSet", -1224 "java.lang.AbstractSet", -1225 "java.lang.AbstractCollection", -1226 "java.lang.Enum", -1227 "org.owasp.dependencycheck.dependency.Confidence", -1228 "org.owasp.dependencycheck.dependency.Dependency", -1229 "org.owasp.dependencycheck.dependency.Evidence", -1230 "org.owasp.dependencycheck.dependency.EvidenceCollection", -1231 "org.owasp.dependencycheck.dependency.Identifier", -1232 "org.owasp.dependencycheck.dependency.Reference", -1233 "org.owasp.dependencycheck.dependency.Vulnerability", -1234 "org.owasp.dependencycheck.dependency.VulnerabilityComparator", -1235 "org.owasp.dependencycheck.dependency.VulnerableSoftware", -1236 "org.owasp.dependencycheck.data.cpe.IndexEntry"); -1237 @SuppressWarnings("unchecked") -1238 final List<Dependency> depList = (List<Dependency>) ois.readObject(); -1239 ret = depList; -1240 } catch (FileNotFoundException ex) { -1241 //TODO fix logging -1242 getLog().error("", ex); -1243 } catch (IOException ex) { -1244 getLog().error("", ex); -1245 } catch (ClassNotFoundException ex) { -1246 getLog().error("", ex); -1247 } finally { -1248 if (ois != null) { -1249 try { -1250 ois.close(); -1251 } catch (IOException ex) { -1252 getLog().error("", ex); -1253 } -1254 } -1255 } -1256 return ret; -1257 } -1258 //</editor-fold> -1259 -1260 } +1185 getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s", +1186 file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey())); +1187 } +1188 mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath()); +1189 } catch (IOException ex) { +1190 getLog().warn("Unable to create data file used for report aggregation; " +1191 + "if report aggregation is being used the results may be incomplete."); +1192 if (getLog().isDebugEnabled()) { +1193 getLog().debug(ex.getMessage(), ex); +1194 } +1195 } finally { +1196 if (out != null) { +1197 try { +1198 out.close(); +1199 } catch (IOException ex) { +1200 if (getLog().isDebugEnabled()) { +1201 getLog().debug("ignore", ex); +1202 } +1203 } +1204 } +1205 } +1206 } +1207 } +1208 +1209 /** +1210 * Reads the serialized scan data from disk. This is used to serialize the +1211 * scan data between the "check" and "aggregate" phase. +1212 * +1213 * @param project the Maven project to read the data file from +1214 * @return a <code>MavenEngine</code> object populated with dependencies if +1215 * the serialized data file exists; otherwise <code>null</code> is returned +1216 */ +1217 protected List<Dependency> readDataFile(MavenProject project) { +1218 final Object oPath = project.getContextValue(this.getDataFileContextKey()); +1219 if (oPath == null) { +1220 return null; +1221 } +1222 List<Dependency> ret = null; +1223 final String path = (String) oPath; +1224 //ObjectInputStream ois = null; +1225 ExpectedOjectInputStream ois = null; +1226 try { +1227 //ois = new ObjectInputStream(new FileInputStream(path)); +1228 ois = new ExpectedOjectInputStream(new FileInputStream(path), +1229 "java.util.ArrayList", +1230 "java.util.HashSet", +1231 "java.util.TreeSet", +1232 "java.lang.AbstractSet", +1233 "java.lang.AbstractCollection", +1234 "java.lang.Enum", +1235 "org.owasp.dependencycheck.dependency.Confidence", +1236 "org.owasp.dependencycheck.dependency.Dependency", +1237 "org.owasp.dependencycheck.dependency.Evidence", +1238 "org.owasp.dependencycheck.dependency.EvidenceCollection", +1239 "org.owasp.dependencycheck.dependency.Identifier", +1240 "org.owasp.dependencycheck.dependency.Reference", +1241 "org.owasp.dependencycheck.dependency.Vulnerability", +1242 "org.owasp.dependencycheck.dependency.VulnerabilityComparator", +1243 "org.owasp.dependencycheck.dependency.VulnerableSoftware", +1244 "org.owasp.dependencycheck.data.cpe.IndexEntry"); +1245 @SuppressWarnings("unchecked") +1246 final List<Dependency> depList = (List<Dependency>) ois.readObject(); +1247 ret = depList; +1248 } catch (FileNotFoundException ex) { +1249 //TODO fix logging +1250 getLog().error("", ex); +1251 } catch (IOException ex) { +1252 getLog().error("", ex); +1253 } catch (ClassNotFoundException ex) { +1254 getLog().error("", ex); +1255 } finally { +1256 if (ois != null) { +1257 try { +1258 ois.close(); +1259 } catch (IOException ex) { +1260 getLog().error("", ex); +1261 } +1262 } +1263 } +1264 return ret; +1265 } +1266 //</editor-fold> +1267 +1268 }
      diff --git a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/CheckMojo.html b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/CheckMojo.html index d9b68af3d..1b1c35531 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/CheckMojo.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/CheckMojo.html @@ -89,7 +89,7 @@ 81 if (getLog().isDebugEnabled()) { 82 getLog().debug("Database connection error", ex); 83 } -84 final String msg = "An exception occured connecting to the local database. Please see the log file for more details."; +84 final String msg = "An exception occurred connecting to the local database. Please see the log file for more details."; 85 if (this.isFailOnError()) { 86 throw new MojoExecutionException(msg, ex); 87 } @@ -104,7 +104,7 @@ 96 engine.analyzeDependencies(); 97 } catch (ExceptionCollection ex) { 98 if (this.isFailOnError() && ex.isFatal()) { -99 throw new MojoExecutionException("One or more exceptions occured during analysis", ex); +99 throw new MojoExecutionException("One or more exceptions occurred during analysis", ex); 100 } 101 exCol = ex; 102 } @@ -120,11 +120,11 @@ 112 } 113 } 114 } -115 writeDataFile(getProject(), null, engine.getDependencies()); +115 //writeDataFile(getProject(), null, engine.getDependencies()); 116 showSummary(getProject(), engine.getDependencies()); 117 checkForFailure(engine.getDependencies()); 118 if (exCol != null && this.isFailOnError()) { -119 throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); +119 throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol); 120 } 121 } 122 } diff --git a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/HelpMojo.html b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/HelpMojo.html index 460ce05b6..0d1795c8e 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/HelpMojo.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/HelpMojo.html @@ -282,184 +282,188 @@ 274 String parameterName = getValue( parameter, "name" ); 275 String parameterDescription = getValue( parameter, "description" ); 276 -277 Element fieldConfigurationElement = (Element) findSingleChild( configurationElement, parameterName ); -278 -279 String parameterDefaultValue = ""; -280 if ( fieldConfigurationElement != null && fieldConfigurationElement.hasAttribute( "default-value" ) ) -281 { -282 parameterDefaultValue = " (Default: " + fieldConfigurationElement.getAttribute( "default-value" ) + ")"; -283 } -284 append( sb, parameterName + parameterDefaultValue, 2 ); -285 Node deprecated = findSingleChild( parameter, "deprecated" ); -286 if ( ( deprecated != null ) && isNotEmpty( deprecated.getTextContent() ) ) -287 { -288 append( sb, "Deprecated. " + deprecated.getTextContent(), 3 ); -289 append( sb, "", 0 ); -290 } -291 append( sb, parameterDescription, 3 ); -292 if ( "true".equals( getValue( parameter, "required" ) ) ) -293 { -294 append( sb, "Required: Yes", 3 ); -295 } -296 if ( ( fieldConfigurationElement != null ) && isNotEmpty( fieldConfigurationElement.getTextContent() ) ) +277 Element fieldConfigurationElement = null; +278 if ( configurationElement != null ) +279 { +280 fieldConfigurationElement = (Element) findSingleChild( configurationElement, parameterName ); +281 } +282 +283 String parameterDefaultValue = ""; +284 if ( fieldConfigurationElement != null && fieldConfigurationElement.hasAttribute( "default-value" ) ) +285 { +286 parameterDefaultValue = " (Default: " + fieldConfigurationElement.getAttribute( "default-value" ) + ")"; +287 } +288 append( sb, parameterName + parameterDefaultValue, 2 ); +289 Node deprecated = findSingleChild( parameter, "deprecated" ); +290 if ( ( deprecated != null ) && isNotEmpty( deprecated.getTextContent() ) ) +291 { +292 append( sb, "Deprecated. " + deprecated.getTextContent(), 3 ); +293 append( sb, "", 0 ); +294 } +295 append( sb, parameterDescription, 3 ); +296 if ( "true".equals( getValue( parameter, "required" ) ) ) 297 { -298 String property = getPropertyFromExpression( fieldConfigurationElement.getTextContent() ); -299 append( sb, "User property: " + property, 3 ); -300 } -301 -302 append( sb, "", 0 ); -303 } -304 -305 /** -306 * <p>Repeat a String <code>n</code> times to form a new string.</p> -307 * -308 * @param str String to repeat -309 * @param repeat number of times to repeat str -310 * @return String with repeated String -311 * @throws NegativeArraySizeException if <code>repeat < 0</code> -312 * @throws NullPointerException if str is <code>null</code> -313 */ -314 private static String repeat( String str, int repeat ) -315 { -316 StringBuilder buffer = new StringBuilder( repeat * str.length() ); -317 -318 for ( int i = 0; i < repeat; i++ ) -319 { -320 buffer.append( str ); -321 } -322 -323 return buffer.toString(); -324 } -325 -326 /** -327 * Append a description to the buffer by respecting the indentSize and lineLength parameters. -328 * <b>Note</b>: The last character is always a new line. -329 * -330 * @param sb The buffer to append the description, not <code>null</code>. -331 * @param description The description, not <code>null</code>. -332 * @param indent The base indentation level of each line, must not be negative. -333 */ -334 private void append( StringBuilder sb, String description, int indent ) -335 { -336 for ( String line : toLines( description, indent, indentSize, lineLength ) ) -337 { -338 sb.append( line ).append( '\n' ); -339 } -340 } -341 -342 /** -343 * Splits the specified text into lines of convenient display length. -344 * -345 * @param text The text to split into lines, must not be <code>null</code>. -346 * @param indent The base indentation level of each line, must not be negative. -347 * @param indentSize The size of each indentation, must not be negative. -348 * @param lineLength The length of the line, must not be negative. -349 * @return The sequence of display lines, never <code>null</code>. -350 * @throws NegativeArraySizeException if <code>indent < 0</code> -351 */ -352 private static List<String> toLines( String text, int indent, int indentSize, int lineLength ) -353 { -354 List<String> lines = new ArrayList<String>(); -355 -356 String ind = repeat( "\t", indent ); -357 -358 String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" ); +298 append( sb, "Required: Yes", 3 ); +299 } +300 if ( ( fieldConfigurationElement != null ) && isNotEmpty( fieldConfigurationElement.getTextContent() ) ) +301 { +302 String property = getPropertyFromExpression( fieldConfigurationElement.getTextContent() ); +303 append( sb, "User property: " + property, 3 ); +304 } +305 +306 append( sb, "", 0 ); +307 } +308 +309 /** +310 * <p>Repeat a String <code>n</code> times to form a new string.</p> +311 * +312 * @param str String to repeat +313 * @param repeat number of times to repeat str +314 * @return String with repeated String +315 * @throws NegativeArraySizeException if <code>repeat &lt; 0</code> +316 * @throws NullPointerException if str is <code>null</code> +317 */ +318 private static String repeat( String str, int repeat ) +319 { +320 StringBuilder buffer = new StringBuilder( repeat * str.length() ); +321 +322 for ( int i = 0; i < repeat; i++ ) +323 { +324 buffer.append( str ); +325 } +326 +327 return buffer.toString(); +328 } +329 +330 /** +331 * Append a description to the buffer by respecting the indentSize and lineLength parameters. +332 * <b>Note</b>: The last character is always a new line. +333 * +334 * @param sb The buffer to append the description, not <code>null</code>. +335 * @param description The description, not <code>null</code>. +336 * @param indent The base indentation level of each line, must not be negative. +337 */ +338 private void append( StringBuilder sb, String description, int indent ) +339 { +340 for ( String line : toLines( description, indent, indentSize, lineLength ) ) +341 { +342 sb.append( line ).append( '\n' ); +343 } +344 } +345 +346 /** +347 * Splits the specified text into lines of convenient display length. +348 * +349 * @param text The text to split into lines, must not be <code>null</code>. +350 * @param indent The base indentation level of each line, must not be negative. +351 * @param indentSize The size of each indentation, must not be negative. +352 * @param lineLength The length of the line, must not be negative. +353 * @return The sequence of display lines, never <code>null</code>. +354 * @throws NegativeArraySizeException if <code>indent < 0</code> +355 */ +356 private static List<String> toLines( String text, int indent, int indentSize, int lineLength ) +357 { +358 List<String> lines = new ArrayList<String>(); 359 -360 for ( String plainLine : plainLines ) -361 { -362 toLines( lines, ind + plainLine, indentSize, lineLength ); -363 } -364 -365 return lines; -366 } -367 -368 /** -369 * Adds the specified line to the output sequence, performing line wrapping if necessary. -370 * -371 * @param lines The sequence of display lines, must not be <code>null</code>. -372 * @param line The line to add, must not be <code>null</code>. -373 * @param indentSize The size of each indentation, must not be negative. -374 * @param lineLength The length of the line, must not be negative. -375 */ -376 private static void toLines( List<String> lines, String line, int indentSize, int lineLength ) -377 { -378 int lineIndent = getIndentLevel( line ); -379 StringBuilder buf = new StringBuilder( 256 ); -380 -381 String[] tokens = line.split( " +" ); -382 -383 for ( String token : tokens ) -384 { -385 if ( buf.length() > 0 ) -386 { -387 if ( buf.length() + token.length() >= lineLength ) -388 { -389 lines.add( buf.toString() ); -390 buf.setLength( 0 ); -391 buf.append( repeat( " ", lineIndent * indentSize ) ); -392 } -393 else -394 { -395 buf.append( ' ' ); +360 String ind = repeat( "\t", indent ); +361 +362 String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" ); +363 +364 for ( String plainLine : plainLines ) +365 { +366 toLines( lines, ind + plainLine, indentSize, lineLength ); +367 } +368 +369 return lines; +370 } +371 +372 /** +373 * Adds the specified line to the output sequence, performing line wrapping if necessary. +374 * +375 * @param lines The sequence of display lines, must not be <code>null</code>. +376 * @param line The line to add, must not be <code>null</code>. +377 * @param indentSize The size of each indentation, must not be negative. +378 * @param lineLength The length of the line, must not be negative. +379 */ +380 private static void toLines( List<String> lines, String line, int indentSize, int lineLength ) +381 { +382 int lineIndent = getIndentLevel( line ); +383 StringBuilder buf = new StringBuilder( 256 ); +384 +385 String[] tokens = line.split( " +" ); +386 +387 for ( String token : tokens ) +388 { +389 if ( buf.length() > 0 ) +390 { +391 if ( buf.length() + token.length() >= lineLength ) +392 { +393 lines.add( buf.toString() ); +394 buf.setLength( 0 ); +395 buf.append( repeat( " ", lineIndent * indentSize ) ); 396 } -397 } -398 -399 for ( int j = 0; j < token.length(); j++ ) -400 { -401 char c = token.charAt( j ); -402 if ( c == '\t' ) -403 { -404 buf.append( repeat( " ", indentSize - buf.length() % indentSize ) ); -405 } -406 else if ( c == '\u00A0' ) +397 else +398 { +399 buf.append( ' ' ); +400 } +401 } +402 +403 for ( int j = 0; j < token.length(); j++ ) +404 { +405 char c = token.charAt( j ); +406 if ( c == '\t' ) 407 { -408 buf.append( ' ' ); +408 buf.append( repeat( " ", indentSize - buf.length() % indentSize ) ); 409 } -410 else +410 else if ( c == '\u00A0' ) 411 { -412 buf.append( c ); +412 buf.append( ' ' ); 413 } -414 } -415 } -416 lines.add( buf.toString() ); -417 } -418 -419 /** -420 * Gets the indentation level of the specified line. -421 * -422 * @param line The line whose indentation level should be retrieved, must not be <code>null</code>. -423 * @return The indentation level of the line. -424 */ -425 private static int getIndentLevel( String line ) -426 { -427 int level = 0; -428 for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ ) -429 { -430 level++; -431 } -432 for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ ) +414 else +415 { +416 buf.append( c ); +417 } +418 } +419 } +420 lines.add( buf.toString() ); +421 } +422 +423 /** +424 * Gets the indentation level of the specified line. +425 * +426 * @param line The line whose indentation level should be retrieved, must not be <code>null</code>. +427 * @return The indentation level of the line. +428 */ +429 private static int getIndentLevel( String line ) +430 { +431 int level = 0; +432 for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ ) 433 { -434 if ( line.charAt( i ) == '\t' ) -435 { -436 level++; -437 break; -438 } -439 } -440 return level; -441 } -442 -443 private String getPropertyFromExpression( String expression ) -444 { -445 if ( expression != null && expression.startsWith( "${" ) && expression.endsWith( "}" ) -446 && !expression.substring( 2 ).contains( "${" ) ) -447 { -448 // expression="${xxx}" -> property="xxx" -449 return expression.substring( 2, expression.length() - 1 ); -450 } -451 // no property can be extracted -452 return null; -453 } -454 } +434 level++; +435 } +436 for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ ) +437 { +438 if ( line.charAt( i ) == '\t' ) +439 { +440 level++; +441 break; +442 } +443 } +444 return level; +445 } +446 +447 private String getPropertyFromExpression( String expression ) +448 { +449 if ( expression != null && expression.startsWith( "${" ) && expression.endsWith( "}" ) +450 && !expression.substring( 2 ).contains( "${" ) ) +451 { +452 // expression="${xxx}" -> property="xxx" +453 return expression.substring( 2, expression.length() - 1 ); +454 } +455 // no property can be extracted +456 return null; +457 } +458 }
      diff --git a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/UpdateMojo.html b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/UpdateMojo.html index 08592eb8f..a4a569851 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/UpdateMojo.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/UpdateMojo.html @@ -79,13 +79,13 @@ 71 if (getLog().isDebugEnabled()) { 72 getLog().debug("Database connection error", ex); 73 } -74 final String msg = "An exception occured connecting to the local database. Please see the log file for more details."; +74 final String msg = "An exception occurred connecting to the local database. Please see the log file for more details."; 75 if (this.isFailOnError()) { 76 throw new MojoExecutionException(msg, ex); 77 } 78 getLog().error(msg); 79 } catch (UpdateException ex) { -80 final String msg = "An exception occured while downloading updates. Please see the log file for more details."; +80 final String msg = "An exception occurred while downloading updates. Please see the log file for more details."; 81 if (this.isFailOnError()) { 82 throw new MojoExecutionException(msg, ex); 83 } diff --git a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/package-frame.html b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/package-frame.html index 2bf11144a..d67fa4248 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/package-frame.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference Package org.owasp.dependencycheck.maven + Dependency-Check Maven Plugin 1.4.4 Reference Package org.owasp.dependencycheck.maven diff --git a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/package-summary.html b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/package-summary.html index 82f460dea..88784a777 100644 --- a/dependency-check-maven/xref/org/owasp/dependencycheck/maven/package-summary.html +++ b/dependency-check-maven/xref/org/owasp/dependencycheck/maven/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference Package org.owasp.dependencycheck.maven + Dependency-Check Maven Plugin 1.4.4 Reference Package org.owasp.dependencycheck.maven diff --git a/dependency-check-maven/xref/overview-frame.html b/dependency-check-maven/xref/overview-frame.html index fb886b2e5..8f1a95365 100644 --- a/dependency-check-maven/xref/overview-frame.html +++ b/dependency-check-maven/xref/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference + Dependency-Check Maven Plugin 1.4.4 Reference @@ -17,12 +17,6 @@ diff --git a/dependency-check-maven/xref/overview-summary.html b/dependency-check-maven/xref/overview-summary.html index 112f89128..85e4b25c2 100644 --- a/dependency-check-maven/xref/overview-summary.html +++ b/dependency-check-maven/xref/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Maven Plugin 1.4.3 Reference + Dependency-Check Maven Plugin 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Maven Plugin 1.4.3 Reference

      +

      Dependency-Check Maven Plugin 1.4.4 Reference

    72. @@ -37,16 +37,6 @@ - - - - - -
      org.owasp.dependencycheck.maven
      - org.owasp.dependencycheck.maven.slf4j -
      - org.slf4j.impl -
      diff --git a/dependency-check-utils/apidocs/allclasses-frame.html b/dependency-check-utils/apidocs/allclasses-frame.html index 5f6d87a77..651b0984c 100644 --- a/dependency-check-utils/apidocs/allclasses-frame.html +++ b/dependency-check-utils/apidocs/allclasses-frame.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Utils 1.4.3 API) - +All Classes (Dependency-Check Utils 1.4.4 API) + diff --git a/dependency-check-utils/apidocs/allclasses-noframe.html b/dependency-check-utils/apidocs/allclasses-noframe.html index ec01d0317..73760b5cd 100644 --- a/dependency-check-utils/apidocs/allclasses-noframe.html +++ b/dependency-check-utils/apidocs/allclasses-noframe.html @@ -2,10 +2,10 @@ - + -All Classes (Dependency-Check Utils 1.4.3 API) - +All Classes (Dependency-Check Utils 1.4.4 API) + diff --git a/dependency-check-utils/apidocs/constant-values.html b/dependency-check-utils/apidocs/constant-values.html index 4d38b9491..d8184d83d 100644 --- a/dependency-check-utils/apidocs/constant-values.html +++ b/dependency-check-utils/apidocs/constant-values.html @@ -2,10 +2,10 @@ - + -Constant Field Values (Dependency-Check Utils 1.4.3 API) - +Constant Field Values (Dependency-Check Utils 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,13 +13,13 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ diff --git a/dependency-check-utils/apidocs/org/owasp/dependencycheck/utils/package-summary.html b/dependency-check-utils/apidocs/org/owasp/dependencycheck/utils/package-summary.html index beac1c3a6..de3bb6e3f 100644 --- a/dependency-check-utils/apidocs/org/owasp/dependencycheck/utils/package-summary.html +++ b/dependency-check-utils/apidocs/org/owasp/dependencycheck/utils/package-summary.html @@ -2,10 +2,10 @@ - + -org.owasp.dependencycheck.utils (Dependency-Check Utils 1.4.3 API) - +org.owasp.dependencycheck.utils (Dependency-Check Utils 1.4.4 API) + @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@ - + diff --git a/dependency-check-utils/cobertura/frame-summary.html b/dependency-check-utils/cobertura/frame-summary.html index 90941d2a8..024f7f781 100644 --- a/dependency-check-utils/cobertura/frame-summary.html +++ b/dependency-check-utils/cobertura/frame-summary.html @@ -16,8 +16,8 @@ - - + +
      Package # Classes Line Coverage Branch Coverage Complexity
      All Packages13
      24%
      136/557
      19%
      37/190
      2.833
      org.owasp.dependencycheck.utils13
      24%
      136/557
      19%
      37/190
      2.833
      All Packages13
      25%
      144/572
      19%
      39/198
      2.901
      org.owasp.dependencycheck.utils13
      25%
      144/572
      19%
      39/198
      2.901
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Checksum.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Checksum.html index d79bd82cb..6805c04a6 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Checksum.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Checksum.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      Checksum
      80%
      28/35
      70%
      7/10
      2.4
      Checksum
      82%
      32/39
      75%
      9/12
      3
       
      @@ -68,7 +68,7 @@  25  
       import java.io.IOException;
       26   -
       import java.nio.MappedByteBuffer;
      +
       import java.nio.ByteBuffer;
       27  
       import java.nio.channels.FileChannel;
       28   @@ -117,161 +117,167 @@  51  
            * <p>
       52   -
            * Creates the cryptographic checksum of a given file using the specified algorithm.</p>
      +
            * Creates the cryptographic checksum of a given file using the specified
       53   -
            *
      +
            * algorithm.</p>
       54   -
            * @param algorithm the algorithm to use to calculate the checksum
      +
            *
       55   -
            * @param file the file to calculate the checksum for
      +
            * @param algorithm the algorithm to use to calculate the checksum
       56   -
            * @return the checksum
      +
            * @param file the file to calculate the checksum for
       57   -
            * @throws IOException when the file does not exist
      +
            * @return the checksum
       58   -
            * @throws NoSuchAlgorithmException when an algorithm is specified that does not exist
      +
            * @throws IOException when the file does not exist
       59   -
            */
      +
            * @throws NoSuchAlgorithmException when an algorithm is specified that does
       60   +
            * not exist
      +  61   +
            */
      +  62  
           public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
      -  61  5
               final MessageDigest digest = MessageDigest.getInstance(algorithm);
      -  62  4
               FileInputStream fis = null;
      -  63   +  63  5
               final MessageDigest md = MessageDigest.getInstance(algorithm);
      +  64  4
               FileInputStream fis = null;
      +  65  4
               FileChannel ch = null;
      +  66  
               try {
      -  64  4
                   fis = new FileInputStream(file);
      -  65  3
                   final FileChannel ch = fis.getChannel();
      -  66  3
                   long remainingToRead = file.length();
      -  67  3
                   long start = 0;
      -  68  6
                   while (remainingToRead > 0) {
      -  69   -
                       long amountToRead;
      -  70  3
                       if (remainingToRead > Integer.MAX_VALUE) {
      -  71  0
                           remainingToRead -= Integer.MAX_VALUE;
      -  72  0
                           amountToRead = Integer.MAX_VALUE;
      -  73   -
                       } else {
      -  74  3
                           amountToRead = remainingToRead;
      -  75  3
                           remainingToRead = 0;
      -  76   -
                       }
      -  77  3
                       final MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead);
      -  78  3
                       digest.update(byteBuffer);
      -  79  3
                       start += amountToRead;
      -  80  3
                   }
      -  81   +  67  4
                   fis = new FileInputStream(file);
      +  68  3
                   ch = fis.getChannel();
      +  69  3
                   final ByteBuffer buf = ByteBuffer.allocateDirect(8192);
      +  70  3
                   int b = ch.read(buf);
      +  71  6
                   while ((b != -1) && (b != 0)) {
      +  72  3
                       buf.flip();
      +  73  3
                       final byte[] bytes = new byte[b];
      +  74  3
                       buf.get(bytes);
      +  75  3
                       md.update(bytes, 0, b);
      +  76  3
                       buf.clear();
      +  77  3
                       b = ch.read(buf);
      +  78  3
                   }
      +  79  6
                   return md.digest();
      +  80  
               } finally {
      -  82  4
                   if (fis != null) {
      -  83   +  81  4
                   if (ch != null) {
      +  82  
                       try {
      -  84  3
                           fis.close();
      -  85  0
                       } catch (IOException ex) {
      -  86  0
                           LOGGER.trace("Error closing file '{}'.", file.getName(), ex);
      -  87  4
                       }
      -  88   +  83  3
                           ch.close();
      +  84  0
                       } catch (IOException ex) {
      +  85  0
                           LOGGER.trace("Error closing channel '{}'.", file.getName(), ex);
      +  86  3
                       }
      +  87  
                   }
      +  88  4
                   if (fis != null) {
       89   -
               }
      -  90  3
               return digest.digest();
      -  91   -
           }
      -  92   -
       
      -  93   -
           /**
      +
                       try {
      +  90  3
                           fis.close();
      +  91  0
                       } catch (IOException ex) {
      +  92  0
                           LOGGER.trace("Error closing file '{}'.", file.getName(), ex);
      +  93  4
                       }
       94   -
            * Calculates the MD5 checksum of a specified file.
      +
                   }
       95   -
            *
      +
               }
       96   -
            * @param file the file to generate the MD5 checksum
      +
           }
       97   -
            * @return the hex representation of the MD5 hash
      +
       
       98   -
            * @throws IOException when the file passed in does not exist
      +
           /**
       99   -
            * @throws NoSuchAlgorithmException when the MD5 algorithm is not available
      +
            * Calculates the MD5 checksum of a specified file.
       100   -
            */
      -  101   -
           public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
      -  102  1
               final byte[] b = getChecksum("MD5", file);
      -  103  1
               return getHex(b);
      -  104   -
           }
      -  105   -
       
      -  106   -
           /**
      -  107   -
            * Calculates the SHA1 checksum of a specified file.
      -  108  
            *
      -  109   +  101  
            * @param file the file to generate the MD5 checksum
      -  110   -
            * @return the hex representation of the SHA1 hash
      -  111   +  102   +
            * @return the hex representation of the MD5 hash
      +  103  
            * @throws IOException when the file passed in does not exist
      -  112   -
            * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available
      -  113   +  104   +
            * @throws NoSuchAlgorithmException when the MD5 algorithm is not available
      +  105  
            */
      -  114   -
           public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
      -  115  1
               final byte[] b = getChecksum("SHA1", file);
      -  116  1
               return getHex(b);
      -  117   +  106   +
           public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
      +  107  1
               final byte[] b = getChecksum("MD5", file);
      +  108  1
               return getHex(b);
      +  109  
           }
      -  118   -
           /**
      -  119   -
            * Hex code characters used in getHex.
      -  120   -
            */
      -  121   -
           private static final String HEXES = "0123456789abcdef";
      -  122   +  110  
       
      +  111   +
           /**
      +  112   +
            * Calculates the SHA1 checksum of a specified file.
      +  113   +
            *
      +  114   +
            * @param file the file to generate the MD5 checksum
      +  115   +
            * @return the hex representation of the SHA1 hash
      +  116   +
            * @throws IOException when the file passed in does not exist
      +  117   +
            * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available
      +  118   +
            */
      +  119   +
           public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
      +  120  1
               final byte[] b = getChecksum("SHA1", file);
      +  121  1
               return getHex(b);
      +  122   +
           }
       123  
           /**
       124   -
            * <p>
      +
            * Hex code characters used in getHex.
       125   -
            * Converts a byte array into a hex string.</p>
      -  126   -
            *
      -  127   -
            * <p>
      -  128   -
            * This method was copied from <a
      -  129   -
            * href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p>
      -  130   -
            *
      -  131   -
            * @param raw a byte array
      -  132   -
            * @return the hex representation of the byte array
      -  133  
            */
      +  126   +
           private static final String HEXES = "0123456789abcdef";
      +  127   +
       
      +  128   +
           /**
      +  129   +
            * <p>
      +  130   +
            * Converts a byte array into a hex string.</p>
      +  131   +
            *
      +  132   +
            * <p>
      +  133   +
            * This method was copied from <a
       134   -
           public static String getHex(byte[] raw) {
      -  135  3
               if (raw == null) {
      -  136  0
                   return null;
      +
            * href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p>
      +  135   +
            *
      +  136   +
            * @param raw a byte array
       137   +
            * @return the hex representation of the byte array
      +  138   +
            */
      +  139   +
           public static String getHex(byte[] raw) {
      +  140  3
               if (raw == null) {
      +  141  0
                   return null;
      +  142  
               }
      -  138  3
               final StringBuilder hex = new StringBuilder(2 * raw.length);
      -  139  56
               for (final byte b : raw) {
      -  140  53
                   hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F));
      -  141   +  143  3
               final StringBuilder hex = new StringBuilder(2 * raw.length);
      +  144  56
               for (final byte b : raw) {
      +  145  53
                   hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F));
      +  146  
               }
      -  142  3
               return hex.toString();
      -  143   +  147  3
               return hex.toString();
      +  148  
           }
      -  144   +  149  
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.DownloadFailedException.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.DownloadFailedException.html index 57632895c..8a6185cdc 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.DownloadFailedException.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.DownloadFailedException.html @@ -147,6 +147,6 @@
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Downloader.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Downloader.html index 7ab67b881..d494dda77 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Downloader.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Downloader.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      Downloader
      6%
      9/150
      1%
      1/52
      7.5
      Downloader
      5%
      9/154
      1%
      1/54
      7.75
       
      @@ -274,303 +274,313 @@
                       } finally {
       152  0
                           conn = null;
       153  0
                       }
      -  154  0
                       final String msg = format("Error downloading file %s; unable to connect.", url.toString());
      -  155  0
                       throw new DownloadFailedException(msg, ex);
      -  156  0
                   }
      +  154  0
                       if ("Connection reset".equalsIgnoreCase(ex.getMessage())) {
      +  155  0
                           final String msg = format("TLS Connection Reset%nPlease see "
      +  156   +
                                   + "http://jeremylong.github.io/DependencyCheck/general/tlsfailures.html "
       157   -
       
      -  158  0
                   final String encoding = conn.getContentEncoding();
      -  159  0
                   BufferedOutputStream writer = null;
      -  160  0
                   InputStream reader = null;
      -  161   -
                   try {
      -  162  0
                       if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
      -  163  0
                           reader = new GZIPInputStream(conn.getInputStream());
      -  164  0
                       } else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
      -  165  0
                           reader = new InflaterInputStream(conn.getInputStream());
      -  166   -
                       } else {
      -  167  0
                           reader = conn.getInputStream();
      -  168   +
                                   + "for more information regarding how to resolve the issue.");
      +  158  0
                           LOGGER.error(msg);
      +  159  0
                           throw new DownloadFailedException(msg, ex);
      +  160  
                       }
      -  169   +  161  0
                       final String msg = format("Error downloading file %s; unable to connect.", url.toString());
      +  162  0
                       throw new DownloadFailedException(msg, ex);
      +  163  0
                   }
      +  164  
       
      -  170  0
                       writer = new BufferedOutputStream(new FileOutputStream(outputPath));
      -  171  0
                       final byte[] buffer = new byte[4096];
      -  172   -
                       int bytesRead;
      -  173  0
                       while ((bytesRead = reader.read(buffer)) > 0) {
      -  174  0
                           writer.write(buffer, 0, bytesRead);
      +  165  0
                   final String encoding = conn.getContentEncoding();
      +  166  0
                   BufferedOutputStream writer = null;
      +  167  0
                   InputStream reader = null;
      +  168   +
                   try {
      +  169  0
                       if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
      +  170  0
                           reader = new GZIPInputStream(conn.getInputStream());
      +  171  0
                       } else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
      +  172  0
                           reader = new InflaterInputStream(conn.getInputStream());
      +  173   +
                       } else {
      +  174  0
                           reader = conn.getInputStream();
       175  
                       }
      -  176  0
                       LOGGER.debug("Download of {} complete", url.toString());
      -  177  0
                   } catch (IOException ex) {
      -  178  0
                       checkForCommonExceptionTypes(ex);
      -  179  0
                       final String msg = format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
      -  180  0
                               url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
      -  181  0
                       throw new DownloadFailedException(msg, ex);
      -  182  0
                   } catch (Throwable ex) {
      -  183  0
                       final String msg = format("Unexpected exception saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
      -  184  0
                               url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
      -  185  0
                       throw new DownloadFailedException(msg, ex);
      -  186   -
                   } finally {
      -  187  0
                       if (writer != null) {
      -  188   -
                           try {
      -  189  0
                               writer.close();
      -  190  0
                           } catch (IOException ex) {
      -  191  0
                               LOGGER.trace("Error closing the writer in Downloader.", ex);
      -  192  0
                           }
      -  193   +  176   +
       
      +  177  0
                       writer = new BufferedOutputStream(new FileOutputStream(outputPath));
      +  178  0
                       final byte[] buffer = new byte[4096];
      +  179   +
                       int bytesRead;
      +  180  0
                       while ((bytesRead = reader.read(buffer)) > 0) {
      +  181  0
                           writer.write(buffer, 0, bytesRead);
      +  182  
                       }
      -  194  0
                       if (reader != null) {
      +  183  0
                       LOGGER.debug("Download of {} complete", url.toString());
      +  184  0
                   } catch (IOException ex) {
      +  185  0
                       checkForCommonExceptionTypes(ex);
      +  186  0
                       final String msg = format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
      +  187  0
                               url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
      +  188  0
                       throw new DownloadFailedException(msg, ex);
      +  189  0
                   } catch (Throwable ex) {
      +  190  0
                       final String msg = format("Unexpected exception saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
      +  191  0
                               url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
      +  192  0
                       throw new DownloadFailedException(msg, ex);
      +  193   +
                   } finally {
      +  194  0
                       if (writer != null) {
       195  
                           try {
      -  196  0
                               reader.close();
      +  196  0
                               writer.close();
       197  0
                           } catch (IOException ex) {
      -  198  0
                               LOGGER.trace("Error closing the reader in Downloader.", ex);
      +  198  0
                               LOGGER.trace("Error closing the writer in Downloader.", ex);
       199  0
                           }
       200  
                       }
      -  201   -
                       try {
      -  202  0
                           conn.disconnect();
      -  203   -
                       } finally {
      -  204  0
                           conn = null;
      -  205  0
                       }
      -  206  0
                   }
      -  207   -
               }
      -  208  0
           }
      -  209   -
       
      -  210   -
           /**
      -  211   -
            * Makes an HTTP Head request to retrieve the last modified date of the
      -  212   -
            * given URL. If the file:// protocol is specified, then the lastTimestamp
      -  213   -
            * of the file is returned.
      -  214   -
            *
      -  215   -
            * @param url the URL to retrieve the timestamp from
      -  216   -
            * @return an epoch timestamp
      -  217   -
            * @throws DownloadFailedException is thrown if an exception occurs making
      -  218   -
            * the HTTP request
      -  219   -
            */
      -  220   -
           public static long getLastModified(URL url) throws DownloadFailedException {
      -  221  1
               return getLastModified(url, false);
      -  222   -
           }
      -  223   -
       
      -  224   -
           /**
      -  225   -
            * Makes an HTTP Head request to retrieve the last modified date of the
      -  226   -
            * given URL. If the file:// protocol is specified, then the lastTimestamp
      -  227   -
            * of the file is returned.
      -  228   -
            *
      -  229   -
            * @param url the URL to retrieve the timestamp from
      -  230   -
            * @param isRetry indicates if this is a retry - to prevent endless loop and
      -  231   -
            * stack overflow
      -  232   -
            * @return an epoch timestamp
      -  233   -
            * @throws DownloadFailedException is thrown if an exception occurs making
      -  234   -
            * the HTTP request
      -  235   -
            */
      -  236   -
           private static long getLastModified(URL url, boolean isRetry) throws DownloadFailedException {
      -  237  1
               long timestamp = 0;
      -  238   -
               //TODO add the FTP protocol?
      -  239  1
               if ("file".equalsIgnoreCase(url.getProtocol())) {
      -  240   -
                   File lastModifiedFile;
      -  241   -
                   try {
      -  242  1
                       lastModifiedFile = new File(url.toURI());
      -  243  0
                   } catch (URISyntaxException ex) {
      -  244  0
                       final String msg = format("Unable to locate '%s'", url.toString());
      -  245  0
                       throw new DownloadFailedException(msg);
      -  246  1
                   }
      -  247  1
                   timestamp = lastModifiedFile.lastModified();
      -  248  1
               } else {
      -  249  0
                   final String httpMethod = determineHttpMethod();
      -  250  0
                   HttpURLConnection conn = null;
      -  251   -
                   try {
      -  252  0
                       conn = URLConnectionFactory.createHttpURLConnection(url);
      -  253  0
                       conn.setRequestMethod(httpMethod);
      -  254  0
                       conn.connect();
      -  255  0
                       final int t = conn.getResponseCode();
      -  256  0
                       if (t >= 200 && t < 300) {
      -  257  0
                           timestamp = conn.getLastModified();
      -  258   -
                       } else {
      -  259  0
                           throw new DownloadFailedException(format("%s request returned a non-200 status code", httpMethod));
      -  260   -
                       }
      -  261  0
                   } catch (URLConnectionFailureException ex) {
      -  262  0
                       throw new DownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex);
      -  263  0
                   } catch (IOException ex) {
      -  264  0
                       checkForCommonExceptionTypes(ex);
      -  265  0
                       LOGGER.error("IO Exception: " + ex.getMessage());
      -  266  0
                       LOGGER.debug("Exception details", ex);
      -  267  0
                       if (ex.getCause() != null) {
      -  268  0
                           LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause());
      -  269   -
                       }
      -  270   -
                       try {
      -  271   -
                           //retry
      -  272  0
                           if (!isRetry && Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP)) {
      -  273  0
                               Settings.setBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, false);
      -  274  0
                               return getLastModified(url, true);
      -  275   -
                           }
      -  276  0
                       } catch (InvalidSettingException ex1) {
      -  277  0
                           LOGGER.debug("invalid setting?", ex);
      -  278  0
                       }
      -  279  0
                       throw new DownloadFailedException(format("Error making HTTP %s request.", httpMethod), ex);
      -  280   -
                   } finally {
      -  281  0
                       if (conn != null) {
      -  282   +  201  0
                       if (reader != null) {
      +  202  
                           try {
      -  283  0
                               conn.disconnect();
      -  284   -
                           } finally {
      -  285  0
                               conn = null;
      -  286  0
                           }
      -  287   +  203  0
                               reader.close();
      +  204  0
                           } catch (IOException ex) {
      +  205  0
                               LOGGER.trace("Error closing the reader in Downloader.", ex);
      +  206  0
                           }
      +  207  
                       }
      -  288   -
                   }
      +  208   +
                       try {
      +  209  0
                           conn.disconnect();
      +  210   +
                       } finally {
      +  211  0
                           conn = null;
      +  212  0
                       }
      +  213  0
                   }
      +  214   +
               }
      +  215  0
           }
      +  216   +
       
      +  217   +
           /**
      +  218   +
            * Makes an HTTP Head request to retrieve the last modified date of the
      +  219   +
            * given URL. If the file:// protocol is specified, then the lastTimestamp
      +  220   +
            * of the file is returned.
      +  221   +
            *
      +  222   +
            * @param url the URL to retrieve the timestamp from
      +  223   +
            * @return an epoch timestamp
      +  224   +
            * @throws DownloadFailedException is thrown if an exception occurs making
      +  225   +
            * the HTTP request
      +  226   +
            */
      +  227   +
           public static long getLastModified(URL url) throws DownloadFailedException {
      +  228  1
               return getLastModified(url, false);
      +  229   +
           }
      +  230   +
       
      +  231   +
           /**
      +  232   +
            * Makes an HTTP Head request to retrieve the last modified date of the
      +  233   +
            * given URL. If the file:// protocol is specified, then the lastTimestamp
      +  234   +
            * of the file is returned.
      +  235   +
            *
      +  236   +
            * @param url the URL to retrieve the timestamp from
      +  237   +
            * @param isRetry indicates if this is a retry - to prevent endless loop and
      +  238   +
            * stack overflow
      +  239   +
            * @return an epoch timestamp
      +  240   +
            * @throws DownloadFailedException is thrown if an exception occurs making
      +  241   +
            * the HTTP request
      +  242   +
            */
      +  243   +
           private static long getLastModified(URL url, boolean isRetry) throws DownloadFailedException {
      +  244  1
               long timestamp = 0;
      +  245   +
               //TODO add the FTP protocol?
      +  246  1
               if ("file".equalsIgnoreCase(url.getProtocol())) {
      +  247   +
                   File lastModifiedFile;
      +  248   +
                   try {
      +  249  1
                       lastModifiedFile = new File(url.toURI());
      +  250  0
                   } catch (URISyntaxException ex) {
      +  251  0
                       final String msg = format("Unable to locate '%s'", url.toString());
      +  252  0
                       throw new DownloadFailedException(msg);
      +  253  1
                   }
      +  254  1
                   timestamp = lastModifiedFile.lastModified();
      +  255  1
               } else {
      +  256  0
                   final String httpMethod = determineHttpMethod();
      +  257  0
                   HttpURLConnection conn = null;
      +  258   +
                   try {
      +  259  0
                       conn = URLConnectionFactory.createHttpURLConnection(url);
      +  260  0
                       conn.setRequestMethod(httpMethod);
      +  261  0
                       conn.connect();
      +  262  0
                       final int t = conn.getResponseCode();
      +  263  0
                       if (t >= 200 && t < 300) {
      +  264  0
                           timestamp = conn.getLastModified();
      +  265   +
                       } else {
      +  266  0
                           throw new DownloadFailedException(format("%s request returned a non-200 status code", httpMethod));
      +  267   +
                       }
      +  268  0
                   } catch (URLConnectionFailureException ex) {
      +  269  0
                       throw new DownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex);
      +  270  0
                   } catch (IOException ex) {
      +  271  0
                       checkForCommonExceptionTypes(ex);
      +  272  0
                       LOGGER.error("IO Exception: " + ex.getMessage());
      +  273  0
                       LOGGER.debug("Exception details", ex);
      +  274  0
                       if (ex.getCause() != null) {
      +  275  0
                           LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause());
      +  276   +
                       }
      +  277   +
                       try {
      +  278   +
                           //retry
      +  279  0
                           if (!isRetry && Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP)) {
      +  280  0
                               Settings.setBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, false);
      +  281  0
                               return getLastModified(url, true);
      +  282   +
                           }
      +  283  0
                       } catch (InvalidSettingException ex1) {
      +  284  0
                           LOGGER.debug("invalid setting?", ex);
      +  285  0
                       }
      +  286  0
                       throw new DownloadFailedException(format("Error making HTTP %s request.", httpMethod), ex);
      +  287   +
                   } finally {
      +  288  0
                       if (conn != null) {
       289   -
               }
      -  290  1
               return timestamp;
      +
                           try {
      +  290  0
                               conn.disconnect();
       291   -
           }
      -  292   -
       
      -  293   -
           /**
      +
                           } finally {
      +  292  0
                               conn = null;
      +  293  0
                           }
       294   -
            * Analyzes the IOException, logs the appropriate information for debugging
      +
                       }
       295   -
            * purposes, and then throws a DownloadFailedException that wraps the IO
      +
                   }
       296   -
            * Exception for common IO Exceptions. This is to provide additional details
      -  297   -
            * to assist in resolution of the exception.
      -  298   -
            *
      -  299   -
            * @param ex the original exception
      -  300   -
            * @throws DownloadFailedException a wrapper exception that contains the
      -  301   -
            * original exception as the cause
      -  302   -
            */
      -  303   -
           protected static synchronized void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException {
      -  304  0
               Throwable cause = ex;
      -  305  0
               while (cause != null) {
      -  306  0
                   if (cause instanceof java.net.UnknownHostException) {
      -  307  0
                       final String msg = format("Unable to resolve domain '%s'", cause.getMessage());
      -  308  0
                       LOGGER.error(msg);
      -  309  0
                       throw new DownloadFailedException(msg);
      -  310   -
                   }
      -  311  0
                   if (cause instanceof InvalidAlgorithmParameterException) {
      -  312  0
                       final String keystore = System.getProperty("javax.net.ssl.keyStore");
      -  313  0
                       final String version = System.getProperty("java.version");
      -  314  0
                       final String vendor = System.getProperty("java.vendor");
      -  315  0
                       LOGGER.info("Error making HTTPS request - InvalidAlgorithmParameterException");
      -  316  0
                       LOGGER.info("There appears to be an issue with the installation of Java and the cacerts."
      -  317   -
                               + "See closed issue #177 here: https://github.com/jeremylong/DependencyCheck/issues/177");
      -  318  0
                       LOGGER.info("Java Info:\njavax.net.ssl.keyStore='{}'\njava.version='{}'\njava.vendor='{}'",
      -  319   -
                               keystore, version, vendor);
      -  320  0
                       throw new DownloadFailedException("Error making HTTPS request. Please see the log for more details.");
      -  321   -
                   }
      -  322  0
                   cause = cause.getCause();
      -  323  
               }
      -  324  0
           }
      -  325   +  297  1
               return timestamp;
      +  298   +
           }
      +  299  
       
      +  300   +
           /**
      +  301   +
            * Analyzes the IOException, logs the appropriate information for debugging
      +  302   +
            * purposes, and then throws a DownloadFailedException that wraps the IO
      +  303   +
            * Exception for common IO Exceptions. This is to provide additional details
      +  304   +
            * to assist in resolution of the exception.
      +  305   +
            *
      +  306   +
            * @param ex the original exception
      +  307   +
            * @throws DownloadFailedException a wrapper exception that contains the
      +  308   +
            * original exception as the cause
      +  309   +
            */
      +  310   +
           protected static synchronized void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException {
      +  311  0
               Throwable cause = ex;
      +  312  0
               while (cause != null) {
      +  313  0
                   if (cause instanceof java.net.UnknownHostException) {
      +  314  0
                       final String msg = format("Unable to resolve domain '%s'", cause.getMessage());
      +  315  0
                       LOGGER.error(msg);
      +  316  0
                       throw new DownloadFailedException(msg);
      +  317   +
                   }
      +  318  0
                   if (cause instanceof InvalidAlgorithmParameterException) {
      +  319  0
                       final String keystore = System.getProperty("javax.net.ssl.keyStore");
      +  320  0
                       final String version = System.getProperty("java.version");
      +  321  0
                       final String vendor = System.getProperty("java.vendor");
      +  322  0
                       LOGGER.info("Error making HTTPS request - InvalidAlgorithmParameterException");
      +  323  0
                       LOGGER.info("There appears to be an issue with the installation of Java and the cacerts."
      +  324   +
                               + "See closed issue #177 here: https://github.com/jeremylong/DependencyCheck/issues/177");
      +  325  0
                       LOGGER.info("Java Info:\njavax.net.ssl.keyStore='{}'\njava.version='{}'\njava.vendor='{}'",
       326   -
           /**
      -  327   -
            * Returns the HEAD or GET HTTP method. HEAD is the default.
      +
                               keystore, version, vendor);
      +  327  0
                       throw new DownloadFailedException("Error making HTTPS request. Please see the log for more details.");
       328   -
            *
      -  329   -
            * @return the HTTP method to use
      +
                   }
      +  329  0
                   cause = cause.getCause();
       330   -
            */
      -  331   -
           private static String determineHttpMethod() {
      -  332  0
               return isQuickQuery() ? HEAD : GET;
      +
               }
      +  331  0
           }
      +  332   +
       
       333   -
           }
      -  334   -
       
      -  335  
           /**
      -  336   -
            * Determines if the HTTP method GET or HEAD should be used to check the
      -  337   -
            * timestamp on external resources.
      -  338   +  334   +
            * Returns the HEAD or GET HTTP method. HEAD is the default.
      +  335  
            *
      -  339   -
            * @return true if configured to use HEAD requests
      -  340   +  336   +
            * @return the HTTP method to use
      +  337  
            */
      -  341   -
           private static boolean isQuickQuery() {
      -  342   -
               boolean quickQuery;
      -  343   -
       
      -  344   -
               try {
      -  345  0
                   quickQuery = Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, true);
      -  346  0
               } catch (InvalidSettingException e) {
      -  347  0
                   quickQuery = true;
      -  348  0
               }
      -  349  0
               return quickQuery;
      -  350   +  338   +
           private static String determineHttpMethod() {
      +  339  0
               return isQuickQuery() ? HEAD : GET;
      +  340  
           }
      +  341   +
       
      +  342   +
           /**
      +  343   +
            * Determines if the HTTP method GET or HEAD should be used to check the
      +  344   +
            * timestamp on external resources.
      +  345   +
            *
      +  346   +
            * @return true if configured to use HEAD requests
      +  347   +
            */
      +  348   +
           private static boolean isQuickQuery() {
      +  349   +
               boolean quickQuery;
      +  350   +
       
       351   +
               try {
      +  352  0
                   quickQuery = Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, true);
      +  353  0
               } catch (InvalidSettingException e) {
      +  354  0
                   quickQuery = true;
      +  355  0
               }
      +  356  0
               return quickQuery;
      +  357   +
           }
      +  358  
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.ExpectedOjectInputStream.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.ExpectedOjectInputStream.html index 78f2f0628..c7cc9579a 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.ExpectedOjectInputStream.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.ExpectedOjectInputStream.html @@ -152,6 +152,6 @@
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.ExtractionException.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.ExtractionException.html index c0514c183..ec90a8667 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.ExtractionException.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.ExtractionException.html @@ -147,6 +147,6 @@
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.FileUtils.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.FileUtils.html index 99c052cfb..e0c9dae0c 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.FileUtils.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.FileUtils.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      FileUtils
      31%
      6/19
      40%
      4/10
      2.4
      FileUtils
      40%
      10/25
      42%
      6/14
      2.833
       
      @@ -147,83 +147,121 @@  67  
           /**
       68   -
            * Deletes a file. If the File is a directory it will recursively delete the contents.
      +
            * Deletes a file. If the File is a directory it will recursively delete the
       69   -
            *
      +
            * contents.
       70   -
            * @param file the File to delete
      +
            *
       71   -
            * @return true if the file was deleted successfully, otherwise false
      +
            * @param file the File to delete
       72   -
            */
      +
            * @return true if the file was deleted successfully, otherwise false
       73   +
            */
      +  74  
           public static boolean delete(File file) {
      -  74  3
               final boolean success = org.apache.commons.io.FileUtils.deleteQuietly(file);
      -  75  3
               if (!success) {
      -  76  0
                   LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath());
      -  77  0
                   file.deleteOnExit();
      -  78   +  75  3
               final boolean success = org.apache.commons.io.FileUtils.deleteQuietly(file);
      +  76  3
               if (!success) {
      +  77  0
                   LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath());
      +  78  0
                   file.deleteOnExit();
      +  79  
               }
      -  79  3
               return success;
      -  80   -
           }
      +  80  3
               return success;
       81   -
       
      +
           }
       82   -
           /**
      -  83   -
            * Generates a new temporary file name that is guaranteed to be unique.
      -  84   -
            *
      -  85   -
            * @param prefix the prefix for the file name to generate
      -  86   -
            * @param extension the extension of the generated file name
      -  87   -
            * @return a temporary File
      -  88   -
            * @throws java.io.IOException thrown if the temporary folder could not be created
      -  89   -
            */
      -  90   -
           public static File getTempFile(String prefix, String extension) throws IOException {
      -  91  0
               final File dir = Settings.getTempDirectory();
      -  92  0
               final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension);
      -  93  0
               final File tempFile = new File(dir, tempFileName);
      -  94  0
               if (tempFile.exists()) {
      -  95  0
                   return getTempFile(prefix, extension);
      -  96   -
               }
      -  97  0
               return tempFile;
      -  98   -
           }
      -  99  
       
      -  100   +  83  
           /**
      -  101   -
            * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows
      -  102   +  84   +
            * Creates a unique temporary directory in the given directory.
      +  85  
            *
      -  103   -
            * @return a String containing the bit bucket
      -  104   +  86   +
            * @param base the base directory to create a temporary directory within
      +  87   +
            * @return the temporary directory
      +  88   +
            * @throws IOException thrown when a directory cannot be created within the
      +  89   +
            * base directory
      +  90  
            */
      -  105   -
           public static String getBitBucket() {
      -  106  0
               if (SystemUtils.IS_OS_WINDOWS) {
      -  107  0
                   return BIT_BUCKET_WIN;
      -  108   -
               } else {
      -  109  0
                   return BIT_BUCKET_UNIX;
      -  110   +  91   +
           public static File createTempDirectory(File base) throws IOException {
      +  92  2
               final File tempDir = new File(base, "dctemp" + UUID.randomUUID().toString());
      +  93  2
               if (tempDir.exists()) {
      +  94  0
                   return createTempDirectory(base);
      +  95  
               }
      -  111   +  96  2
               if (!tempDir.mkdirs()) {
      +  97  0
                   throw new IOException("Could not create temp directory `" + tempDir.getAbsolutePath() + "`");
      +  98   +
               }
      +  99  2
               return tempDir;
      +  100  
           }
      -  112   +  101   +
       
      +  102   +
           /**
      +  103   +
            * Generates a new temporary file name that is guaranteed to be unique.
      +  104   +
            *
      +  105   +
            * @param prefix the prefix for the file name to generate
      +  106   +
            * @param extension the extension of the generated file name
      +  107   +
            * @return a temporary File
      +  108   +
            * @throws java.io.IOException thrown if the temporary folder could not be
      +  109   +
            * created
      +  110   +
            */
      +  111   +
           public static File getTempFile(String prefix, String extension) throws IOException {
      +  112  0
               final File dir = Settings.getTempDirectory();
      +  113  0
               final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension);
      +  114  0
               final File tempFile = new File(dir, tempFileName);
      +  115  0
               if (tempFile.exists()) {
      +  116  0
                   return getTempFile(prefix, extension);
      +  117   +
               }
      +  118  0
               return tempFile;
      +  119   +
           }
      +  120   +
       
      +  121   +
           /**
      +  122   +
            * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for
      +  123   +
            * Windows
      +  124   +
            *
      +  125   +
            * @return a String containing the bit bucket
      +  126   +
            */
      +  127   +
           public static String getBitBucket() {
      +  128  0
               if (SystemUtils.IS_OS_WINDOWS) {
      +  129  0
                   return BIT_BUCKET_WIN;
      +  130   +
               } else {
      +  131  0
                   return BIT_BUCKET_UNIX;
      +  132   +
               }
      +  133   +
           }
      +  134  
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.InvalidSettingException.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.InvalidSettingException.html index ba93242f3..f241c1948 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.InvalidSettingException.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.InvalidSettingException.html @@ -147,6 +147,6 @@
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.SSLSocketFactoryEx.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.SSLSocketFactoryEx.html index fcad99863..fe633895b 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.SSLSocketFactoryEx.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.SSLSocketFactoryEx.html @@ -12,7 +12,7 @@
       
      - +
      Classes in this File Line Coverage Branch Coverage Complexity
      SSLSocketFactoryEx
      0%
      0/62
      0%
      0/6
      1.4
      SSLSocketFactoryEx
      0%
      0/67
      0%
      0/10
      1.533
       
      @@ -466,75 +466,84 @@
            */
       245  
           protected String[] getProtocolList() {
      -  246  0
               final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
      +  246  0
               SSLSocket socket = null;
       247  0
               String[] availableProtocols = null;
      -  248   -
       
      -  249  0
               SSLSocket socket = null;
      +  248  0
               final String[] preferredProtocols = Settings.getString(
      +  249   +
                       Settings.KEYS.DOWNLOADER_TLS_PROTOCOL_LIST,
       250   -
       
      -  251   +
                       "TLSv1,TLSv1.1,TLSv1.2,TLSv1.3")
      +  251  0
                       .split(",");
      +  252  
               try {
      -  252  0
                   final SSLSocketFactory factory = sslCtxt.getSocketFactory();
      -  253  0
                   socket = (SSLSocket) factory.createSocket();
      -  254   +  253  0
                   final SSLSocketFactory factory = sslCtxt.getSocketFactory();
      +  254  0
                   socket = (SSLSocket) factory.createSocket();
      +  255  
       
      -  255  0
                   availableProtocols = socket.getSupportedProtocols();
      -  256  0
                   Arrays.sort(availableProtocols);
      -  257  0
               } catch (Exception ex) {
      -  258  0
                   LOGGER.debug("Error getting protocol list, using TLSv1", ex);
      -  259  0
                   return new String[]{"TLSv1"};
      -  260   -
               } finally {
      -  261  0
                   if (socket != null) {
      +  256  0
                   availableProtocols = socket.getSupportedProtocols();
      +  257  0
                   Arrays.sort(availableProtocols);
      +  258  0
                   if (LOGGER.isDebugEnabled()) {
      +  259  0
                       LOGGER.debug("Available Protocols:");
      +  260  0
                       for (String p : availableProtocols) {
      +  261  0
                           LOGGER.debug(p);
       262   -
                       try {
      -  263  0
                           socket.close();
      -  264  0
                       } catch (IOException ex) {
      -  265  0
                           LOGGER.trace("Error closing socket", ex);
      -  266  0
                       }
      +
                       }
      +  263   +
                   }
      +  264  0
               } catch (Exception ex) {
      +  265  0
                   LOGGER.debug("Error getting protocol list, using TLSv1", ex);
      +  266  0
                   return new String[]{"TLSv1"};
       267   -
                   }
      -  268   -
               }
      +
               } finally {
      +  268  0
                   if (socket != null) {
       269   -
       
      -  270  0
               final List<String> aa = new ArrayList<String>();
      -  271  0
               for (String preferredProtocol : preferredProtocols) {
      -  272  0
                   final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol);
      -  273  0
                   if (idx >= 0) {
      -  274  0
                       aa.add(preferredProtocol);
      -  275   +
                       try {
      +  270  0
                           socket.close();
      +  271  0
                       } catch (IOException ex) {
      +  272  0
                           LOGGER.trace("Error closing socket", ex);
      +  273  0
                       }
      +  274  
                   }
      -  276   +  275  
               }
      -  277   +  276  
       
      -  278  0
               return aa.toArray(new String[0]);
      -  279   -
           }
      -  280   -
       
      -  281   -
           /**
      +  277  0
               final List<String> aa = new ArrayList<String>();
      +  278  0
               for (String preferredProtocol : preferredProtocols) {
      +  279  0
                   final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol);
      +  280  0
                   if (idx >= 0) {
      +  281  0
                       aa.add(preferredProtocol);
       282   -
            * The SSL context.
      +
                   }
       283   -
            */
      +
               }
       284   -
           private SSLContext sslCtxt;
      -  285   -
           /**
      +
       
      +  285  0
               return aa.toArray(new String[0]);
       286   -
            * The protocols.
      +
           }
       287   -
            */
      +
       
       288   -
           private String[] protocols;
      +
           /**
       289   +
            * The SSL context.
      +  290   +
            */
      +  291   +
           private SSLContext sslCtxt;
      +  292   +
           /**
      +  293   +
            * The protocols.
      +  294   +
            */
      +  295   +
           private String[] protocols;
      +  296  
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Settings.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Settings.html index 226127016..4f6460cf5 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Settings.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.Settings.html @@ -12,8 +12,8 @@
       
      - - + +
      Classes in this File Line Coverage Branch Coverage Complexity
      Settings
      47%
      84/176
      35%
      23/64
      2.697
      Settings$KEYS
      0%
      0/2
      N/A
      2.697
      Settings
      48%
      84/172
      35%
      21/60
      2.606
      Settings$KEYS
      0%
      0/2
      N/A
      2.606
       
      @@ -607,218 +607,217 @@  295  
               /**
       296   -
                * The properties key for whether the SWIFT package manager analyzer is enabled.
      +
                * The properties key for whether the SWIFT package manager analyzer is
       297   -
                */
      +
                * enabled.
       298   -
               public static final String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled";
      +
                */
       299   -
               /**
      +
               public static final String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled";
       300   -
                * The properties key for the Central search URL.
      +
               /**
       301   -
                */
      +
                * The properties key for the Central search URL.
       302   -
               public static final String ANALYZER_CENTRAL_URL = "analyzer.central.url";
      +
                */
       303   -
               /**
      +
               public static final String ANALYZER_CENTRAL_URL = "analyzer.central.url";
       304   -
                * The path to mono, if available.
      +
               /**
       305   -
                */
      +
                * The path to mono, if available.
       306   -
               public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path";
      +
                */
       307   -
               /**
      +
               public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path";
       308   -
                * The path to bundle-audit, if available.
      +
               /**
       309   -
                */
      +
                * The path to bundle-audit, if available.
       310   -
               public static final String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path";
      +
                */
       311   -
               /**
      +
               public static final String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path";
       312   -
                * The additional configured zip file extensions, if available.
      +
               /**
       313   -
                */
      +
                * The additional configured zip file extensions, if available.
       314   -
               public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip";
      +
                */
       315   -
               /**
      +
               public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip";
       316   -
                * The key to obtain the path to the VFEED data file.
      +
               /**
       317   -
                */
      +
                * The key to obtain the path to the VFEED data file.
       318   -
               public static final String VFEED_DATA_FILE = "vfeed.data_file";
      +
                */
       319   -
               /**
      +
               public static final String VFEED_DATA_FILE = "vfeed.data_file";
       320   -
                * The key to obtain the VFEED connection string.
      +
               /**
       321   -
                */
      +
                * The key to obtain the VFEED connection string.
       322   -
               public static final String VFEED_CONNECTION_STRING = "vfeed.connection_string";
      +
                */
       323   -
       
      +
               public static final String VFEED_CONNECTION_STRING = "vfeed.connection_string";
       324   -
               /**
      +
       
       325   -
                * The key to obtain the base download URL for the VFeed data file.
      +
               /**
       326   -
                */
      +
                * The key to obtain the base download URL for the VFeed data file.
       327   -
               public static final String VFEED_DOWNLOAD_URL = "vfeed.download_url";
      +
                */
       328   -
               /**
      +
               public static final String VFEED_DOWNLOAD_URL = "vfeed.download_url";
       329   -
                * The key to obtain the download file name for the VFeed data.
      +
               /**
       330   -
                */
      +
                * The key to obtain the download file name for the VFeed data.
       331   -
               public static final String VFEED_DOWNLOAD_FILE = "vfeed.download_file";
      +
                */
       332   -
               /**
      +
               public static final String VFEED_DOWNLOAD_FILE = "vfeed.download_file";
       333   -
                * The key to obtain the VFeed update status.
      -  334   -
                */
      -  335   -
               public static final String VFEED_UPDATE_STATUS = "vfeed.update_status";
      -  336   -
       
      -  337  
               /**
      -  338   -
                * The HTTP request method for query last modified date.
      -  339   +  334   +
                * The key to obtain the VFeed update status.
      +  335  
                */
      +  336   +
               public static final String VFEED_UPDATE_STATUS = "vfeed.update_status";
      +  337   +
       
      +  338   +
               /**
      +  339   +
                * The HTTP request method for query last modified date.
       340   -
               public static final String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp";
      +
                */
       341   -
           }
      +
               public static final String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp";
       342   -
           //</editor-fold>
      +
               /**
       343   -
       
      +
                * The HTTP protocol list to use.
       344   -
           /**
      +
                */
       345   -
            * The logger.
      +
               public static final String DOWNLOADER_TLS_PROTOCOL_LIST = "downloader.tls.protocols";
       346   -
            */
      -  347  1
           private static final Logger LOGGER = LoggerFactory.getLogger(Settings.class);
      +
           }
      +  347   +
           //</editor-fold>
       348   -
           /**
      -  349   -
            * The properties file location.
      -  350   -
            */
      -  351   -
           private static final String PROPERTIES_FILE = "dependencycheck.properties";
      -  352   -
           /**
      -  353   -
            * Thread local settings.
      -  354   -
            */
      -  355  1
           private static final ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>();
      -  356   -
           /**
      -  357   -
            * The properties.
      -  358   -
            */
      -  359  2
           private Properties props = null;
      -  360  
       
      +  349   +
           /**
      +  350   +
            * The logger.
      +  351   +
            */
      +  352  1
           private static final Logger LOGGER = LoggerFactory.getLogger(Settings.class);
      +  353   +
           /**
      +  354   +
            * The properties file location.
      +  355   +
            */
      +  356   +
           private static final String PROPERTIES_FILE = "dependencycheck.properties";
      +  357   +
           /**
      +  358   +
            * Thread local settings.
      +  359   +
            */
      +  360  1
           private static final ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>();
       361  
           /**
       362   -
            * Private constructor for the Settings class. This class loads the
      +
            * The properties.
       363   -
            * properties files.
      -  364   -
            *
      +
            */
      +  364  2
           private Properties props = null;
       365   -
            * @param propertiesFilePath the path to the base properties file to load
      +
       
       366   -
            */
      -  367  2
           private Settings(String propertiesFilePath) {
      -  368  2
               InputStream in = null;
      -  369  2
               props = new Properties();
      +
           /**
      +  367   +
            * Private constructor for the Settings class. This class loads the
      +  368   +
            * properties files.
      +  369   +
            *
       370   -
               try {
      -  371  2
                   in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath);
      -  372  2
                   props.load(in);
      -  373  0
               } catch (IOException ex) {
      -  374  0
                   LOGGER.error("Unable to load default settings.");
      -  375  0
                   LOGGER.debug("", ex);
      -  376   -
               } finally {
      -  377  2
                   if (in != null) {
      -  378   -
                       try {
      -  379  2
                           in.close();
      -  380  0
                       } catch (IOException ex) {
      -  381  0
                           LOGGER.trace("", ex);
      -  382  2
                       }
      -  383   -
                   }
      -  384   -
               }
      -  385  2
               logProperties("Properties loaded", props);
      -  386  2
           }
      -  387   -
       
      -  388   -
           /**
      -  389   -
            * Initializes the thread local settings object. Note, to use the settings
      -  390   -
            * object you must call this method. However, you must also call
      -  391   -
            * Settings.cleanup() to properly release resources.
      -  392   -
            */
      -  393   -
           public static void initialize() {
      -  394  2
               LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE));
      -  395  2
           }
      -  396   -
       
      -  397   -
           /**
      -  398   -
            * Initializes the thread local settings object. Note, to use the settings
      -  399   -
            * object you must call this method. However, you must also call
      -  400   -
            * Settings.cleanup() to properly release resources.
      -  401   -
            *
      -  402  
            * @param propertiesFilePath the path to the base properties file to load
      -  403   +  371  
            */
      -  404   -
           public static void initialize(String propertiesFilePath) {
      -  405  0
               LOCAL_SETTINGS.set(new Settings(propertiesFilePath));
      -  406  0
           }
      -  407   +  372  2
           private Settings(String propertiesFilePath) {
      +  373  2
               InputStream in = null;
      +  374  2
               props = new Properties();
      +  375   +
               try {
      +  376  2
                   in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath);
      +  377  2
                   props.load(in);
      +  378  0
               } catch (NullPointerException ex) {
      +  379  0
                   LOGGER.error("Did not find settings file '{}'.", propertiesFilePath);
      +  380  0
                   LOGGER.debug("", ex);
      +  381  0
               } catch (IOException ex) {
      +  382  0
                   LOGGER.error("Unable to load settings from '{}'.", propertiesFilePath);
      +  383  0
                   LOGGER.debug("", ex);
      +  384   +
               } finally {
      +  385  2
                   if (in != null) {
      +  386   +
                       try {
      +  387  2
                           in.close();
      +  388  0
                       } catch (IOException ex) {
      +  389  0
                           LOGGER.trace("", ex);
      +  390  2
                       }
      +  391   +
                   }
      +  392   +
               }
      +  393  2
               logProperties("Properties loaded", props);
      +  394  2
           }
      +  395  
       
      -  408   +  396  
           /**
      +  397   +
            * Initializes the thread local settings object. Note, to use the settings
      +  398   +
            * object you must call this method. However, you must also call
      +  399   +
            * Settings.cleanup() to properly release resources.
      +  400   +
            */
      +  401   +
           public static void initialize() {
      +  402  2
               LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE));
      +  403  2
           }
      +  404   +
       
      +  405   +
           /**
      +  406   +
            * Initializes the thread local settings object. Note, to use the settings
      +  407   +
            * object you must call this method. However, you must also call
      +  408   +
            * Settings.cleanup() to properly release resources.
       409   -
            * Cleans up resources to prevent memory leaks.
      -  410  
            *
      +  410   +
            * @param propertiesFilePath the path to the base properties file to load
       411  
            */
       412   -
           public static void cleanup() {
      -  413  0
               cleanup(true);
      +
           public static void initialize(String propertiesFilePath) {
      +  413  0
               LOCAL_SETTINGS.set(new Settings(propertiesFilePath));
       414  0
           }
       415  
       
      @@ -829,885 +828,888 @@  418  
            *
       419   -
            * @param deleteTemporary flag indicating whether any temporary directories
      +
            */
       420   -
            * generated should be removed
      -  421   -
            */
      -  422   -
           public static void cleanup(boolean deleteTemporary) {
      -  423  2
               if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) {
      -  424  2
                   FileUtils.delete(tempDirectory);
      -  425  2
                   if (tempDirectory.exists()) {
      +
           public static void cleanup() {
      +  421  0
               cleanup(true);
      +  422  0
           }
      +  423   +
       
      +  424   +
           /**
      +  425   +
            * Cleans up resources to prevent memory leaks.
       426   -
                       try {
      -  427  0
                           Thread.sleep(2000);
      -  428  0
                       } catch (InterruptedException ex) {
      -  429  0
                           LOGGER.trace("ignore", ex);
      -  430  0
                       }
      -  431  0
                       FileUtils.delete(tempDirectory);
      -  432   -
                   }
      -  433   -
               }
      +
            *
      +  427   +
            * @param deleteTemporary flag indicating whether any temporary directories
      +  428   +
            * generated should be removed
      +  429   +
            */
      +  430   +
           public static synchronized void cleanup(boolean deleteTemporary) {
      +  431  2
               if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) {
      +  432  2
                   FileUtils.delete(tempDirectory);
      +  433  2
                   tempDirectory = null;
       434   +
               }
      +  435  
               try {
      -  435  2
                   LOCAL_SETTINGS.remove();
      -  436  0
               } catch (Throwable ex) {
      -  437  0
                   LOGGER.debug("Error cleaning up Settings", ex);
      -  438  2
               }
      -  439  2
           }
      -  440   -
       
      +  436  2
                   LOCAL_SETTINGS.remove();
      +  437  0
               } catch (Throwable ex) {
      +  438  0
                   LOGGER.debug("Error cleaning up Settings", ex);
      +  439  2
               }
      +  440  2
           }
       441   -
           /**
      +
       
       442   -
            * Gets the underlying instance of the Settings object.
      +
           /**
       443   -
            *
      +
            * Gets the underlying instance of the Settings object.
       444   -
            * @return the Settings object
      +
            *
       445   -
            */
      +
            * @return the Settings object
       446   +
            */
      +  447  
           public static Settings getInstance() {
      -  447  0
               return LOCAL_SETTINGS.get();
      -  448   -
           }
      +  448  0
               return LOCAL_SETTINGS.get();
       449   -
       
      +
           }
       450   -
           /**
      +
       
       451   -
            * Sets the instance of the Settings object to use in this thread.
      +
           /**
       452   -
            *
      +
            * Sets the instance of the Settings object to use in this thread.
       453   -
            * @param instance the instance of the settings object to use in this thread
      +
            *
       454   -
            */
      +
            * @param instance the instance of the settings object to use in this thread
       455   +
            */
      +  456  
           public static void setInstance(Settings instance) {
      -  456  0
               LOCAL_SETTINGS.set(instance);
      -  457  0
           }
      -  458   -
       
      +  457  0
               LOCAL_SETTINGS.set(instance);
      +  458  0
           }
       459   -
           /**
      +
       
       460   -
            * Logs the properties. This will not log any properties that contain
      +
           /**
       461   -
            * 'password' in the key.
      +
            * Logs the properties. This will not log any properties that contain
       462   -
            *
      +
            * 'password' in the key.
       463   -
            * @param header the header to print with the log message
      +
            *
       464   -
            * @param properties the properties to log
      +
            * @param header the header to print with the log message
       465   -
            */
      +
            * @param properties the properties to log
       466   +
            */
      +  467  
           private static void logProperties(String header, Properties properties) {
      -  467  3
               if (LOGGER.isDebugEnabled()) {
      -  468  0
                   final StringWriter sw = new StringWriter();
      -  469  0
                   PrintWriter pw = null;
      -  470   +  468  3
               if (LOGGER.isDebugEnabled()) {
      +  469  0
                   final StringWriter sw = new StringWriter();
      +  470  0
                   PrintWriter pw = null;
      +  471  
                   try {
      -  471  0
                       pw = new PrintWriter(sw);
      -  472  0
                       pw.format("%s:%n%n", header);
      -  473  0
                       final Enumeration<?> e = properties.propertyNames();
      -  474  0
                       while (e.hasMoreElements()) {
      -  475  0
                           final String key = (String) e.nextElement();
      -  476  0
                           if (key.contains("password")) {
      -  477  0
                               pw.format("%s='*****'%n", key);
      -  478   +  472  0
                       pw = new PrintWriter(sw);
      +  473  0
                       pw.format("%s:%n%n", header);
      +  474  0
                       final Enumeration<?> e = properties.propertyNames();
      +  475  0
                       while (e.hasMoreElements()) {
      +  476  0
                           final String key = (String) e.nextElement();
      +  477  0
                           if (key.contains("password")) {
      +  478  0
                               pw.format("%s='*****'%n", key);
      +  479  
                           } else {
      -  479  0
                               final String value = properties.getProperty(key);
      -  480  0
                               if (value != null) {
      -  481  0
                                   pw.format("%s='%s'%n", key, value);
      -  482   -
                               }
      +  480  0
                               final String value = properties.getProperty(key);
      +  481  0
                               if (value != null) {
      +  482  0
                                   pw.format("%s='%s'%n", key, value);
       483   +
                               }
      +  484  
                           }
      -  484  0
                       }
      -  485  0
                       pw.flush();
      -  486  0
                       LOGGER.debug(sw.toString());
      -  487   +  485  0
                       }
      +  486  0
                       pw.flush();
      +  487  0
                       LOGGER.debug(sw.toString());
      +  488  
                   } finally {
      -  488  0
                       if (pw != null) {
      -  489  0
                           pw.close();
      -  490   -
                       }
      +  489  0
                       if (pw != null) {
      +  490  0
                           pw.close();
       491   -
                   }
      +
                       }
       492   -
       
      +
                   }
       493   -
               }
      -  494  3
           }
      -  495  
       
      +  494   +
               }
      +  495  3
           }
       496   -
           /**
      +
       
       497   -
            * Sets a property value.
      +
           /**
       498   -
            *
      +
            * Sets a property value.
       499   -
            * @param key the key for the property
      +
            *
       500   -
            * @param value the value for the property
      +
            * @param key the key for the property
       501   -
            */
      +
            * @param value the value for the property
       502   +
            */
      +  503  
           public static void setString(String key, String value) {
      -  503  8
               LOCAL_SETTINGS.get().props.setProperty(key, value);
      -  504  8
               LOGGER.debug("Setting: {}='{}'", key, value);
      -  505  8
           }
      -  506   -
       
      +  504  8
               LOCAL_SETTINGS.get().props.setProperty(key, value);
      +  505  8
               LOGGER.debug("Setting: {}='{}'", key, value);
      +  506  8
           }
       507   -
           /**
      +
       
       508   -
            * Sets a property value only if the value is not null.
      +
           /**
       509   -
            *
      +
            * Sets a property value only if the value is not null.
       510   -
            * @param key the key for the property
      +
            *
       511   -
            * @param value the value for the property
      +
            * @param key the key for the property
       512   -
            */
      +
            * @param value the value for the property
       513   +
            */
      +  514  
           public static void setStringIfNotNull(String key, String value) {
      -  514  1
               if (null != value) {
      -  515  0
                   setString(key, value);
      -  516   +  515  1
               if (null != value) {
      +  516  0
                   setString(key, value);
      +  517  
               }
      -  517  1
           }
      -  518   -
       
      +  518  1
           }
       519   -
           /**
      +
       
       520   -
            * Sets a property value only if the value is not null and not empty.
      +
           /**
       521   -
            *
      +
            * Sets a property value only if the value is not null and not empty.
       522   -
            * @param key the key for the property
      +
            *
       523   -
            * @param value the value for the property
      +
            * @param key the key for the property
       524   -
            */
      +
            * @param value the value for the property
       525   +
            */
      +  526  
           public static void setStringIfNotEmpty(String key, String value) {
      -  526  1
               if (null != value && !value.isEmpty()) {
      -  527  0
                   setString(key, value);
      -  528   +  527  1
               if (null != value && !value.isEmpty()) {
      +  528  0
                   setString(key, value);
      +  529  
               }
      -  529  1
           }
      -  530   -
       
      +  530  1
           }
       531   -
           /**
      +
       
       532   -
            * Sets a property value.
      +
           /**
       533   -
            *
      -  534   -
            * @param key the key for the property
      -  535   -
            * @param value the value for the property
      -  536   -
            */
      -  537   -
           public static void setBoolean(String key, boolean value) {
      -  538  0
               setString(key, Boolean.toString(value));
      -  539  0
           }
      -  540   -
       
      -  541   -
           /**
      -  542   -
            * Sets a property value only if the value is not null.
      -  543   -
            *
      -  544   -
            * @param key the key for the property
      -  545   -
            * @param value the value for the property
      -  546   -
            */
      -  547   -
           public static void setBooleanIfNotNull(String key, Boolean value) {
      -  548  0
               if (null != value) {
      -  549  0
                   setBoolean(key, value);
      -  550   -
               }
      -  551  0
           }
      -  552   -
       
      -  553   -
           /**
      -  554  
            * Sets a property value.
      -  555   +  534  
            *
      -  556   +  535  
            * @param key the key for the property
      -  557   +  536  
            * @param value the value for the property
      -  558   +  537  
            */
      -  559   -
           public static void setInt(String key, int value) {
      -  560  0
               LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value));
      -  561  0
               LOGGER.debug("Setting: {}='{}'", key, value);
      -  562  0
           }
      -  563   +  538   +
           public static void setBoolean(String key, boolean value) {
      +  539  0
               setString(key, Boolean.toString(value));
      +  540  0
           }
      +  541  
       
      -  564   +  542  
           /**
      -  565   +  543  
            * Sets a property value only if the value is not null.
      -  566   +  544  
            *
      -  567   +  545  
            * @param key the key for the property
      -  568   +  546  
            * @param value the value for the property
      +  547   +
            */
      +  548   +
           public static void setBooleanIfNotNull(String key, Boolean value) {
      +  549  0
               if (null != value) {
      +  550  0
                   setBoolean(key, value);
      +  551   +
               }
      +  552  0
           }
      +  553   +
       
      +  554   +
           /**
      +  555   +
            * Sets a property value.
      +  556   +
            *
      +  557   +
            * @param key the key for the property
      +  558   +
            * @param value the value for the property
      +  559   +
            */
      +  560   +
           public static void setInt(String key, int value) {
      +  561  0
               LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value));
      +  562  0
               LOGGER.debug("Setting: {}='{}'", key, value);
      +  563  0
           }
      +  564   +
       
      +  565   +
           /**
      +  566   +
            * Sets a property value only if the value is not null.
      +  567   +
            *
      +  568   +
            * @param key the key for the property
       569   -
            */
      +
            * @param value the value for the property
       570   +
            */
      +  571  
           public static void setIntIfNotNull(String key, Integer value) {
      -  571  0
               if (null != value) {
      -  572  0
                   setInt(key, value);
      -  573   +  572  0
               if (null != value) {
      +  573  0
                   setInt(key, value);
      +  574  
               }
      -  574  0
           }
      -  575   -
       
      +  575  0
           }
       576   -
           /**
      +
       
       577   -
            * Merges a new properties file into the current properties. This method
      +
           /**
       578   -
            * allows for the loading of a user provided properties file.<br><br>
      +
            * Merges a new properties file into the current properties. This method
       579   -
            * <b>Note</b>: even if using this method - system properties will be loaded
      +
            * allows for the loading of a user provided properties file.<br><br>
       580   -
            * before properties loaded from files.
      -  581   -
            *
      -  582   -
            * @param filePath the path to the properties file to merge.
      -  583   -
            * @throws FileNotFoundException is thrown when the filePath points to a
      -  584   -
            * non-existent file
      -  585   -
            * @throws IOException is thrown when there is an exception loading/merging
      -  586   -
            * the properties
      -  587   -
            */
      -  588   -
           public static void mergeProperties(File filePath) throws FileNotFoundException, IOException {
      -  589  0
               FileInputStream fis = null;
      -  590   -
               try {
      -  591  0
                   fis = new FileInputStream(filePath);
      -  592  0
                   mergeProperties(fis);
      -  593   -
               } finally {
      -  594  0
                   if (fis != null) {
      -  595   -
                       try {
      -  596  0
                           fis.close();
      -  597  0
                       } catch (IOException ex) {
      -  598  0
                           LOGGER.trace("close error", ex);
      -  599  0
                       }
      -  600   -
                   }
      -  601   -
               }
      -  602  0
           }
      -  603   -
       
      -  604   -
           /**
      -  605   -
            * Merges a new properties file into the current properties. This method
      -  606   -
            * allows for the loading of a user provided properties file.<br><br>
      -  607   -
            * Note: even if using this method - system properties will be loaded before
      -  608   -
            * properties loaded from files.
      -  609   -
            *
      -  610   -
            * @param filePath the path to the properties file to merge.
      -  611   -
            * @throws FileNotFoundException is thrown when the filePath points to a
      -  612   -
            * non-existent file
      -  613   -
            * @throws IOException is thrown when there is an exception loading/merging
      -  614   -
            * the properties
      -  615   -
            */
      -  616   -
           public static void mergeProperties(String filePath) throws FileNotFoundException, IOException {
      -  617  1
               FileInputStream fis = null;
      -  618   -
               try {
      -  619  1
                   fis = new FileInputStream(filePath);
      -  620  1
                   mergeProperties(fis);
      -  621   -
               } finally {
      -  622  1
                   if (fis != null) {
      -  623   -
                       try {
      -  624  1
                           fis.close();
      -  625  0
                       } catch (IOException ex) {
      -  626  0
                           LOGGER.trace("close error", ex);
      -  627  1
                       }
      -  628   -
                   }
      -  629   -
               }
      -  630  1
           }
      -  631   -
       
      -  632   -
           /**
      -  633   -
            * Merges a new properties file into the current properties. This method
      -  634   -
            * allows for the loading of a user provided properties file.<br><br>
      -  635  
            * <b>Note</b>: even if using this method - system properties will be loaded
      -  636   +  581  
            * before properties loaded from files.
      -  637   +  582  
            *
      -  638   -
            * @param stream an Input Stream pointing at a properties file to merge
      -  639   +  583   +
            * @param filePath the path to the properties file to merge.
      +  584   +
            * @throws FileNotFoundException is thrown when the filePath points to a
      +  585   +
            * non-existent file
      +  586  
            * @throws IOException is thrown when there is an exception loading/merging
      -  640   +  587  
            * the properties
      -  641   +  588  
            */
      -  642   -
           public static void mergeProperties(InputStream stream) throws IOException {
      -  643  1
               LOCAL_SETTINGS.get().props.load(stream);
      -  644  1
               logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props);
      -  645  1
           }
      -  646   -
       
      -  647   -
           /**
      -  648   -
            * Returns a value from the properties file as a File object. If the value
      -  649   -
            * was specified as a system property or passed in via the -Dprop=value
      -  650   -
            * argument - this method will return the value from the system properties
      -  651   -
            * before the values in the contained configuration file.
      -  652   -
            *
      -  653   -
            * @param key the key to lookup within the properties file
      -  654   -
            * @return the property from the properties file converted to a File object
      -  655   -
            */
      -  656   -
           public static File getFile(String key) {
      -  657  0
               final String file = getString(key);
      -  658  0
               if (file == null) {
      -  659  0
                   return null;
      -  660   -
               }
      -  661  0
               return new File(file);
      -  662   -
           }
      -  663   -
       
      -  664   -
           /**
      -  665   -
            * Returns a value from the properties file as a File object. If the value
      -  666   -
            * was specified as a system property or passed in via the -Dprop=value
      -  667   -
            * argument - this method will return the value from the system properties
      -  668   -
            * before the values in the contained configuration file.
      -  669   -
            *
      -  670   -
            * This method will check the configured base directory and will use this as
      -  671   -
            * the base of the file path. Additionally, if the base directory begins
      -  672   -
            * with a leading "[JAR]\" sequence with the path to the folder containing
      -  673   -
            * the JAR file containing this class.
      -  674   -
            *
      -  675   -
            * @param key the key to lookup within the properties file
      -  676   -
            * @return the property from the properties file converted to a File object
      -  677   -
            */
      -  678   -
           protected static File getDataFile(String key) {
      -  679  2
               final String file = getString(key);
      -  680  2
               LOGGER.debug("Settings.getDataFile() - file: '{}'", file);
      -  681  2
               if (file == null) {
      -  682  0
                   return null;
      -  683   -
               }
      -  684  2
               if (file.startsWith("[JAR]")) {
      -  685  0
                   LOGGER.debug("Settings.getDataFile() - transforming filename");
      -  686  0
                   final File jarPath = getJarPath();
      -  687  0
                   LOGGER.debug("Settings.getDataFile() - jar file: '{}'", jarPath.toString());
      -  688  0
                   final File retVal = new File(jarPath, file.substring(6));
      -  689  0
                   LOGGER.debug("Settings.getDataFile() - returning: '{}'", retVal.toString());
      -  690  0
                   return retVal;
      -  691   -
               }
      -  692  2
               return new File(file);
      -  693   -
           }
      -  694   -
       
      -  695   -
           /**
      -  696   -
            * Attempts to retrieve the folder containing the Jar file containing the
      -  697   -
            * Settings class.
      -  698   -
            *
      -  699   -
            * @return a File object
      -  700   -
            */
      -  701   -
           private static File getJarPath() {
      -  702  0
               final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath();
      -  703  0
               String decodedPath = ".";
      -  704   +  589   +
           public static void mergeProperties(File filePath) throws FileNotFoundException, IOException {
      +  590  0
               FileInputStream fis = null;
      +  591  
               try {
      -  705  0
                   decodedPath = URLDecoder.decode(jarPath, "UTF-8");
      -  706  0
               } catch (UnsupportedEncodingException ex) {
      -  707  0
                   LOGGER.trace("", ex);
      -  708  0
               }
      -  709   -
       
      -  710  0
               final File path = new File(decodedPath);
      -  711  0
               if (path.getName().toLowerCase().endsWith(".jar")) {
      -  712  0
                   return path.getParentFile();
      -  713   -
               } else {
      -  714  0
                   return new File(".");
      -  715   +  592  0
                   fis = new FileInputStream(filePath);
      +  593  0
                   mergeProperties(fis);
      +  594   +
               } finally {
      +  595  0
                   if (fis != null) {
      +  596   +
                       try {
      +  597  0
                           fis.close();
      +  598  0
                       } catch (IOException ex) {
      +  599  0
                           LOGGER.trace("close error", ex);
      +  600  0
                       }
      +  601   +
                   }
      +  602  
               }
      -  716   -
           }
      -  717   +  603  0
           }
      +  604  
       
      -  718   +  605  
           /**
      -  719   -
            * Returns a value from the properties file. If the value was specified as a
      -  720   -
            * system property or passed in via the -Dprop=value argument - this method
      -  721   -
            * will return the value from the system properties before the values in the
      -  722   -
            * contained configuration file.
      -  723   +  606   +
            * Merges a new properties file into the current properties. This method
      +  607   +
            * allows for the loading of a user provided properties file.<br><br>
      +  608   +
            * Note: even if using this method - system properties will be loaded before
      +  609   +
            * properties loaded from files.
      +  610  
            *
      -  724   +  611   +
            * @param filePath the path to the properties file to merge.
      +  612   +
            * @throws FileNotFoundException is thrown when the filePath points to a
      +  613   +
            * non-existent file
      +  614   +
            * @throws IOException is thrown when there is an exception loading/merging
      +  615   +
            * the properties
      +  616   +
            */
      +  617   +
           public static void mergeProperties(String filePath) throws FileNotFoundException, IOException {
      +  618  1
               FileInputStream fis = null;
      +  619   +
               try {
      +  620  1
                   fis = new FileInputStream(filePath);
      +  621  1
                   mergeProperties(fis);
      +  622   +
               } finally {
      +  623  1
                   if (fis != null) {
      +  624   +
                       try {
      +  625  1
                           fis.close();
      +  626  0
                       } catch (IOException ex) {
      +  627  0
                           LOGGER.trace("close error", ex);
      +  628  1
                       }
      +  629   +
                   }
      +  630   +
               }
      +  631  1
           }
      +  632   +
       
      +  633   +
           /**
      +  634   +
            * Merges a new properties file into the current properties. This method
      +  635   +
            * allows for the loading of a user provided properties file.<br><br>
      +  636   +
            * <b>Note</b>: even if using this method - system properties will be loaded
      +  637   +
            * before properties loaded from files.
      +  638   +
            *
      +  639   +
            * @param stream an Input Stream pointing at a properties file to merge
      +  640   +
            * @throws IOException is thrown when there is an exception loading/merging
      +  641   +
            * the properties
      +  642   +
            */
      +  643   +
           public static void mergeProperties(InputStream stream) throws IOException {
      +  644  1
               LOCAL_SETTINGS.get().props.load(stream);
      +  645  1
               logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props);
      +  646  1
           }
      +  647   +
       
      +  648   +
           /**
      +  649   +
            * Returns a value from the properties file as a File object. If the value
      +  650   +
            * was specified as a system property or passed in via the -Dprop=value
      +  651   +
            * argument - this method will return the value from the system properties
      +  652   +
            * before the values in the contained configuration file.
      +  653   +
            *
      +  654  
            * @param key the key to lookup within the properties file
      -  725   -
            * @param defaultValue the default value for the requested property
      -  726   -
            * @return the property from the properties file
      -  727   +  655   +
            * @return the property from the properties file converted to a File object
      +  656  
            */
      -  728   -
           public static String getString(String key, String defaultValue) {
      -  729  6
               final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue));
      -  730  6
               return str;
      -  731   +  657   +
           public static File getFile(String key) {
      +  658  0
               final String file = getString(key);
      +  659  0
               if (file == null) {
      +  660  0
                   return null;
      +  661   +
               }
      +  662  0
               return new File(file);
      +  663  
           }
      -  732   +  664  
       
      -  733   +  665  
           /**
      -  734   -
            * A reference to the temporary directory; used incase it needs to be
      -  735   -
            * deleted during cleanup.
      -  736   -
            */
      -  737  1
           private static File tempDirectory = null;
      -  738   -
       
      -  739   -
           /**
      -  740   -
            * Returns the temporary directory.
      -  741   +  666   +
            * Returns a value from the properties file as a File object. If the value
      +  667   +
            * was specified as a system property or passed in via the -Dprop=value
      +  668   +
            * argument - this method will return the value from the system properties
      +  669   +
            * before the values in the contained configuration file.
      +  670  
            *
      -  742   -
            * @return the temporary directory
      -  743   -
            * @throws java.io.IOException thrown if the temporary directory does not
      -  744   -
            * exist and cannot be created
      -  745   +  671   +
            * This method will check the configured base directory and will use this as
      +  672   +
            * the base of the file path. Additionally, if the base directory begins
      +  673   +
            * with a leading "[JAR]\" sequence with the path to the folder containing
      +  674   +
            * the JAR file containing this class.
      +  675   +
            *
      +  676   +
            * @param key the key to lookup within the properties file
      +  677   +
            * @return the property from the properties file converted to a File object
      +  678  
            */
      +  679   +
           protected static File getDataFile(String key) {
      +  680  2
               final String file = getString(key);
      +  681  2
               LOGGER.debug("Settings.getDataFile() - file: '{}'", file);
      +  682  2
               if (file == null) {
      +  683  0
                   return null;
      +  684   +
               }
      +  685  2
               if (file.startsWith("[JAR]")) {
      +  686  0
                   LOGGER.debug("Settings.getDataFile() - transforming filename");
      +  687  0
                   final File jarPath = getJarPath();
      +  688  0
                   LOGGER.debug("Settings.getDataFile() - jar file: '{}'", jarPath.toString());
      +  689  0
                   final File retVal = new File(jarPath, file.substring(6));
      +  690  0
                   LOGGER.debug("Settings.getDataFile() - returning: '{}'", retVal.toString());
      +  691  0
                   return retVal;
      +  692   +
               }
      +  693  2
               return new File(file);
      +  694   +
           }
      +  695   +
       
      +  696   +
           /**
      +  697   +
            * Attempts to retrieve the folder containing the Jar file containing the
      +  698   +
            * Settings class.
      +  699   +
            *
      +  700   +
            * @return a File object
      +  701   +
            */
      +  702   +
           private static File getJarPath() {
      +  703  0
               final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath();
      +  704  0
               String decodedPath = ".";
      +  705   +
               try {
      +  706  0
                   decodedPath = URLDecoder.decode(jarPath, "UTF-8");
      +  707  0
               } catch (UnsupportedEncodingException ex) {
      +  708  0
                   LOGGER.trace("", ex);
      +  709  0
               }
      +  710   +
       
      +  711  0
               final File path = new File(decodedPath);
      +  712  0
               if (path.getName().toLowerCase().endsWith(".jar")) {
      +  713  0
                   return path.getParentFile();
      +  714   +
               } else {
      +  715  0
                   return new File(".");
      +  716   +
               }
      +  717   +
           }
      +  718   +
       
      +  719   +
           /**
      +  720   +
            * Returns a value from the properties file. If the value was specified as a
      +  721   +
            * system property or passed in via the -Dprop=value argument - this method
      +  722   +
            * will return the value from the system properties before the values in the
      +  723   +
            * contained configuration file.
      +  724   +
            *
      +  725   +
            * @param key the key to lookup within the properties file
      +  726   +
            * @param defaultValue the default value for the requested property
      +  727   +
            * @return the property from the properties file
      +  728   +
            */
      +  729   +
           public static String getString(String key, String defaultValue) {
      +  730  6
               final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue));
      +  731  6
               return str;
      +  732   +
           }
      +  733   +
       
      +  734   +
           /**
      +  735   +
            * A reference to the temporary directory; used incase it needs to be
      +  736   +
            * deleted during cleanup.
      +  737   +
            */
      +  738  1
           private static File tempDirectory = null;
      +  739   +
       
      +  740   +
           /**
      +  741   +
            * Returns the temporary directory.
      +  742   +
            *
      +  743   +
            * @return the temporary directory
      +  744   +
            * @throws java.io.IOException thrown if the temporary directory does not
      +  745   +
            * exist and cannot be created
       746   -
           public static File getTempDirectory() throws IOException {
      -  747  2
               final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")), "dctemp");
      -  748  2
               if (!tmpDir.exists() && !tmpDir.mkdirs()) {
      -  749  0
                   final String msg = String.format("Unable to make a temporary folder '%s'", tmpDir.getPath());
      -  750  0
                   throw new IOException(msg);
      +
            */
      +  747   +
           public static synchronized File getTempDirectory() throws IOException {
      +  748  2
               if (tempDirectory == null) {
      +  749  2
                   final File baseTemp = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")));
      +  750  2
                   tempDirectory = FileUtils.createTempDirectory(baseTemp);
       751  
               }
      -  752  2
               tempDirectory = tmpDir;
      -  753  2
               return tmpDir;
      +  752  2
               return tempDirectory;
      +  753   +
           }
       754   -
           }
      +
       
       755   -
       
      +
           /**
       756   -
           /**
      -  757  
            * Returns a value from the properties file. If the value was specified as a
      -  758   +  757  
            * system property or passed in via the -Dprop=value argument - this method
      -  759   +  758  
            * will return the value from the system properties before the values in the
      -  760   +  759  
            * contained configuration file.
      +  760   +
            *
       761   -
            *
      +
            * @param key the key to lookup within the properties file
       762   -
            * @param key the key to lookup within the properties file
      +
            * @return the property from the properties file
       763   -
            * @return the property from the properties file
      +
            */
       764   -
            */
      -  765  
           public static String getString(String key) {
      -  766  19
               return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key));
      +  765  19
               return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key));
      +  766   +
           }
       767   -
           }
      +
       
       768   -
       
      +
           /**
       769   -
           /**
      -  770  
            * Removes a property from the local properties collection. This is mainly
      -  771   +  770  
            * used in test cases.
      +  771   +
            *
       772   -
            *
      -  773  
            * @param key the property key to remove
      +  773   +
            */
       774   -
            */
      -  775  
           public static void removeProperty(String key) {
      -  776  1
               LOCAL_SETTINGS.get().props.remove(key);
      -  777  1
           }
      +  775  1
               LOCAL_SETTINGS.get().props.remove(key);
      +  776  1
           }
      +  777   +
       
       778   -
       
      +
           /**
       779   -
           /**
      +
            * Returns an int value from the properties file. If the value was specified
       780   -
            * Returns an int value from the properties file. If the value was specified
      +
            * as a system property or passed in via the -Dprop=value argument - this
       781   -
            * as a system property or passed in via the -Dprop=value argument - this
      +
            * method will return the value from the system properties before the values
       782   -
            * method will return the value from the system properties before the values
      +
            * in the contained configuration file.
       783   -
            * in the contained configuration file.
      +
            *
       784   -
            *
      +
            * @param key the key to lookup within the properties file
       785   -
            * @param key the key to lookup within the properties file
      +
            * @return the property from the properties file
       786   -
            * @return the property from the properties file
      +
            * @throws InvalidSettingException is thrown if there is an error retrieving
       787   -
            * @throws InvalidSettingException is thrown if there is an error retrieving
      +
            * the setting
       788   -
            * the setting
      +
            */
       789   -
            */
      -  790  
           public static int getInt(String key) throws InvalidSettingException {
      -  791   +  790  
               try {
      -  792  1
                   return Integer.parseInt(Settings.getString(key));
      -  793  0
               } catch (NumberFormatException ex) {
      -  794  0
                   throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
      +  791  1
                   return Integer.parseInt(Settings.getString(key));
      +  792  0
               } catch (NumberFormatException ex) {
      +  793  0
                   throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
      +  794   +
               }
       795   -
               }
      +
           }
       796   -
           }
      +
       
       797   -
       
      +
           /**
       798   -
           /**
      -  799  
            * Returns an int value from the properties file. If the value was specified
      +  799   +
            * as a system property or passed in via the -Dprop=value argument - this
       800   -
            * as a system property or passed in via the -Dprop=value argument - this
      +
            * method will return the value from the system properties before the values
       801   -
            * method will return the value from the system properties before the values
      +
            * in the contained configuration file.
       802   -
            * in the contained configuration file.
      +
            *
       803   -
            *
      +
            * @param key the key to lookup within the properties file
       804   -
            * @param key the key to lookup within the properties file
      -  805  
            * @param defaultValue the default value to return
      -  806   +  805  
            * @return the property from the properties file or the defaultValue if the
      -  807   +  806  
            * property does not exist or cannot be converted to an integer
      +  807   +
            */
       808   -
            */
      -  809  
           public static int getInt(String key, int defaultValue) {
      -  810   +  809  
               int value;
      -  811   +  810  
               try {
      -  812  1
                   value = Integer.parseInt(Settings.getString(key));
      -  813  1
               } catch (NumberFormatException ex) {
      -  814  1
                   if (!Settings.getString(key, "").isEmpty()) {
      -  815  1
                       LOGGER.debug("Could not convert property '{}={}' to an int; using {} instead.", key, Settings.getString(key), defaultValue);
      -  816   +  811  1
                   value = Integer.parseInt(Settings.getString(key));
      +  812  1
               } catch (NumberFormatException ex) {
      +  813  1
                   if (!Settings.getString(key, "").isEmpty()) {
      +  814  1
                       LOGGER.debug("Could not convert property '{}={}' to an int; using {} instead.", key, Settings.getString(key), defaultValue);
      +  815  
                   }
      -  817  1
                   value = defaultValue;
      -  818  0
               }
      -  819  1
               return value;
      +  816  1
                   value = defaultValue;
      +  817  0
               }
      +  818  1
               return value;
      +  819   +
           }
       820   -
           }
      +
       
       821   -
       
      +
           /**
       822   -
           /**
      -  823  
            * Returns a long value from the properties file. If the value was specified
      -  824   +  823  
            * as a system property or passed in via the -Dprop=value argument - this
      -  825   +  824  
            * method will return the value from the system properties before the values
      -  826   +  825  
            * in the contained configuration file.
      +  826   +
            *
       827   -
            *
      +
            * @param key the key to lookup within the properties file
       828   -
            * @param key the key to lookup within the properties file
      +
            * @return the property from the properties file
       829   -
            * @return the property from the properties file
      +
            * @throws InvalidSettingException is thrown if there is an error retrieving
       830   -
            * @throws InvalidSettingException is thrown if there is an error retrieving
      +
            * the setting
       831   -
            * the setting
      +
            */
       832   -
            */
      -  833  
           public static long getLong(String key) throws InvalidSettingException {
      -  834   +  833  
               try {
      -  835  1
                   return Long.parseLong(Settings.getString(key));
      -  836  0
               } catch (NumberFormatException ex) {
      -  837  0
                   throw new InvalidSettingException("Could not convert property '" + key + "' to a long.", ex);
      +  834  1
                   return Long.parseLong(Settings.getString(key));
      +  835  0
               } catch (NumberFormatException ex) {
      +  836  0
                   throw new InvalidSettingException("Could not convert property '" + key + "' to a long.", ex);
      +  837   +
               }
       838   -
               }
      +
           }
       839   -
           }
      +
       
       840   -
       
      +
           /**
       841   -
           /**
      +
            * Returns a boolean value from the properties file. If the value was
       842   -
            * Returns a boolean value from the properties file. If the value was
      +
            * specified as a system property or passed in via the
       843   -
            * specified as a system property or passed in via the
      +
            * <code>-Dprop=value</code> argument this method will return the value from
       844   -
            * <code>-Dprop=value</code> argument this method will return the value from
      +
            * the system properties before the values in the contained configuration
       845   -
            * the system properties before the values in the contained configuration
      +
            * file.
       846   -
            * file.
      +
            *
       847   -
            *
      +
            * @param key the key to lookup within the properties file
       848   -
            * @param key the key to lookup within the properties file
      +
            * @return the property from the properties file
       849   -
            * @return the property from the properties file
      +
            * @throws InvalidSettingException is thrown if there is an error retrieving
       850   -
            * @throws InvalidSettingException is thrown if there is an error retrieving
      +
            * the setting
       851   -
            * the setting
      +
            */
       852   -
            */
      -  853  
           public static boolean getBoolean(String key) throws InvalidSettingException {
      -  854  1
               return Boolean.parseBoolean(Settings.getString(key));
      +  853  1
               return Boolean.parseBoolean(Settings.getString(key));
      +  854   +
           }
       855   -
           }
      +
       
       856   -
       
      +
           /**
       857   -
           /**
      -  858  
            * Returns a boolean value from the properties file. If the value was
      -  859   +  858  
            * specified as a system property or passed in via the
      -  860   +  859  
            * <code>-Dprop=value</code> argument this method will return the value from
      -  861   +  860  
            * the system properties before the values in the contained configuration
      -  862   +  861  
            * file.
      +  862   +
            *
       863   -
            *
      -  864  
            * @param key the key to lookup within the properties file
      -  865   +  864  
            * @param defaultValue the default value to return if the setting does not
      -  866   +  865  
            * exist
      -  867   +  866  
            * @return the property from the properties file
      -  868   +  867  
            * @throws InvalidSettingException is thrown if there is an error retrieving
      -  869   +  868  
            * the setting
      +  869   +
            */
       870   -
            */
      -  871  
           public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException {
      -  872  1
               return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue)));
      +  871  1
               return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue)));
      +  872   +
           }
       873   -
           }
      +
       
       874   -
       
      +
           /**
       875   -
           /**
      -  876  
            * Returns a connection string from the configured properties. If the
      -  877   +  876  
            * connection string contains a %s, this method will determine the 'data'
      -  878   +  877  
            * directory and replace the %s with the path to the data directory. If the
      -  879   +  878  
            * data directory does not exists it will be created.
      +  879   +
            *
       880   -
            *
      -  881  
            * @param connectionStringKey the property file key for the connection
      -  882   +  881  
            * string
      -  883   +  882  
            * @param dbFileNameKey the settings key for the db filename
      -  884   +  883  
            * @return the connection string
      -  885   +  884  
            * @throws IOException thrown the data directory cannot be created
      -  886   +  885  
            * @throws InvalidSettingException thrown if there is an invalid setting
      +  886   +
            */
       887   -
            */
      -  888  
           public static String getConnectionString(String connectionStringKey, String dbFileNameKey)
      -  889   +  888  
                   throws IOException, InvalidSettingException {
      -  890  2
               final String connStr = Settings.getString(connectionStringKey);
      -  891  2
               if (connStr == null) {
      -  892  1
                   final String msg = String.format("Invalid properties file; %s is missing.", connectionStringKey);
      -  893  1
                   throw new InvalidSettingException(msg);
      -  894   +  889  2
               final String connStr = Settings.getString(connectionStringKey);
      +  890  2
               if (connStr == null) {
      +  891  1
                   final String msg = String.format("Invalid properties file; %s is missing.", connectionStringKey);
      +  892  1
                   throw new InvalidSettingException(msg);
      +  893  
               }
      -  895  1
               if (connStr.contains("%s")) {
      -  896  1
                   final File directory = getDataDirectory();
      -  897  1
                   String fileName = null;
      -  898  1
                   if (dbFileNameKey != null) {
      -  899  1
                       fileName = Settings.getString(dbFileNameKey);
      -  900   +  894  1
               if (connStr.contains("%s")) {
      +  895  1
                   final File directory = getDataDirectory();
      +  896  1
                   String fileName = null;
      +  897  1
                   if (dbFileNameKey != null) {
      +  898  1
                       fileName = Settings.getString(dbFileNameKey);
      +  899  
                   }
      -  901  1
                   if (fileName == null) {
      -  902  0
                       final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.",
      -  903   +  900  1
                   if (fileName == null) {
      +  901  0
                       final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.",
      +  902  
                               dbFileNameKey);
      -  904  0
                       throw new InvalidSettingException(msg);
      -  905   +  903  0
                       throw new InvalidSettingException(msg);
      +  904   +
                   }
      +  905  1
                   if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) {
      +  906  1
                       fileName = fileName.substring(0, fileName.length() - 6);
      +  907  
                   }
      -  906  1
                   if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) {
      -  907  1
                       fileName = fileName.substring(0, fileName.length() - 6);
       908   -
                   }
      -  909  
                   // yes, for H2 this path won't actually exists - but this is sufficient to get the value needed
      -  910  1
                   final File dbFile = new File(directory, fileName);
      -  911  1
                   final String cString = String.format(connStr, dbFile.getCanonicalPath());
      -  912  1
                   LOGGER.debug("Connection String: '{}'", cString);
      -  913  1
                   return cString;
      -  914   +  909  1
                   final File dbFile = new File(directory, fileName);
      +  910  1
                   final String cString = String.format(connStr, dbFile.getCanonicalPath());
      +  911  1
                   LOGGER.debug("Connection String: '{}'", cString);
      +  912  1
                   return cString;
      +  913  
               }
      -  915  0
               return connStr;
      +  914  0
               return connStr;
      +  915   +
           }
       916   -
           }
      -  917  
       
      -  918   +  917  
           /**
      -  919   +  918  
            * Retrieves the directory that the JAR file exists in so that we can ensure
      -  920   +  919  
            * we always use a common data directory for the embedded H2 database. This
      -  921   +  920  
            * is public solely for some unit tests; otherwise this should be private.
      -  922   +  921  
            *
      -  923   +  922  
            * @return the data directory to store data files
      -  924   +  923  
            * @throws IOException is thrown if an IOException occurs of course...
      -  925   +  924  
            */
      -  926   +  925  
           public static File getDataDirectory() throws IOException {
      -  927  1
               final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY);
      -  928  1
               if (path.exists() || path.mkdirs()) {
      -  929  1
                   return path;
      -  930   +  926  1
               final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY);
      +  927  1
               if (path.exists() || path.mkdirs()) {
      +  928  1
                   return path;
      +  929  
               }
      -  931  0
               throw new IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath()));
      -  932   +  930  0
               throw new IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath()));
      +  931  
           }
      -  933   +  932  
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFactory.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFactory.html index bf5f16eab..1ebfb267f 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFactory.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFactory.html @@ -348,7 +348,7 @@  198  0
                   } catch (NoSuchAlgorithmException ex) {
       199  0
                       LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex);
       200  0
                   } catch (KeyManagementException ex) {
      -  201  0
                       LOGGER.debug("Key mnagement eception in SSLSocketFactoryEx", ex);
      +  201  0
                       LOGGER.debug("Key management exception in SSLSocketFactoryEx", ex);
       202  0
                   }
       203  
               }
      @@ -357,6 +357,6 @@
       }
      - + diff --git a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFailureException.html b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFailureException.html index e78bcda88..74e1682c9 100644 --- a/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFailureException.html +++ b/dependency-check-utils/cobertura/org.owasp.dependencycheck.utils.URLConnectionFailureException.html @@ -147,6 +147,6 @@
       }
      - + diff --git a/dependency-check-utils/dependency-analysis.html b/dependency-check-utils/dependency-analysis.html index 08e166ed1..3d246ed37 100644 --- a/dependency-check-utils/dependency-analysis.html +++ b/dependency-check-utils/dependency-analysis.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Dependencies Report @@ -52,7 +52,7 @@ @@ -86,7 +86,7 @@ Project Information - +
    73. @@ -168,6 +168,13 @@ Checkstyle
    74. + +
    75. + + + + PMD +
    76. diff --git a/dependency-check-utils/dependency-updates-report.html b/dependency-check-utils/dependency-updates-report.html index 4df223a06..48c8df47b 100644 --- a/dependency-check-utils/dependency-updates-report.html +++ b/dependency-check-utils/dependency-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Dependency Updates Report @@ -52,7 +52,7 @@ @@ -86,7 +86,7 @@ Project Information - +
    77. @@ -168,6 +168,13 @@ Checkstyle
    78. + +
    79. + + + + PMD +
    80. @@ -215,7 +222,7 @@ # of dependencies using the latest version available -21 +22 # of dependencies where the next version available is smaller than an incremental version update @@ -223,7 +230,7 @@ # of dependencies where the next version available is an incremental version update -1 +0 # of dependencies where the next version available is a minor version update @@ -296,15 +303,15 @@ 1.4.177 - + com.sun.mail mailapi -1.5.5 +1.5.6 jar -1.5.6 + @@ -500,16 +507,16 @@ - + org.apache.maven.plugin-tools maven-plugin-annotations -3.4 +3.5 jar -3.5 + @@ -584,7 +591,7 @@ 1.25 - + org.jsoup jsoup 1.9.2 @@ -593,7 +600,7 @@ jar - +1.10.1 @@ -747,13 +754,13 @@ jar Newer versions -1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192 Latest Minor +1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192
      1.4.193 Latest Minor

      com.sun.mail:mailapi

      - + @@ -762,7 +769,7 @@ - + @@ -771,10 +778,7 @@ - - - -
      Status There is at least one newer incremental version available. Incremental updates are typically passive.
       No newer versions available.
      Group Id com.sun.mail
      mailapi
      Current Version1.5.5
      1.5.6
      Scope
      Typejar
      Newer versions1.5.6 Next Incremental
      +jar

      commons-cli:commons-cli

      @@ -972,7 +976,7 @@ -
      jar
      Newer versions3.4 Next Minor
      +3.4 Next Minor
      3.5 Latest Minor

      org.apache.lucene:lucene-analyzers-common

      @@ -999,7 +1003,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-core

      @@ -1026,7 +1030,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-queryparser

      @@ -1053,7 +1057,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-test-framework

      @@ -1080,7 +1084,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.maven:maven-core

      @@ -1182,7 +1186,7 @@
      - + @@ -1191,7 +1195,7 @@ - + @@ -1200,10 +1204,7 @@ - - - -
      Status There is at least one newer minor version available. Minor updates are sometimes passive.
       No newer versions available.
      Group Id org.apache.maven.plugin-tools
      maven-plugin-annotations
      Current Version3.4
      3.5
      Scope
      Typejar
      Newer versions3.5 Next Minor
      +jar

      org.apache.maven.reporting:maven-reporting-api

      @@ -1353,13 +1354,13 @@ -
      jar
      Newer versions1.25 Next Minor
      1.26
      1.27 Latest Minor
      +1.25 Next Minor
      1.26
      1.27
      1.28
      1.29 Latest Minor

      org.jsoup:jsoup

      - + @@ -1377,7 +1378,10 @@ -
      Status No newer versions available.
       There is at least one newer minor version available. Minor updates are sometimes passive.
      Group Id org.jsoup
      Typejar
      +jar + +Newer versions +1.10.1 Next Minor

      org.slf4j:slf4j-api

      diff --git a/dependency-check-utils/findbugs.html b/dependency-check-utils/findbugs.html index 2b2ee1a69..d13735f0f 100644 --- a/dependency-check-utils/findbugs.html +++ b/dependency-check-utils/findbugs.html @@ -1,13 +1,13 @@ - + dependency-check-ant – FindBugs Bug Detector Report @@ -52,7 +52,7 @@ @@ -86,7 +86,7 @@ Project Information - +
    81. @@ -168,6 +168,13 @@ Checkstyle
    82. + +
    83. + + + + PMD +
    84. diff --git a/dependency-check-utils/index.html b/dependency-check-utils/index.html index ae00bf05b..ce2400a9f 100644 --- a/dependency-check-utils/index.html +++ b/dependency-check-utils/index.html @@ -1,13 +1,13 @@ - + dependency-check-ant – About @@ -52,7 +52,7 @@ @@ -86,7 +86,7 @@ Project Information - +
    85. diff --git a/dependency-check-utils/integration.html b/dependency-check-utils/integration.html index 9bd97a14a..9001fb594 100644 --- a/dependency-check-utils/integration.html +++ b/dependency-check-utils/integration.html @@ -1,13 +1,13 @@ - + dependency-check-ant – CI Management @@ -52,7 +52,7 @@ @@ -135,7 +135,7 @@
    86. - +
    87. diff --git a/dependency-check-utils/issue-tracking.html b/dependency-check-utils/issue-tracking.html index 520923975..451725598 100644 --- a/dependency-check-utils/issue-tracking.html +++ b/dependency-check-utils/issue-tracking.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Issue Management @@ -52,7 +52,7 @@ @@ -135,7 +135,7 @@
    88. - +
    89. diff --git a/dependency-check-utils/license.html b/dependency-check-utils/license.html index b942bf3d7..8c28b245e 100644 --- a/dependency-check-utils/license.html +++ b/dependency-check-utils/license.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Licenses @@ -52,7 +52,7 @@ @@ -135,7 +135,7 @@
    90. - +
    91. diff --git a/dependency-check-utils/mail-lists.html b/dependency-check-utils/mail-lists.html index a90511589..db68d0e9c 100644 --- a/dependency-check-utils/mail-lists.html +++ b/dependency-check-utils/mail-lists.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Mailing Lists @@ -52,7 +52,7 @@ @@ -135,7 +135,7 @@
    92. - +
    93. diff --git a/dependency-check-utils/plugin-updates-report.html b/dependency-check-utils/plugin-updates-report.html index 4e2caea57..8cb522c43 100644 --- a/dependency-check-utils/plugin-updates-report.html +++ b/dependency-check-utils/plugin-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Plugin Updates Report @@ -52,7 +52,7 @@ @@ -86,7 +86,7 @@ Project Information
    94. - +
    95. @@ -168,6 +168,13 @@ Checkstyle
    96. + +
    97. + + + + PMD +
    98. @@ -383,7 +390,7 @@ - + @@ -664,7 +671,7 @@ -
      org.apache.maven.plugins maven-resources-plugin3.0.03.0.1 maven-resources-plugin
      Current Version3.0.0
      +3.0.1

      Plugin org.apache.maven.plugins:maven-site-plugin

      diff --git a/dependency-check-utils/pmd.html b/dependency-check-utils/pmd.html index 94486ecfa..c078f60ed 100644 --- a/dependency-check-utils/pmd.html +++ b/dependency-check-utils/pmd.html @@ -1,13 +1,13 @@ - + dependency-check-ant – PMD Results @@ -52,7 +52,7 @@ @@ -221,14 +221,17 @@

      Files

      -

      org/owasp/dependencycheck/utils/Downloader.java

      +

      org/owasp/dependencycheck/utils/Checksum.java

      - -
      Violation Line
      Unnecessary use of fully qualified name 'String.format' due to existing static import 'java.lang.String.format'307
      +Useless parentheses. +71 + +Useless parentheses. +71 diff --git a/dependency-check-utils/project-info.html b/dependency-check-utils/project-info.html index a206d3e56..a08f7c86e 100644 --- a/dependency-check-utils/project-info.html +++ b/dependency-check-utils/project-info.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Information @@ -52,7 +52,7 @@ @@ -135,7 +135,7 @@ - +
    99. diff --git a/dependency-check-utils/project-reports.html b/dependency-check-utils/project-reports.html index e76522e74..8de03078a 100644 --- a/dependency-check-utils/project-reports.html +++ b/dependency-check-utils/project-reports.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Generated Reports @@ -52,7 +52,7 @@ @@ -86,7 +86,7 @@ Project Information
    100. - +
    101. Project Reports @@ -168,6 +168,13 @@ Checkstyle
    102. + +
    103. + + + + PMD +
    104. @@ -249,7 +256,10 @@ Provides details of the plugins used by this project which have newer versions available. Checkstyle -Report on coding style conventions. +Report on coding style conventions. + +PMD +Verification of coding rules. diff --git a/dependency-check-utils/project-summary.html b/dependency-check-utils/project-summary.html index fa3e33106..fd7273af7 100644 --- a/dependency-check-utils/project-summary.html +++ b/dependency-check-utils/project-summary.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Summary @@ -52,7 +52,7 @@ @@ -135,7 +135,7 @@ - +
    105. @@ -223,7 +223,7 @@ dependency-check-utils Version -1.4.3 +1.4.4 Type jar diff --git a/dependency-check-utils/source-repository.html b/dependency-check-utils/source-repository.html index 9d4e204f0..fc49c5fb4 100644 --- a/dependency-check-utils/source-repository.html +++ b/dependency-check-utils/source-repository.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Source Code Management @@ -52,7 +52,7 @@ @@ -135,7 +135,7 @@
    106. - +
    107. diff --git a/dependency-check-utils/surefire-report.html b/dependency-check-utils/surefire-report.html index 21d9c41d2..977b22d6a 100644 --- a/dependency-check-utils/surefire-report.html +++ b/dependency-check-utils/surefire-report.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Surefire Report @@ -52,7 +52,7 @@ @@ -86,7 +86,7 @@ Project Information
    108. - +
    109. @@ -168,6 +168,13 @@ Checkstyle
    110. + +
    111. + + + + PMD +
    112. @@ -244,7 +251,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.689
      +0.882

      Note: failures are anticipated and checked for with assertions while errors are unanticipated.


      Package List

      @@ -265,7 +272,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.689
      +0.882

      Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.

      org.owasp.dependencycheck.utils

      @@ -287,7 +294,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.492 +0.613 DownloaderTest @@ -305,7 +312,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.079 +0.07 FileUtilsTest @@ -314,7 +321,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.115 +0.195 SettingsTest @@ -323,7 +330,7 @@ function toggleDisplay(elementId) { 0 0 100% -0.003

      +0.004

      Test Cases

      [Summary] [Package List] [Test Cases]

      @@ -333,19 +340,19 @@ function toggleDisplay(elementId) { testGetChecksum_NoSuchAlgorithm -0.399 +0.527 testGetChecksum -0.005 +0.009 testGetMD5Checksum -0.001 +0 testGetChecksum_FileNotFound -0.001 +0.003 testGetHex @@ -353,7 +360,7 @@ function toggleDisplay(elementId) { testGetSHA1Checksum -0.001
      +0

      DownloaderTest

      @@ -367,11 +374,11 @@ function toggleDisplay(elementId) { - + -
      testResolveClassException0.078
      0.067
      testResolveClass0.001
      +0

      FileUtilsTest

      @@ -382,7 +389,7 @@ function toggleDisplay(elementId) { -
      testDelete0.114
      +0.195

      SettingsTest

      @@ -397,7 +404,7 @@ function toggleDisplay(elementId) { - + diff --git a/dependency-check-utils/taglist.html b/dependency-check-utils/taglist.html index 22c40db9d..ec4f01f7a 100644 --- a/dependency-check-utils/taglist.html +++ b/dependency-check-utils/taglist.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Tag List report @@ -52,7 +52,7 @@ @@ -86,7 +86,7 @@ Project Information - +
    113. @@ -168,6 +168,13 @@ Checkstyle
    114. + +
    115. + + + + PMD +
    116. @@ -230,7 +237,7 @@ -
      testMergeProperties_String0.001
      0
      testGetDataFile Line
      add the FTP protocol?238
      +245 diff --git a/dependency-check-utils/team-list.html b/dependency-check-utils/team-list.html index e20560ad4..5f0b6d0f4 100644 --- a/dependency-check-utils/team-list.html +++ b/dependency-check-utils/team-list.html @@ -1,13 +1,13 @@ - + dependency-check-ant – Project Team @@ -52,7 +52,7 @@ @@ -135,7 +135,7 @@ - +
    117. diff --git a/dependency-check-utils/xref-test/index.html b/dependency-check-utils/xref-test/index.html index 1635bc815..c07f8efae 100644 --- a/dependency-check-utils/xref-test/index.html +++ b/dependency-check-utils/xref-test/index.html @@ -4,7 +4,7 @@ - Dependency-Check Utils 1.4.3 Reference + Dependency-Check Utils 1.4.4 Reference diff --git a/dependency-check-utils/xref-test/org/owasp/dependencycheck/utils/package-frame.html b/dependency-check-utils/xref-test/org/owasp/dependencycheck/utils/package-frame.html index 8ac1facc1..1e2cfd5be 100644 --- a/dependency-check-utils/xref-test/org/owasp/dependencycheck/utils/package-frame.html +++ b/dependency-check-utils/xref-test/org/owasp/dependencycheck/utils/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Utils 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Utils 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-utils/xref-test/org/owasp/dependencycheck/utils/package-summary.html b/dependency-check-utils/xref-test/org/owasp/dependencycheck/utils/package-summary.html index ad19c5d8f..0b699e716 100644 --- a/dependency-check-utils/xref-test/org/owasp/dependencycheck/utils/package-summary.html +++ b/dependency-check-utils/xref-test/org/owasp/dependencycheck/utils/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Utils 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Utils 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-utils/xref-test/overview-frame.html b/dependency-check-utils/xref-test/overview-frame.html index 46b9088ae..9318d2cec 100644 --- a/dependency-check-utils/xref-test/overview-frame.html +++ b/dependency-check-utils/xref-test/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Utils 1.4.3 Reference + Dependency-Check Utils 1.4.4 Reference diff --git a/dependency-check-utils/xref-test/overview-summary.html b/dependency-check-utils/xref-test/overview-summary.html index b43685082..87591a21d 100644 --- a/dependency-check-utils/xref-test/overview-summary.html +++ b/dependency-check-utils/xref-test/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Utils 1.4.3 Reference + Dependency-Check Utils 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Utils 1.4.3 Reference

      +

      Dependency-Check Utils 1.4.4 Reference

      diff --git a/dependency-check-utils/xref/index.html b/dependency-check-utils/xref/index.html index 1635bc815..c07f8efae 100644 --- a/dependency-check-utils/xref/index.html +++ b/dependency-check-utils/xref/index.html @@ -4,7 +4,7 @@ - Dependency-Check Utils 1.4.3 Reference + Dependency-Check Utils 1.4.4 Reference diff --git a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Checksum.html b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Checksum.html index 1ca6881e7..2ed3cd4cc 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Checksum.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Checksum.html @@ -31,7 +31,7 @@ 23import java.io.File; 24import java.io.FileInputStream; 25import java.io.IOException; -26import java.nio.MappedByteBuffer; +26import java.nio.ByteBuffer; 27import java.nio.channels.FileChannel; 28import java.security.MessageDigest; 29import java.security.NoSuchAlgorithmException; @@ -57,99 +57,104 @@ 4950/**51 * <p> -52 * Creates the cryptographic checksum of a given file using the specified algorithm.</p> -53 * -54 * @param algorithm the algorithm to use to calculate the checksum -55 * @param file the file to calculate the checksum for -56 * @return the checksum -57 * @throws IOException when the file does not exist -58 * @throws NoSuchAlgorithmException when an algorithm is specified that does not exist -59 */ -60publicstatic byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException { -61final MessageDigest digest = MessageDigest.getInstance(algorithm); -62 FileInputStream fis = null; -63try { -64 fis = new FileInputStream(file); -65final FileChannel ch = fis.getChannel(); -66long remainingToRead = file.length(); -67long start = 0; -68while (remainingToRead > 0) { -69long amountToRead; -70if (remainingToRead > Integer.MAX_VALUE) { -71 remainingToRead -= Integer.MAX_VALUE; -72 amountToRead = Integer.MAX_VALUE; -73 } else { -74 amountToRead = remainingToRead; -75 remainingToRead = 0; -76 } -77final MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead); -78 digest.update(byteBuffer); -79 start += amountToRead; -80 } -81 } finally { -82if (fis != null) { -83try { -84 fis.close(); -85 } catch (IOException ex) { -86 LOGGER.trace("Error closing file '{}'.", file.getName(), ex); -87 } -88 } -89 } -90return digest.digest(); -91 } -92 -93/** -94 * Calculates the MD5 checksum of a specified file. -95 * -96 * @param file the file to generate the MD5 checksum -97 * @return the hex representation of the MD5 hash -98 * @throws IOException when the file passed in does not exist -99 * @throws NoSuchAlgorithmException when the MD5 algorithm is not available -100 */ -101publicstatic String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException { -102final byte[] b = getChecksum("MD5", file); -103return getHex(b); -104 } -105 -106/** -107 * Calculates the SHA1 checksum of a specified file. -108 * -109 * @param file the file to generate the MD5 checksum -110 * @return the hex representation of the SHA1 hash -111 * @throws IOException when the file passed in does not exist -112 * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available -113 */ -114publicstatic String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException { -115final byte[] b = getChecksum("SHA1", file); -116return getHex(b); -117 } -118/** -119 * Hex code characters used in getHex. -120 */ -121privatestaticfinal String HEXES = "0123456789abcdef"; -122 +52 * Creates the cryptographic checksum of a given file using the specified +53 * algorithm.</p> +54 * +55 * @param algorithm the algorithm to use to calculate the checksum +56 * @param file the file to calculate the checksum for +57 * @return the checksum +58 * @throws IOException when the file does not exist +59 * @throws NoSuchAlgorithmException when an algorithm is specified that does +60 * not exist +61 */ +62publicstatic byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException { +63final MessageDigest md = MessageDigest.getInstance(algorithm); +64 FileInputStream fis = null; +65 FileChannel ch = null; +66try { +67 fis = new FileInputStream(file); +68 ch = fis.getChannel(); +69final ByteBuffer buf = ByteBuffer.allocateDirect(8192); +70int b = ch.read(buf); +71while ((b != -1) && (b != 0)) { +72 buf.flip(); +73final byte[] bytes = new byte[b]; +74 buf.get(bytes); +75 md.update(bytes, 0, b); +76 buf.clear(); +77 b = ch.read(buf); +78 } +79return md.digest(); +80 } finally { +81if (ch != null) { +82try { +83 ch.close(); +84 } catch (IOException ex) { +85 LOGGER.trace("Error closing channel '{}'.", file.getName(), ex); +86 } +87 } +88if (fis != null) { +89try { +90 fis.close(); +91 } catch (IOException ex) { +92 LOGGER.trace("Error closing file '{}'.", file.getName(), ex); +93 } +94 } +95 } +96 } +97 +98/** +99 * Calculates the MD5 checksum of a specified file. +100 * +101 * @param file the file to generate the MD5 checksum +102 * @return the hex representation of the MD5 hash +103 * @throws IOException when the file passed in does not exist +104 * @throws NoSuchAlgorithmException when the MD5 algorithm is not available +105 */ +106publicstatic String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException { +107final byte[] b = getChecksum("MD5", file); +108return getHex(b); +109 } +110 +111/** +112 * Calculates the SHA1 checksum of a specified file. +113 * +114 * @param file the file to generate the MD5 checksum +115 * @return the hex representation of the SHA1 hash +116 * @throws IOException when the file passed in does not exist +117 * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available +118 */ +119publicstatic String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException { +120final byte[] b = getChecksum("SHA1", file); +121return getHex(b); +122 } 123/** -124 * <p> -125 * Converts a byte array into a hex string.</p> -126 * -127 * <p> -128 * This method was copied from <a -129 * href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p> -130 * -131 * @param raw a byte array -132 * @return the hex representation of the byte array -133 */ -134publicstatic String getHex(byte[] raw) { -135if (raw == null) { -136returnnull; -137 } -138final StringBuilder hex = new StringBuilder(2 * raw.length); -139for (final byte b : raw) { -140 hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F)); -141 } -142return hex.toString(); -143 } -144 } +124 * Hex code characters used in getHex. +125 */ +126privatestaticfinal String HEXES = "0123456789abcdef"; +127 +128/** +129 * <p> +130 * Converts a byte array into a hex string.</p> +131 * +132 * <p> +133 * This method was copied from <a +134 * href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p> +135 * +136 * @param raw a byte array +137 * @return the hex representation of the byte array +138 */ +139publicstatic String getHex(byte[] raw) { +140if (raw == null) { +141returnnull; +142 } +143final StringBuilder hex = new StringBuilder(2 * raw.length); +144for (final byte b : raw) { +145 hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F)); +146 } +147return hex.toString(); +148 } +149 }
      diff --git a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Downloader.html b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Downloader.html index 1be66e97c..1009b1619 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Downloader.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Downloader.html @@ -159,204 +159,211 @@ 151 } finally { 152 conn = null; 153 } -154final String msg = format("Error downloading file %s; unable to connect.", url.toString()); -155thrownewDownloadFailedException(msg, ex); -156 } -157 -158final String encoding = conn.getContentEncoding(); -159 BufferedOutputStream writer = null; -160 InputStream reader = null; -161try { -162if (encoding != null && "gzip".equalsIgnoreCase(encoding)) { -163 reader = new GZIPInputStream(conn.getInputStream()); -164 } elseif (encoding != null && "deflate".equalsIgnoreCase(encoding)) { -165 reader = new InflaterInputStream(conn.getInputStream()); -166 } else { -167 reader = conn.getInputStream(); -168 } -169 -170 writer = new BufferedOutputStream(new FileOutputStream(outputPath)); -171final byte[] buffer = new byte[4096]; -172int bytesRead; -173while ((bytesRead = reader.read(buffer)) > 0) { -174 writer.write(buffer, 0, bytesRead); +154if ("Connection reset".equalsIgnoreCase(ex.getMessage())) { +155final String msg = format("TLS Connection Reset%nPlease see " +156 + "http://jeremylong.github.io/DependencyCheck/general/tlsfailures.html " +157 + "for more information regarding how to resolve the issue."); +158 LOGGER.error(msg); +159thrownewDownloadFailedException(msg, ex); +160 } +161final String msg = format("Error downloading file %s; unable to connect.", url.toString()); +162thrownewDownloadFailedException(msg, ex); +163 } +164 +165final String encoding = conn.getContentEncoding(); +166 BufferedOutputStream writer = null; +167 InputStream reader = null; +168try { +169if (encoding != null && "gzip".equalsIgnoreCase(encoding)) { +170 reader = new GZIPInputStream(conn.getInputStream()); +171 } elseif (encoding != null && "deflate".equalsIgnoreCase(encoding)) { +172 reader = new InflaterInputStream(conn.getInputStream()); +173 } else { +174 reader = conn.getInputStream(); 175 } -176 LOGGER.debug("Download of {} complete", url.toString()); -177 } catch (IOException ex) { -178 checkForCommonExceptionTypes(ex); -179final String msg = format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n", -180 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); -181thrownewDownloadFailedException(msg, ex); -182 } catch (Throwable ex) { -183final String msg = format("Unexpected exception saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n", -184 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); -185thrownewDownloadFailedException(msg, ex); -186 } finally { -187if (writer != null) { -188try { -189 writer.close(); -190 } catch (IOException ex) { -191 LOGGER.trace("Error closing the writer in Downloader.", ex); -192 } -193 } -194if (reader != null) { +176 +177 writer = new BufferedOutputStream(new FileOutputStream(outputPath)); +178final byte[] buffer = new byte[4096]; +179int bytesRead; +180while ((bytesRead = reader.read(buffer)) > 0) { +181 writer.write(buffer, 0, bytesRead); +182 } +183 LOGGER.debug("Download of {} complete", url.toString()); +184 } catch (IOException ex) { +185 checkForCommonExceptionTypes(ex); +186final String msg = format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n", +187 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); +188thrownewDownloadFailedException(msg, ex); +189 } catch (Throwable ex) { +190final String msg = format("Unexpected exception saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n", +191 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); +192thrownewDownloadFailedException(msg, ex); +193 } finally { +194if (writer != null) { 195try { -196 reader.close(); +196 writer.close(); 197 } catch (IOException ex) { -198 LOGGER.trace("Error closing the reader in Downloader.", ex); +198 LOGGER.trace("Error closing the writer in Downloader.", ex); 199 } 200 } -201try { -202 conn.disconnect(); -203 } finally { -204 conn = null; -205 } -206 } -207 } -208 } -209 -210/** -211 * Makes an HTTP Head request to retrieve the last modified date of the -212 * given URL. If the file:// protocol is specified, then the lastTimestamp -213 * of the file is returned. -214 * -215 * @param url the URL to retrieve the timestamp from -216 * @return an epoch timestamp -217 * @throws DownloadFailedException is thrown if an exception occurs making -218 * the HTTP request -219 */ -220publicstaticlong getLastModified(URL url) throws DownloadFailedException { -221return getLastModified(url, false); -222 } -223 -224/** -225 * Makes an HTTP Head request to retrieve the last modified date of the -226 * given URL. If the file:// protocol is specified, then the lastTimestamp -227 * of the file is returned. -228 * -229 * @param url the URL to retrieve the timestamp from -230 * @param isRetry indicates if this is a retry - to prevent endless loop and -231 * stack overflow -232 * @return an epoch timestamp -233 * @throws DownloadFailedException is thrown if an exception occurs making -234 * the HTTP request -235 */ -236privatestaticlong getLastModified(URL url, boolean isRetry) throws DownloadFailedException { -237long timestamp = 0; -238//TODO add the FTP protocol? -239if ("file".equalsIgnoreCase(url.getProtocol())) { -240 File lastModifiedFile; -241try { -242 lastModifiedFile = new File(url.toURI()); -243 } catch (URISyntaxException ex) { -244final String msg = format("Unable to locate '%s'", url.toString()); -245thrownewDownloadFailedException(msg); -246 } -247 timestamp = lastModifiedFile.lastModified(); -248 } else { -249final String httpMethod = determineHttpMethod(); -250 HttpURLConnection conn = null; -251try { -252 conn = URLConnectionFactory.createHttpURLConnection(url); -253 conn.setRequestMethod(httpMethod); -254 conn.connect(); -255finalint t = conn.getResponseCode(); -256if (t >= 200 && t < 300) { -257 timestamp = conn.getLastModified(); -258 } else { -259thrownewDownloadFailedException(format("%s request returned a non-200 status code", httpMethod)); -260 } -261 } catch (URLConnectionFailureException ex) { -262thrownewDownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex); -263 } catch (IOException ex) { -264 checkForCommonExceptionTypes(ex); -265 LOGGER.error("IO Exception: " + ex.getMessage()); -266 LOGGER.debug("Exception details", ex); -267if (ex.getCause() != null) { -268 LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause()); -269 } -270try { -271//retry -272if (!isRetry && Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP)) { -273 Settings.setBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, false); -274return getLastModified(url, true); -275 } -276 } catch (InvalidSettingException ex1) { -277 LOGGER.debug("invalid setting?", ex); -278 } -279thrownewDownloadFailedException(format("Error making HTTP %s request.", httpMethod), ex); -280 } finally { -281if (conn != null) { -282try { -283 conn.disconnect(); -284 } finally { -285 conn = null; -286 } -287 } -288 } -289 } -290return timestamp; -291 } -292 -293/** -294 * Analyzes the IOException, logs the appropriate information for debugging -295 * purposes, and then throws a DownloadFailedException that wraps the IO -296 * Exception for common IO Exceptions. This is to provide additional details -297 * to assist in resolution of the exception. -298 * -299 * @param ex the original exception -300 * @throws DownloadFailedException a wrapper exception that contains the -301 * original exception as the cause -302 */ -303protectedstaticsynchronizedvoid checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException { -304 Throwable cause = ex; -305while (cause != null) { -306if (cause instanceof java.net.UnknownHostException) { -307final String msg = format("Unable to resolve domain '%s'", cause.getMessage()); -308 LOGGER.error(msg); -309thrownewDownloadFailedException(msg); -310 } -311if (cause instanceof InvalidAlgorithmParameterException) { -312final String keystore = System.getProperty("javax.net.ssl.keyStore"); -313final String version = System.getProperty("java.version"); -314final String vendor = System.getProperty("java.vendor"); -315 LOGGER.info("Error making HTTPS request - InvalidAlgorithmParameterException"); -316 LOGGER.info("There appears to be an issue with the installation of Java and the cacerts." -317 + "See closed issue #177 here: https://github.com/jeremylong/DependencyCheck/issues/177"); -318 LOGGER.info("Java Info:\njavax.net.ssl.keyStore='{}'\njava.version='{}'\njava.vendor='{}'", -319 keystore, version, vendor); -320thrownewDownloadFailedException("Error making HTTPS request. Please see the log for more details."); -321 } -322 cause = cause.getCause(); -323 } -324 } -325 -326/** -327 * Returns the HEAD or GET HTTP method. HEAD is the default. -328 * -329 * @return the HTTP method to use -330 */ -331privatestatic String determineHttpMethod() { -332return isQuickQuery() ? HEAD : GET; -333 } -334 -335/** -336 * Determines if the HTTP method GET or HEAD should be used to check the -337 * timestamp on external resources. -338 * -339 * @return true if configured to use HEAD requests -340 */ -341privatestaticboolean isQuickQuery() { -342boolean quickQuery; -343 -344try { -345 quickQuery = Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, true); -346 } catch (InvalidSettingException e) { -347 quickQuery = true; -348 } -349return quickQuery; -350 } -351 } +201if (reader != null) { +202try { +203 reader.close(); +204 } catch (IOException ex) { +205 LOGGER.trace("Error closing the reader in Downloader.", ex); +206 } +207 } +208try { +209 conn.disconnect(); +210 } finally { +211 conn = null; +212 } +213 } +214 } +215 } +216 +217/** +218 * Makes an HTTP Head request to retrieve the last modified date of the +219 * given URL. If the file:// protocol is specified, then the lastTimestamp +220 * of the file is returned. +221 * +222 * @param url the URL to retrieve the timestamp from +223 * @return an epoch timestamp +224 * @throws DownloadFailedException is thrown if an exception occurs making +225 * the HTTP request +226 */ +227publicstaticlong getLastModified(URL url) throws DownloadFailedException { +228return getLastModified(url, false); +229 } +230 +231/** +232 * Makes an HTTP Head request to retrieve the last modified date of the +233 * given URL. If the file:// protocol is specified, then the lastTimestamp +234 * of the file is returned. +235 * +236 * @param url the URL to retrieve the timestamp from +237 * @param isRetry indicates if this is a retry - to prevent endless loop and +238 * stack overflow +239 * @return an epoch timestamp +240 * @throws DownloadFailedException is thrown if an exception occurs making +241 * the HTTP request +242 */ +243privatestaticlong getLastModified(URL url, boolean isRetry) throws DownloadFailedException { +244long timestamp = 0; +245//TODO add the FTP protocol? +246if ("file".equalsIgnoreCase(url.getProtocol())) { +247 File lastModifiedFile; +248try { +249 lastModifiedFile = new File(url.toURI()); +250 } catch (URISyntaxException ex) { +251final String msg = format("Unable to locate '%s'", url.toString()); +252thrownewDownloadFailedException(msg); +253 } +254 timestamp = lastModifiedFile.lastModified(); +255 } else { +256final String httpMethod = determineHttpMethod(); +257 HttpURLConnection conn = null; +258try { +259 conn = URLConnectionFactory.createHttpURLConnection(url); +260 conn.setRequestMethod(httpMethod); +261 conn.connect(); +262finalint t = conn.getResponseCode(); +263if (t >= 200 && t < 300) { +264 timestamp = conn.getLastModified(); +265 } else { +266thrownewDownloadFailedException(format("%s request returned a non-200 status code", httpMethod)); +267 } +268 } catch (URLConnectionFailureException ex) { +269thrownewDownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex); +270 } catch (IOException ex) { +271 checkForCommonExceptionTypes(ex); +272 LOGGER.error("IO Exception: " + ex.getMessage()); +273 LOGGER.debug("Exception details", ex); +274if (ex.getCause() != null) { +275 LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause()); +276 } +277try { +278//retry +279if (!isRetry && Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP)) { +280 Settings.setBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, false); +281return getLastModified(url, true); +282 } +283 } catch (InvalidSettingException ex1) { +284 LOGGER.debug("invalid setting?", ex); +285 } +286thrownewDownloadFailedException(format("Error making HTTP %s request.", httpMethod), ex); +287 } finally { +288if (conn != null) { +289try { +290 conn.disconnect(); +291 } finally { +292 conn = null; +293 } +294 } +295 } +296 } +297return timestamp; +298 } +299 +300/** +301 * Analyzes the IOException, logs the appropriate information for debugging +302 * purposes, and then throws a DownloadFailedException that wraps the IO +303 * Exception for common IO Exceptions. This is to provide additional details +304 * to assist in resolution of the exception. +305 * +306 * @param ex the original exception +307 * @throws DownloadFailedException a wrapper exception that contains the +308 * original exception as the cause +309 */ +310protectedstaticsynchronizedvoid checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException { +311 Throwable cause = ex; +312while (cause != null) { +313if (cause instanceof java.net.UnknownHostException) { +314final String msg = format("Unable to resolve domain '%s'", cause.getMessage()); +315 LOGGER.error(msg); +316thrownewDownloadFailedException(msg); +317 } +318if (cause instanceof InvalidAlgorithmParameterException) { +319final String keystore = System.getProperty("javax.net.ssl.keyStore"); +320final String version = System.getProperty("java.version"); +321final String vendor = System.getProperty("java.vendor"); +322 LOGGER.info("Error making HTTPS request - InvalidAlgorithmParameterException"); +323 LOGGER.info("There appears to be an issue with the installation of Java and the cacerts." +324 + "See closed issue #177 here: https://github.com/jeremylong/DependencyCheck/issues/177"); +325 LOGGER.info("Java Info:\njavax.net.ssl.keyStore='{}'\njava.version='{}'\njava.vendor='{}'", +326 keystore, version, vendor); +327thrownewDownloadFailedException("Error making HTTPS request. Please see the log for more details."); +328 } +329 cause = cause.getCause(); +330 } +331 } +332 +333/** +334 * Returns the HEAD or GET HTTP method. HEAD is the default. +335 * +336 * @return the HTTP method to use +337 */ +338privatestatic String determineHttpMethod() { +339return isQuickQuery() ? HEAD : GET; +340 } +341 +342/** +343 * Determines if the HTTP method GET or HEAD should be used to check the +344 * timestamp on external resources. +345 * +346 * @return true if configured to use HEAD requests +347 */ +348privatestaticboolean isQuickQuery() { +349boolean quickQuery; +350 +351try { +352 quickQuery = Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, true); +353 } catch (InvalidSettingException e) { +354 quickQuery = true; +355 } +356return quickQuery; +357 } +358 }
      diff --git a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/FileUtils.html b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/FileUtils.html index 3c7a93528..1c80c2f61 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/FileUtils.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/FileUtils.html @@ -73,51 +73,73 @@ 65 } 6667/** -68 * Deletes a file. If the File is a directory it will recursively delete the contents. -69 * -70 * @param file the File to delete -71 * @return true if the file was deleted successfully, otherwise false -72 */ -73publicstaticboolean delete(File file) { -74finalboolean success = org.apache.commons.io.FileUtils.deleteQuietly(file); -75if (!success) { -76 LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath()); -77 file.deleteOnExit(); -78 } -79return success; -80 } -81 -82/** -83 * Generates a new temporary file name that is guaranteed to be unique. -84 * -85 * @param prefix the prefix for the file name to generate -86 * @param extension the extension of the generated file name -87 * @return a temporary File -88 * @throws java.io.IOException thrown if the temporary folder could not be created -89 */ -90publicstatic File getTempFile(String prefix, String extension) throws IOException { -91final File dir = Settings.getTempDirectory(); -92final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension); -93final File tempFile = new File(dir, tempFileName); -94if (tempFile.exists()) { -95return getTempFile(prefix, extension); -96 } -97return tempFile; -98 } -99 -100/** -101 * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows -102 * -103 * @return a String containing the bit bucket -104 */ -105publicstatic String getBitBucket() { -106if (SystemUtils.IS_OS_WINDOWS) { -107return BIT_BUCKET_WIN; -108 } else { -109return BIT_BUCKET_UNIX; -110 } -111 } -112 } +68 * Deletes a file. If the File is a directory it will recursively delete the +69 * contents. +70 * +71 * @param file the File to delete +72 * @return true if the file was deleted successfully, otherwise false +73 */ +74publicstaticboolean delete(File file) { +75finalboolean success = org.apache.commons.io.FileUtils.deleteQuietly(file); +76if (!success) { +77 LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath()); +78 file.deleteOnExit(); +79 } +80return success; +81 } +82 +83/** +84 * Creates a unique temporary directory in the given directory. +85 * +86 * @param base the base directory to create a temporary directory within +87 * @return the temporary directory +88 * @throws IOException thrown when a directory cannot be created within the +89 * base directory +90 */ +91publicstatic File createTempDirectory(File base) throws IOException { +92final File tempDir = new File(base, "dctemp" + UUID.randomUUID().toString()); +93if (tempDir.exists()) { +94return createTempDirectory(base); +95 } +96if (!tempDir.mkdirs()) { +97thrownew IOException("Could not create temp directory `" + tempDir.getAbsolutePath() + "`"); +98 } +99return tempDir; +100 } +101 +102/** +103 * Generates a new temporary file name that is guaranteed to be unique. +104 * +105 * @param prefix the prefix for the file name to generate +106 * @param extension the extension of the generated file name +107 * @return a temporary File +108 * @throws java.io.IOException thrown if the temporary folder could not be +109 * created +110 */ +111publicstatic File getTempFile(String prefix, String extension) throws IOException { +112final File dir = Settings.getTempDirectory(); +113final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension); +114final File tempFile = new File(dir, tempFileName); +115if (tempFile.exists()) { +116return getTempFile(prefix, extension); +117 } +118return tempFile; +119 } +120 +121/** +122 * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for +123 * Windows +124 * +125 * @return a String containing the bit bucket +126 */ +127publicstatic String getBitBucket() { +128if (SystemUtils.IS_OS_WINDOWS) { +129return BIT_BUCKET_WIN; +130 } else { +131return BIT_BUCKET_UNIX; +132 } +133 } +134 }
      diff --git a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html index cd0018537..60955f064 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html @@ -251,50 +251,57 @@ 243 * @return the protocol list244 */245protected String[] getProtocolList() { -246final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"}; +246 SSLSocket socket = null; 247 String[] availableProtocols = null; -248 -249 SSLSocket socket = null; -250 -251try { -252final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -253 socket = (SSLSocket) factory.createSocket(); -254 -255 availableProtocols = socket.getSupportedProtocols(); -256 Arrays.sort(availableProtocols); -257 } catch (Exception ex) { -258 LOGGER.debug("Error getting protocol list, using TLSv1", ex); -259returnnew String[]{"TLSv1"}; -260 } finally { -261if (socket != null) { -262try { -263 socket.close(); -264 } catch (IOException ex) { -265 LOGGER.trace("Error closing socket", ex); -266 } -267 } -268 } -269 -270final List<String> aa = new ArrayList<String>(); -271for (String preferredProtocol : preferredProtocols) { -272finalint idx = Arrays.binarySearch(availableProtocols, preferredProtocol); -273if (idx >= 0) { -274 aa.add(preferredProtocol); -275 } -276 } -277 -278return aa.toArray(new String[0]); -279 } -280 -281/** -282 * The SSL context. -283 */ -284private SSLContext sslCtxt; -285/** -286 * The protocols. -287 */ -288private String[] protocols; -289 } +248final String[] preferredProtocols = Settings.getString( +249 Settings.KEYS.DOWNLOADER_TLS_PROTOCOL_LIST, +250"TLSv1,TLSv1.1,TLSv1.2,TLSv1.3") +251 .split(","); +252try { +253final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +254 socket = (SSLSocket) factory.createSocket(); +255 +256 availableProtocols = socket.getSupportedProtocols(); +257 Arrays.sort(availableProtocols); +258if (LOGGER.isDebugEnabled()) { +259 LOGGER.debug("Available Protocols:"); +260for (String p : availableProtocols) { +261 LOGGER.debug(p); +262 } +263 } +264 } catch (Exception ex) { +265 LOGGER.debug("Error getting protocol list, using TLSv1", ex); +266returnnew String[]{"TLSv1"}; +267 } finally { +268if (socket != null) { +269try { +270 socket.close(); +271 } catch (IOException ex) { +272 LOGGER.trace("Error closing socket", ex); +273 } +274 } +275 } +276 +277final List<String> aa = new ArrayList<String>(); +278for (String preferredProtocol : preferredProtocols) { +279finalint idx = Arrays.binarySearch(availableProtocols, preferredProtocol); +280if (idx >= 0) { +281 aa.add(preferredProtocol); +282 } +283 } +284 +285return aa.toArray(new String[0]); +286 } +287 +288/** +289 * The SSL context. +290 */ +291private SSLContext sslCtxt; +292/** +293 * The protocols. +294 */ +295private String[] protocols; +296 }
      diff --git a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Settings.html b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Settings.html index db25a5eb5..dc706e95e 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Settings.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/Settings.html @@ -301,644 +301,643 @@ 293 */294publicstaticfinal String ANALYZER_COCOAPODS_ENABLED = "analyzer.cocoapods.enabled"; 295/** -296 * The properties key for whether the SWIFT package manager analyzer is enabled. -297 */ -298publicstaticfinal String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled"; -299/** -300 * The properties key for the Central search URL. -301 */ -302publicstaticfinal String ANALYZER_CENTRAL_URL = "analyzer.central.url"; -303/** -304 * The path to mono, if available. -305 */ -306publicstaticfinal String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path"; -307/** -308 * The path to bundle-audit, if available. -309 */ -310publicstaticfinal String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path"; -311/** -312 * The additional configured zip file extensions, if available. -313 */ -314publicstaticfinal String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip"; -315/** -316 * The key to obtain the path to the VFEED data file. -317 */ -318publicstaticfinal String VFEED_DATA_FILE = "vfeed.data_file"; -319/** -320 * The key to obtain the VFEED connection string. -321 */ -322publicstaticfinal String VFEED_CONNECTION_STRING = "vfeed.connection_string"; -323 -324/** -325 * The key to obtain the base download URL for the VFeed data file. -326 */ -327publicstaticfinal String VFEED_DOWNLOAD_URL = "vfeed.download_url"; -328/** -329 * The key to obtain the download file name for the VFeed data. -330 */ -331publicstaticfinal String VFEED_DOWNLOAD_FILE = "vfeed.download_file"; -332/** -333 * The key to obtain the VFeed update status. -334 */ -335publicstaticfinal String VFEED_UPDATE_STATUS = "vfeed.update_status"; -336 -337/** -338 * The HTTP request method for query last modified date. -339 */ -340publicstaticfinal String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp"; -341 } -342//</editor-fold> -343 -344/** -345 * The logger. -346 */ -347privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(Settings.class); -348/** -349 * The properties file location. -350 */ -351privatestaticfinal String PROPERTIES_FILE = "dependencycheck.properties"; -352/** -353 * Thread local settings. -354 */ -355privatestaticfinal ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>(); -356/** -357 * The properties. -358 */ -359private Properties props = null; -360 +296 * The properties key for whether the SWIFT package manager analyzer is +297 * enabled. +298 */ +299publicstaticfinal String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled"; +300/** +301 * The properties key for the Central search URL. +302 */ +303publicstaticfinal String ANALYZER_CENTRAL_URL = "analyzer.central.url"; +304/** +305 * The path to mono, if available. +306 */ +307publicstaticfinal String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path"; +308/** +309 * The path to bundle-audit, if available. +310 */ +311publicstaticfinal String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path"; +312/** +313 * The additional configured zip file extensions, if available. +314 */ +315publicstaticfinal String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip"; +316/** +317 * The key to obtain the path to the VFEED data file. +318 */ +319publicstaticfinal String VFEED_DATA_FILE = "vfeed.data_file"; +320/** +321 * The key to obtain the VFEED connection string. +322 */ +323publicstaticfinal String VFEED_CONNECTION_STRING = "vfeed.connection_string"; +324 +325/** +326 * The key to obtain the base download URL for the VFeed data file. +327 */ +328publicstaticfinal String VFEED_DOWNLOAD_URL = "vfeed.download_url"; +329/** +330 * The key to obtain the download file name for the VFeed data. +331 */ +332publicstaticfinal String VFEED_DOWNLOAD_FILE = "vfeed.download_file"; +333/** +334 * The key to obtain the VFeed update status. +335 */ +336publicstaticfinal String VFEED_UPDATE_STATUS = "vfeed.update_status"; +337 +338/** +339 * The HTTP request method for query last modified date. +340 */ +341publicstaticfinal String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp"; +342/** +343 * The HTTP protocol list to use. +344 */ +345publicstaticfinal String DOWNLOADER_TLS_PROTOCOL_LIST = "downloader.tls.protocols"; +346 } +347//</editor-fold> +348 +349/** +350 * The logger. +351 */ +352privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(Settings.class); +353/** +354 * The properties file location. +355 */ +356privatestaticfinal String PROPERTIES_FILE = "dependencycheck.properties"; +357/** +358 * Thread local settings. +359 */ +360privatestaticfinal ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>(); 361/** -362 * Private constructor for the Settings class. This class loads the -363 * properties files. -364 * -365 * @param propertiesFilePath the path to the base properties file to load -366 */ -367privateSettings(String propertiesFilePath) { -368 InputStream in = null; -369 props = new Properties(); -370try { -371 in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath); -372 props.load(in); -373 } catch (IOException ex) { -374 LOGGER.error("Unable to load default settings."); -375 LOGGER.debug("", ex); -376 } finally { -377if (in != null) { -378try { -379 in.close(); -380 } catch (IOException ex) { -381 LOGGER.trace("", ex); -382 } -383 } -384 } -385 logProperties("Properties loaded", props); -386 } -387 -388/** -389 * Initializes the thread local settings object. Note, to use the settings -390 * object you must call this method. However, you must also call -391 * Settings.cleanup() to properly release resources. -392 */ -393publicstaticvoid initialize() { -394 LOCAL_SETTINGS.set(newSettings(PROPERTIES_FILE)); -395 } -396 -397/** -398 * Initializes the thread local settings object. Note, to use the settings -399 * object you must call this method. However, you must also call -400 * Settings.cleanup() to properly release resources. -401 * -402 * @param propertiesFilePath the path to the base properties file to load -403 */ -404publicstaticvoid initialize(String propertiesFilePath) { -405 LOCAL_SETTINGS.set(newSettings(propertiesFilePath)); -406 } -407 -408/** -409 * Cleans up resources to prevent memory leaks. -410 * +362 * The properties. +363 */ +364private Properties props = null; +365 +366/** +367 * Private constructor for the Settings class. This class loads the +368 * properties files. +369 * +370 * @param propertiesFilePath the path to the base properties file to load +371 */ +372privateSettings(String propertiesFilePath) { +373 InputStream in = null; +374 props = new Properties(); +375try { +376 in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath); +377 props.load(in); +378 } catch (NullPointerException ex) { +379 LOGGER.error("Did not find settings file '{}'.", propertiesFilePath); +380 LOGGER.debug("", ex); +381 } catch (IOException ex) { +382 LOGGER.error("Unable to load settings from '{}'.", propertiesFilePath); +383 LOGGER.debug("", ex); +384 } finally { +385if (in != null) { +386try { +387 in.close(); +388 } catch (IOException ex) { +389 LOGGER.trace("", ex); +390 } +391 } +392 } +393 logProperties("Properties loaded", props); +394 } +395 +396/** +397 * Initializes the thread local settings object. Note, to use the settings +398 * object you must call this method. However, you must also call +399 * Settings.cleanup() to properly release resources. +400 */ +401publicstaticvoid initialize() { +402 LOCAL_SETTINGS.set(newSettings(PROPERTIES_FILE)); +403 } +404 +405/** +406 * Initializes the thread local settings object. Note, to use the settings +407 * object you must call this method. However, you must also call +408 * Settings.cleanup() to properly release resources. +409 * +410 * @param propertiesFilePath the path to the base properties file to load411 */ -412publicstaticvoid cleanup() { -413 cleanup(true); +412publicstaticvoid initialize(String propertiesFilePath) { +413 LOCAL_SETTINGS.set(newSettings(propertiesFilePath)); 414 } 415416/**417 * Cleans up resources to prevent memory leaks.418 * -419 * @param deleteTemporary flag indicating whether any temporary directories -420 * generated should be removed -421 */ -422publicstaticvoid cleanup(boolean deleteTemporary) { -423if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) { -424 FileUtils.delete(tempDirectory); -425if (tempDirectory.exists()) { -426try { -427 Thread.sleep(2000); -428 } catch (InterruptedException ex) { -429 LOGGER.trace("ignore", ex); -430 } -431 FileUtils.delete(tempDirectory); -432 } -433 } -434try { -435 LOCAL_SETTINGS.remove(); -436 } catch (Throwable ex) { -437 LOGGER.debug("Error cleaning up Settings", ex); -438 } -439 } -440 -441/** -442 * Gets the underlying instance of the Settings object. -443 * -444 * @return the Settings object -445 */ -446publicstaticSettings getInstance() { -447return LOCAL_SETTINGS.get(); -448 } -449 -450/** -451 * Sets the instance of the Settings object to use in this thread. -452 * -453 * @param instance the instance of the settings object to use in this thread -454 */ -455publicstaticvoid setInstance(Settings instance) { -456 LOCAL_SETTINGS.set(instance); -457 } -458 -459/** -460 * Logs the properties. This will not log any properties that contain -461 * 'password' in the key. -462 * -463 * @param header the header to print with the log message -464 * @param properties the properties to log -465 */ -466privatestaticvoid logProperties(String header, Properties properties) { -467if (LOGGER.isDebugEnabled()) { -468final StringWriter sw = new StringWriter(); -469 PrintWriter pw = null; -470try { -471 pw = new PrintWriter(sw); -472 pw.format("%s:%n%n", header); -473final Enumeration<?> e = properties.propertyNames(); -474while (e.hasMoreElements()) { -475final String key = (String) e.nextElement(); -476if (key.contains("password")) { -477 pw.format("%s='*****'%n", key); -478 } else { -479final String value = properties.getProperty(key); -480if (value != null) { -481 pw.format("%s='%s'%n", key, value); -482 } -483 } -484 } -485 pw.flush(); -486 LOGGER.debug(sw.toString()); -487 } finally { -488if (pw != null) { -489 pw.close(); -490 } -491 } -492 -493 } -494 } -495 -496/** -497 * Sets a property value. -498 * -499 * @param key the key for the property -500 * @param value the value for the property -501 */ -502publicstaticvoid setString(String key, String value) { -503 LOCAL_SETTINGS.get().props.setProperty(key, value); -504 LOGGER.debug("Setting: {}='{}'", key, value); -505 } -506 -507/** -508 * Sets a property value only if the value is not null. -509 * -510 * @param key the key for the property -511 * @param value the value for the property -512 */ -513publicstaticvoid setStringIfNotNull(String key, String value) { -514if (null != value) { -515 setString(key, value); -516 } -517 } -518 -519/** -520 * Sets a property value only if the value is not null and not empty. -521 * -522 * @param key the key for the property -523 * @param value the value for the property -524 */ -525publicstaticvoid setStringIfNotEmpty(String key, String value) { -526if (null != value && !value.isEmpty()) { -527 setString(key, value); -528 } -529 } -530 -531/** -532 * Sets a property value. -533 * -534 * @param key the key for the property -535 * @param value the value for the property -536 */ -537publicstaticvoid setBoolean(String key, boolean value) { -538 setString(key, Boolean.toString(value)); -539 } -540 -541/** -542 * Sets a property value only if the value is not null. -543 * -544 * @param key the key for the property -545 * @param value the value for the property -546 */ -547publicstaticvoid setBooleanIfNotNull(String key, Boolean value) { -548if (null != value) { -549 setBoolean(key, value); -550 } -551 } -552 -553/** -554 * Sets a property value. -555 * -556 * @param key the key for the property -557 * @param value the value for the property -558 */ -559publicstaticvoid setInt(String key, int value) { -560 LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value)); -561 LOGGER.debug("Setting: {}='{}'", key, value); -562 } -563 -564/** -565 * Sets a property value only if the value is not null. -566 * -567 * @param key the key for the property -568 * @param value the value for the property -569 */ -570publicstaticvoid setIntIfNotNull(String key, Integer value) { -571if (null != value) { -572 setInt(key, value); -573 } -574 } -575 -576/** -577 * Merges a new properties file into the current properties. This method -578 * allows for the loading of a user provided properties file.<br><br> -579 * <b>Note</b>: even if using this method - system properties will be loaded -580 * before properties loaded from files. -581 * -582 * @param filePath the path to the properties file to merge. -583 * @throws FileNotFoundException is thrown when the filePath points to a -584 * non-existent file -585 * @throws IOException is thrown when there is an exception loading/merging -586 * the properties -587 */ -588publicstaticvoid mergeProperties(File filePath) throws FileNotFoundException, IOException { -589 FileInputStream fis = null; -590try { -591 fis = new FileInputStream(filePath); -592 mergeProperties(fis); -593 } finally { -594if (fis != null) { -595try { -596 fis.close(); -597 } catch (IOException ex) { -598 LOGGER.trace("close error", ex); -599 } -600 } -601 } -602 } -603 -604/** -605 * Merges a new properties file into the current properties. This method -606 * allows for the loading of a user provided properties file.<br><br> -607 * Note: even if using this method - system properties will be loaded before -608 * properties loaded from files. -609 * -610 * @param filePath the path to the properties file to merge. -611 * @throws FileNotFoundException is thrown when the filePath points to a -612 * non-existent file -613 * @throws IOException is thrown when there is an exception loading/merging -614 * the properties -615 */ -616publicstaticvoid mergeProperties(String filePath) throws FileNotFoundException, IOException { -617 FileInputStream fis = null; -618try { -619 fis = new FileInputStream(filePath); -620 mergeProperties(fis); -621 } finally { -622if (fis != null) { -623try { -624 fis.close(); -625 } catch (IOException ex) { -626 LOGGER.trace("close error", ex); -627 } -628 } -629 } -630 } -631 -632/** -633 * Merges a new properties file into the current properties. This method -634 * allows for the loading of a user provided properties file.<br><br> -635 * <b>Note</b>: even if using this method - system properties will be loaded -636 * before properties loaded from files. -637 * -638 * @param stream an Input Stream pointing at a properties file to merge -639 * @throws IOException is thrown when there is an exception loading/merging -640 * the properties -641 */ -642publicstaticvoid mergeProperties(InputStream stream) throws IOException { -643 LOCAL_SETTINGS.get().props.load(stream); -644 logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props); -645 } -646 -647/** -648 * Returns a value from the properties file as a File object. If the value -649 * was specified as a system property or passed in via the -Dprop=value -650 * argument - this method will return the value from the system properties -651 * before the values in the contained configuration file. -652 * -653 * @param key the key to lookup within the properties file -654 * @return the property from the properties file converted to a File object -655 */ -656publicstatic File getFile(String key) { -657final String file = getString(key); -658if (file == null) { -659returnnull; -660 } -661returnnew File(file); -662 } -663 -664/** -665 * Returns a value from the properties file as a File object. If the value -666 * was specified as a system property or passed in via the -Dprop=value -667 * argument - this method will return the value from the system properties -668 * before the values in the contained configuration file. -669 * -670 * This method will check the configured base directory and will use this as -671 * the base of the file path. Additionally, if the base directory begins -672 * with a leading "[JAR]\" sequence with the path to the folder containing -673 * the JAR file containing this class. -674 * -675 * @param key the key to lookup within the properties file -676 * @return the property from the properties file converted to a File object -677 */ -678protectedstatic File getDataFile(String key) { -679final String file = getString(key); -680 LOGGER.debug("Settings.getDataFile() - file: '{}'", file); -681if (file == null) { -682returnnull; -683 } -684if (file.startsWith("[JAR]")) { -685 LOGGER.debug("Settings.getDataFile() - transforming filename"); -686final File jarPath = getJarPath(); -687 LOGGER.debug("Settings.getDataFile() - jar file: '{}'", jarPath.toString()); -688final File retVal = new File(jarPath, file.substring(6)); -689 LOGGER.debug("Settings.getDataFile() - returning: '{}'", retVal.toString()); -690return retVal; -691 } -692returnnew File(file); -693 } -694 -695/** -696 * Attempts to retrieve the folder containing the Jar file containing the -697 * Settings class. -698 * -699 * @return a File object -700 */ -701privatestatic File getJarPath() { -702final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath(); -703 String decodedPath = "."; -704try { -705 decodedPath = URLDecoder.decode(jarPath, "UTF-8"); -706 } catch (UnsupportedEncodingException ex) { -707 LOGGER.trace("", ex); -708 } -709 -710final File path = new File(decodedPath); -711if (path.getName().toLowerCase().endsWith(".jar")) { -712return path.getParentFile(); -713 } else { -714returnnew File("."); -715 } -716 } -717 -718/** -719 * Returns a value from the properties file. If the value was specified as a -720 * system property or passed in via the -Dprop=value argument - this method -721 * will return the value from the system properties before the values in the -722 * contained configuration file. -723 * -724 * @param key the key to lookup within the properties file -725 * @param defaultValue the default value for the requested property -726 * @return the property from the properties file -727 */ -728publicstatic String getString(String key, String defaultValue) { -729final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue)); -730return str; -731 } -732 -733/** -734 * A reference to the temporary directory; used incase it needs to be -735 * deleted during cleanup. -736 */ -737privatestatic File tempDirectory = null; -738 -739/** -740 * Returns the temporary directory. -741 * -742 * @return the temporary directory -743 * @throws java.io.IOException thrown if the temporary directory does not -744 * exist and cannot be created -745 */ -746publicstatic File getTempDirectory() throws IOException { -747final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")), "dctemp"); -748if (!tmpDir.exists() && !tmpDir.mkdirs()) { -749final String msg = String.format("Unable to make a temporary folder '%s'", tmpDir.getPath()); -750thrownew IOException(msg); +419 */ +420publicstaticvoid cleanup() { +421 cleanup(true); +422 } +423 +424/** +425 * Cleans up resources to prevent memory leaks. +426 * +427 * @param deleteTemporary flag indicating whether any temporary directories +428 * generated should be removed +429 */ +430publicstaticsynchronizedvoid cleanup(boolean deleteTemporary) { +431if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) { +432 FileUtils.delete(tempDirectory); +433 tempDirectory = null; +434 } +435try { +436 LOCAL_SETTINGS.remove(); +437 } catch (Throwable ex) { +438 LOGGER.debug("Error cleaning up Settings", ex); +439 } +440 } +441 +442/** +443 * Gets the underlying instance of the Settings object. +444 * +445 * @return the Settings object +446 */ +447publicstaticSettings getInstance() { +448return LOCAL_SETTINGS.get(); +449 } +450 +451/** +452 * Sets the instance of the Settings object to use in this thread. +453 * +454 * @param instance the instance of the settings object to use in this thread +455 */ +456publicstaticvoid setInstance(Settings instance) { +457 LOCAL_SETTINGS.set(instance); +458 } +459 +460/** +461 * Logs the properties. This will not log any properties that contain +462 * 'password' in the key. +463 * +464 * @param header the header to print with the log message +465 * @param properties the properties to log +466 */ +467privatestaticvoid logProperties(String header, Properties properties) { +468if (LOGGER.isDebugEnabled()) { +469final StringWriter sw = new StringWriter(); +470 PrintWriter pw = null; +471try { +472 pw = new PrintWriter(sw); +473 pw.format("%s:%n%n", header); +474final Enumeration<?> e = properties.propertyNames(); +475while (e.hasMoreElements()) { +476final String key = (String) e.nextElement(); +477if (key.contains("password")) { +478 pw.format("%s='*****'%n", key); +479 } else { +480final String value = properties.getProperty(key); +481if (value != null) { +482 pw.format("%s='%s'%n", key, value); +483 } +484 } +485 } +486 pw.flush(); +487 LOGGER.debug(sw.toString()); +488 } finally { +489if (pw != null) { +490 pw.close(); +491 } +492 } +493 +494 } +495 } +496 +497/** +498 * Sets a property value. +499 * +500 * @param key the key for the property +501 * @param value the value for the property +502 */ +503publicstaticvoid setString(String key, String value) { +504 LOCAL_SETTINGS.get().props.setProperty(key, value); +505 LOGGER.debug("Setting: {}='{}'", key, value); +506 } +507 +508/** +509 * Sets a property value only if the value is not null. +510 * +511 * @param key the key for the property +512 * @param value the value for the property +513 */ +514publicstaticvoid setStringIfNotNull(String key, String value) { +515if (null != value) { +516 setString(key, value); +517 } +518 } +519 +520/** +521 * Sets a property value only if the value is not null and not empty. +522 * +523 * @param key the key for the property +524 * @param value the value for the property +525 */ +526publicstaticvoid setStringIfNotEmpty(String key, String value) { +527if (null != value && !value.isEmpty()) { +528 setString(key, value); +529 } +530 } +531 +532/** +533 * Sets a property value. +534 * +535 * @param key the key for the property +536 * @param value the value for the property +537 */ +538publicstaticvoid setBoolean(String key, boolean value) { +539 setString(key, Boolean.toString(value)); +540 } +541 +542/** +543 * Sets a property value only if the value is not null. +544 * +545 * @param key the key for the property +546 * @param value the value for the property +547 */ +548publicstaticvoid setBooleanIfNotNull(String key, Boolean value) { +549if (null != value) { +550 setBoolean(key, value); +551 } +552 } +553 +554/** +555 * Sets a property value. +556 * +557 * @param key the key for the property +558 * @param value the value for the property +559 */ +560publicstaticvoid setInt(String key, int value) { +561 LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value)); +562 LOGGER.debug("Setting: {}='{}'", key, value); +563 } +564 +565/** +566 * Sets a property value only if the value is not null. +567 * +568 * @param key the key for the property +569 * @param value the value for the property +570 */ +571publicstaticvoid setIntIfNotNull(String key, Integer value) { +572if (null != value) { +573 setInt(key, value); +574 } +575 } +576 +577/** +578 * Merges a new properties file into the current properties. This method +579 * allows for the loading of a user provided properties file.<br><br> +580 * <b>Note</b>: even if using this method - system properties will be loaded +581 * before properties loaded from files. +582 * +583 * @param filePath the path to the properties file to merge. +584 * @throws FileNotFoundException is thrown when the filePath points to a +585 * non-existent file +586 * @throws IOException is thrown when there is an exception loading/merging +587 * the properties +588 */ +589publicstaticvoid mergeProperties(File filePath) throws FileNotFoundException, IOException { +590 FileInputStream fis = null; +591try { +592 fis = new FileInputStream(filePath); +593 mergeProperties(fis); +594 } finally { +595if (fis != null) { +596try { +597 fis.close(); +598 } catch (IOException ex) { +599 LOGGER.trace("close error", ex); +600 } +601 } +602 } +603 } +604 +605/** +606 * Merges a new properties file into the current properties. This method +607 * allows for the loading of a user provided properties file.<br><br> +608 * Note: even if using this method - system properties will be loaded before +609 * properties loaded from files. +610 * +611 * @param filePath the path to the properties file to merge. +612 * @throws FileNotFoundException is thrown when the filePath points to a +613 * non-existent file +614 * @throws IOException is thrown when there is an exception loading/merging +615 * the properties +616 */ +617publicstaticvoid mergeProperties(String filePath) throws FileNotFoundException, IOException { +618 FileInputStream fis = null; +619try { +620 fis = new FileInputStream(filePath); +621 mergeProperties(fis); +622 } finally { +623if (fis != null) { +624try { +625 fis.close(); +626 } catch (IOException ex) { +627 LOGGER.trace("close error", ex); +628 } +629 } +630 } +631 } +632 +633/** +634 * Merges a new properties file into the current properties. This method +635 * allows for the loading of a user provided properties file.<br><br> +636 * <b>Note</b>: even if using this method - system properties will be loaded +637 * before properties loaded from files. +638 * +639 * @param stream an Input Stream pointing at a properties file to merge +640 * @throws IOException is thrown when there is an exception loading/merging +641 * the properties +642 */ +643publicstaticvoid mergeProperties(InputStream stream) throws IOException { +644 LOCAL_SETTINGS.get().props.load(stream); +645 logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props); +646 } +647 +648/** +649 * Returns a value from the properties file as a File object. If the value +650 * was specified as a system property or passed in via the -Dprop=value +651 * argument - this method will return the value from the system properties +652 * before the values in the contained configuration file. +653 * +654 * @param key the key to lookup within the properties file +655 * @return the property from the properties file converted to a File object +656 */ +657publicstatic File getFile(String key) { +658final String file = getString(key); +659if (file == null) { +660returnnull; +661 } +662returnnew File(file); +663 } +664 +665/** +666 * Returns a value from the properties file as a File object. If the value +667 * was specified as a system property or passed in via the -Dprop=value +668 * argument - this method will return the value from the system properties +669 * before the values in the contained configuration file. +670 * +671 * This method will check the configured base directory and will use this as +672 * the base of the file path. Additionally, if the base directory begins +673 * with a leading "[JAR]\" sequence with the path to the folder containing +674 * the JAR file containing this class. +675 * +676 * @param key the key to lookup within the properties file +677 * @return the property from the properties file converted to a File object +678 */ +679protectedstatic File getDataFile(String key) { +680final String file = getString(key); +681 LOGGER.debug("Settings.getDataFile() - file: '{}'", file); +682if (file == null) { +683returnnull; +684 } +685if (file.startsWith("[JAR]")) { +686 LOGGER.debug("Settings.getDataFile() - transforming filename"); +687final File jarPath = getJarPath(); +688 LOGGER.debug("Settings.getDataFile() - jar file: '{}'", jarPath.toString()); +689final File retVal = new File(jarPath, file.substring(6)); +690 LOGGER.debug("Settings.getDataFile() - returning: '{}'", retVal.toString()); +691return retVal; +692 } +693returnnew File(file); +694 } +695 +696/** +697 * Attempts to retrieve the folder containing the Jar file containing the +698 * Settings class. +699 * +700 * @return a File object +701 */ +702privatestatic File getJarPath() { +703final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath(); +704 String decodedPath = "."; +705try { +706 decodedPath = URLDecoder.decode(jarPath, "UTF-8"); +707 } catch (UnsupportedEncodingException ex) { +708 LOGGER.trace("", ex); +709 } +710 +711final File path = new File(decodedPath); +712if (path.getName().toLowerCase().endsWith(".jar")) { +713return path.getParentFile(); +714 } else { +715returnnew File("."); +716 } +717 } +718 +719/** +720 * Returns a value from the properties file. If the value was specified as a +721 * system property or passed in via the -Dprop=value argument - this method +722 * will return the value from the system properties before the values in the +723 * contained configuration file. +724 * +725 * @param key the key to lookup within the properties file +726 * @param defaultValue the default value for the requested property +727 * @return the property from the properties file +728 */ +729publicstatic String getString(String key, String defaultValue) { +730final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue)); +731return str; +732 } +733 +734/** +735 * A reference to the temporary directory; used incase it needs to be +736 * deleted during cleanup. +737 */ +738privatestatic File tempDirectory = null; +739 +740/** +741 * Returns the temporary directory. +742 * +743 * @return the temporary directory +744 * @throws java.io.IOException thrown if the temporary directory does not +745 * exist and cannot be created +746 */ +747publicstaticsynchronized File getTempDirectory() throws IOException { +748if (tempDirectory == null) { +749final File baseTemp = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir"))); +750 tempDirectory = FileUtils.createTempDirectory(baseTemp); 751 } -752 tempDirectory = tmpDir; -753return tmpDir; -754 } -755 -756/** -757 * Returns a value from the properties file. If the value was specified as a -758 * system property or passed in via the -Dprop=value argument - this method -759 * will return the value from the system properties before the values in the -760 * contained configuration file. -761 * -762 * @param key the key to lookup within the properties file -763 * @return the property from the properties file -764 */ -765publicstatic String getString(String key) { -766return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key)); -767 } -768 -769/** -770 * Removes a property from the local properties collection. This is mainly -771 * used in test cases. -772 * -773 * @param key the property key to remove -774 */ -775publicstaticvoid removeProperty(String key) { -776 LOCAL_SETTINGS.get().props.remove(key); -777 } -778 -779/** -780 * Returns an int value from the properties file. If the value was specified -781 * as a system property or passed in via the -Dprop=value argument - this -782 * method will return the value from the system properties before the values -783 * in the contained configuration file. -784 * -785 * @param key the key to lookup within the properties file -786 * @return the property from the properties file -787 * @throws InvalidSettingException is thrown if there is an error retrieving -788 * the setting -789 */ -790publicstaticint getInt(String key) throws InvalidSettingException { -791try { -792return Integer.parseInt(Settings.getString(key)); -793 } catch (NumberFormatException ex) { -794thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex); -795 } -796 } -797 -798/** -799 * Returns an int value from the properties file. If the value was specified -800 * as a system property or passed in via the -Dprop=value argument - this -801 * method will return the value from the system properties before the values -802 * in the contained configuration file. -803 * -804 * @param key the key to lookup within the properties file -805 * @param defaultValue the default value to return -806 * @return the property from the properties file or the defaultValue if the -807 * property does not exist or cannot be converted to an integer -808 */ -809publicstaticint getInt(String key, int defaultValue) { -810int value; -811try { -812 value = Integer.parseInt(Settings.getString(key)); -813 } catch (NumberFormatException ex) { -814if (!Settings.getString(key, "").isEmpty()) { -815 LOGGER.debug("Could not convert property '{}={}' to an int; using {} instead.", key, Settings.getString(key), defaultValue); -816 } -817 value = defaultValue; -818 } -819return value; -820 } -821 -822/** -823 * Returns a long value from the properties file. If the value was specified -824 * as a system property or passed in via the -Dprop=value argument - this -825 * method will return the value from the system properties before the values -826 * in the contained configuration file. -827 * -828 * @param key the key to lookup within the properties file -829 * @return the property from the properties file -830 * @throws InvalidSettingException is thrown if there is an error retrieving -831 * the setting -832 */ -833publicstaticlong getLong(String key) throws InvalidSettingException { -834try { -835return Long.parseLong(Settings.getString(key)); -836 } catch (NumberFormatException ex) { -837thrownewInvalidSettingException("Could not convert property '" + key + "' to a long.", ex); -838 } -839 } -840 -841/** -842 * Returns a boolean value from the properties file. If the value was -843 * specified as a system property or passed in via the -844 * <code>-Dprop=value</code> argument this method will return the value from -845 * the system properties before the values in the contained configuration -846 * file. -847 * -848 * @param key the key to lookup within the properties file -849 * @return the property from the properties file -850 * @throws InvalidSettingException is thrown if there is an error retrieving -851 * the setting -852 */ -853publicstaticboolean getBoolean(String key) throws InvalidSettingException { -854return Boolean.parseBoolean(Settings.getString(key)); -855 } -856 -857/** -858 * Returns a boolean value from the properties file. If the value was -859 * specified as a system property or passed in via the -860 * <code>-Dprop=value</code> argument this method will return the value from -861 * the system properties before the values in the contained configuration -862 * file. -863 * -864 * @param key the key to lookup within the properties file -865 * @param defaultValue the default value to return if the setting does not -866 * exist -867 * @return the property from the properties file -868 * @throws InvalidSettingException is thrown if there is an error retrieving -869 * the setting -870 */ -871publicstaticboolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException { -872return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue))); -873 } -874 -875/** -876 * Returns a connection string from the configured properties. If the -877 * connection string contains a %s, this method will determine the 'data' -878 * directory and replace the %s with the path to the data directory. If the -879 * data directory does not exists it will be created. -880 * -881 * @param connectionStringKey the property file key for the connection -882 * string -883 * @param dbFileNameKey the settings key for the db filename -884 * @return the connection string -885 * @throws IOException thrown the data directory cannot be created -886 * @throws InvalidSettingException thrown if there is an invalid setting -887 */ -888publicstatic String getConnectionString(String connectionStringKey, String dbFileNameKey) -889throws IOException, InvalidSettingException { -890final String connStr = Settings.getString(connectionStringKey); -891if (connStr == null) { -892final String msg = String.format("Invalid properties file; %s is missing.", connectionStringKey); -893thrownewInvalidSettingException(msg); -894 } -895if (connStr.contains("%s")) { -896final File directory = getDataDirectory(); -897 String fileName = null; -898if (dbFileNameKey != null) { -899 fileName = Settings.getString(dbFileNameKey); -900 } -901if (fileName == null) { -902final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.", -903 dbFileNameKey); -904thrownewInvalidSettingException(msg); -905 } -906if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) { -907 fileName = fileName.substring(0, fileName.length() - 6); -908 } -909// yes, for H2 this path won't actually exists - but this is sufficient to get the value needed -910final File dbFile = new File(directory, fileName); -911final String cString = String.format(connStr, dbFile.getCanonicalPath()); -912 LOGGER.debug("Connection String: '{}'", cString); -913return cString; -914 } -915return connStr; -916 } -917 -918/** -919 * Retrieves the directory that the JAR file exists in so that we can ensure -920 * we always use a common data directory for the embedded H2 database. This -921 * is public solely for some unit tests; otherwise this should be private. -922 * -923 * @return the data directory to store data files -924 * @throws IOException is thrown if an IOException occurs of course... -925 */ -926publicstatic File getDataDirectory() throws IOException { -927final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY); -928if (path.exists() || path.mkdirs()) { -929return path; -930 } -931thrownew IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath())); -932 } -933 } +752return tempDirectory; +753 } +754 +755/** +756 * Returns a value from the properties file. If the value was specified as a +757 * system property or passed in via the -Dprop=value argument - this method +758 * will return the value from the system properties before the values in the +759 * contained configuration file. +760 * +761 * @param key the key to lookup within the properties file +762 * @return the property from the properties file +763 */ +764publicstatic String getString(String key) { +765return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key)); +766 } +767 +768/** +769 * Removes a property from the local properties collection. This is mainly +770 * used in test cases. +771 * +772 * @param key the property key to remove +773 */ +774publicstaticvoid removeProperty(String key) { +775 LOCAL_SETTINGS.get().props.remove(key); +776 } +777 +778/** +779 * Returns an int value from the properties file. If the value was specified +780 * as a system property or passed in via the -Dprop=value argument - this +781 * method will return the value from the system properties before the values +782 * in the contained configuration file. +783 * +784 * @param key the key to lookup within the properties file +785 * @return the property from the properties file +786 * @throws InvalidSettingException is thrown if there is an error retrieving +787 * the setting +788 */ +789publicstaticint getInt(String key) throws InvalidSettingException { +790try { +791return Integer.parseInt(Settings.getString(key)); +792 } catch (NumberFormatException ex) { +793thrownewInvalidSettingException("Could not convert property '" + key + "' to an int.", ex); +794 } +795 } +796 +797/** +798 * Returns an int value from the properties file. If the value was specified +799 * as a system property or passed in via the -Dprop=value argument - this +800 * method will return the value from the system properties before the values +801 * in the contained configuration file. +802 * +803 * @param key the key to lookup within the properties file +804 * @param defaultValue the default value to return +805 * @return the property from the properties file or the defaultValue if the +806 * property does not exist or cannot be converted to an integer +807 */ +808publicstaticint getInt(String key, int defaultValue) { +809int value; +810try { +811 value = Integer.parseInt(Settings.getString(key)); +812 } catch (NumberFormatException ex) { +813if (!Settings.getString(key, "").isEmpty()) { +814 LOGGER.debug("Could not convert property '{}={}' to an int; using {} instead.", key, Settings.getString(key), defaultValue); +815 } +816 value = defaultValue; +817 } +818return value; +819 } +820 +821/** +822 * Returns a long value from the properties file. If the value was specified +823 * as a system property or passed in via the -Dprop=value argument - this +824 * method will return the value from the system properties before the values +825 * in the contained configuration file. +826 * +827 * @param key the key to lookup within the properties file +828 * @return the property from the properties file +829 * @throws InvalidSettingException is thrown if there is an error retrieving +830 * the setting +831 */ +832publicstaticlong getLong(String key) throws InvalidSettingException { +833try { +834return Long.parseLong(Settings.getString(key)); +835 } catch (NumberFormatException ex) { +836thrownewInvalidSettingException("Could not convert property '" + key + "' to a long.", ex); +837 } +838 } +839 +840/** +841 * Returns a boolean value from the properties file. If the value was +842 * specified as a system property or passed in via the +843 * <code>-Dprop=value</code> argument this method will return the value from +844 * the system properties before the values in the contained configuration +845 * file. +846 * +847 * @param key the key to lookup within the properties file +848 * @return the property from the properties file +849 * @throws InvalidSettingException is thrown if there is an error retrieving +850 * the setting +851 */ +852publicstaticboolean getBoolean(String key) throws InvalidSettingException { +853return Boolean.parseBoolean(Settings.getString(key)); +854 } +855 +856/** +857 * Returns a boolean value from the properties file. If the value was +858 * specified as a system property or passed in via the +859 * <code>-Dprop=value</code> argument this method will return the value from +860 * the system properties before the values in the contained configuration +861 * file. +862 * +863 * @param key the key to lookup within the properties file +864 * @param defaultValue the default value to return if the setting does not +865 * exist +866 * @return the property from the properties file +867 * @throws InvalidSettingException is thrown if there is an error retrieving +868 * the setting +869 */ +870publicstaticboolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException { +871return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue))); +872 } +873 +874/** +875 * Returns a connection string from the configured properties. If the +876 * connection string contains a %s, this method will determine the 'data' +877 * directory and replace the %s with the path to the data directory. If the +878 * data directory does not exists it will be created. +879 * +880 * @param connectionStringKey the property file key for the connection +881 * string +882 * @param dbFileNameKey the settings key for the db filename +883 * @return the connection string +884 * @throws IOException thrown the data directory cannot be created +885 * @throws InvalidSettingException thrown if there is an invalid setting +886 */ +887publicstatic String getConnectionString(String connectionStringKey, String dbFileNameKey) +888throws IOException, InvalidSettingException { +889final String connStr = Settings.getString(connectionStringKey); +890if (connStr == null) { +891final String msg = String.format("Invalid properties file; %s is missing.", connectionStringKey); +892thrownewInvalidSettingException(msg); +893 } +894if (connStr.contains("%s")) { +895final File directory = getDataDirectory(); +896 String fileName = null; +897if (dbFileNameKey != null) { +898 fileName = Settings.getString(dbFileNameKey); +899 } +900if (fileName == null) { +901final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.", +902 dbFileNameKey); +903thrownewInvalidSettingException(msg); +904 } +905if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) { +906 fileName = fileName.substring(0, fileName.length() - 6); +907 } +908// yes, for H2 this path won't actually exists - but this is sufficient to get the value needed +909final File dbFile = new File(directory, fileName); +910final String cString = String.format(connStr, dbFile.getCanonicalPath()); +911 LOGGER.debug("Connection String: '{}'", cString); +912return cString; +913 } +914return connStr; +915 } +916 +917/** +918 * Retrieves the directory that the JAR file exists in so that we can ensure +919 * we always use a common data directory for the embedded H2 database. This +920 * is public solely for some unit tests; otherwise this should be private. +921 * +922 * @return the data directory to store data files +923 * @throws IOException is thrown if an IOException occurs of course... +924 */ +925publicstatic File getDataDirectory() throws IOException { +926final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY); +927if (path.exists() || path.mkdirs()) { +928return path; +929 } +930thrownew IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath())); +931 } +932 }
      diff --git a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html index cbb6a4306..2066cc451 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html @@ -206,7 +206,7 @@ 198 } catch (NoSuchAlgorithmException ex) { 199 LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex); 200 } catch (KeyManagementException ex) { -201 LOGGER.debug("Key mnagement eception in SSLSocketFactoryEx", ex); +201 LOGGER.debug("Key management exception in SSLSocketFactoryEx", ex); 202 } 203 } 204 } diff --git a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/package-frame.html b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/package-frame.html index 2c9a17aef..4026f2a45 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/package-frame.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Utils 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Utils 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/package-summary.html b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/package-summary.html index 91e9d572e..6e1bc3467 100644 --- a/dependency-check-utils/xref/org/owasp/dependencycheck/utils/package-summary.html +++ b/dependency-check-utils/xref/org/owasp/dependencycheck/utils/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Utils 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check Utils 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/dependency-check-utils/xref/overview-frame.html b/dependency-check-utils/xref/overview-frame.html index 46b9088ae..9318d2cec 100644 --- a/dependency-check-utils/xref/overview-frame.html +++ b/dependency-check-utils/xref/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check Utils 1.4.3 Reference + Dependency-Check Utils 1.4.4 Reference diff --git a/dependency-check-utils/xref/overview-summary.html b/dependency-check-utils/xref/overview-summary.html index b43685082..87591a21d 100644 --- a/dependency-check-utils/xref/overview-summary.html +++ b/dependency-check-utils/xref/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check Utils 1.4.3 Reference + Dependency-Check Utils 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check Utils 1.4.3 Reference

      +

      Dependency-Check Utils 1.4.4 Reference

      diff --git a/dependency-updates-report.html b/dependency-updates-report.html index 0bc54cd94..3e74583ee 100644 --- a/dependency-updates-report.html +++ b/dependency-updates-report.html @@ -1,13 +1,13 @@ - + dependency-check – Dependency Updates Report @@ -59,9 +59,9 @@
    118. Dependency Updates Report
    119. -
    120. | Last Published: 2016-09-06
    121. +
    122. | Last Published: 2016-11-05
    123. - Version: 1.4.3 + Version: 1.4.4
    124. @@ -74,14 +74,14 @@ - + @@ -205,7 +205,7 @@ - + @@ -278,15 +278,15 @@ - + - + - + @@ -482,16 +482,16 @@ - + - + - + @@ -566,7 +566,7 @@ - + @@ -575,7 +575,7 @@ - + @@ -729,13 +729,13 @@ -
      # of dependencies using the latest version available21
      22
      # of dependencies where the next version available is smaller than an incremental version update
      # of dependencies where the next version available is an incremental version update1
      0
      # of dependencies where the next version available is a minor version update1.4.177
      com.sun.mail mailapi1.5.51.5.6 jar 1.5.6
      org.apache.maven.plugin-tools maven-plugin-annotations3.43.5 jar 3.5
      1.25
      org.jsoup jsoup 1.9.2jar 1.10.1
      jar
      Newer versions1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192 Latest Minor
      +1.4.177 Next Minor
      1.4.178
      1.4.179
      1.4.180
      1.4.181
      1.4.182
      1.4.183
      1.4.184
      1.4.185
      1.4.186
      1.4.187
      1.4.188
      1.4.189
      1.4.190
      1.4.191
      1.4.192
      1.4.193 Latest Minor

      com.sun.mail:mailapi

      - + @@ -744,7 +744,7 @@ - + @@ -753,10 +753,7 @@ - - - -
      Status There is at least one newer incremental version available. Incremental updates are typically passive.
       No newer versions available.
      Group Id com.sun.mail
      mailapi
      Current Version1.5.5
      1.5.6
      Scope
      Typejar
      Newer versions1.5.6 Next Incremental
      +jar

      commons-cli:commons-cli

      @@ -954,7 +951,7 @@ -
      jar
      Newer versions3.4 Next Minor
      +3.4 Next Minor
      3.5 Latest Minor

      org.apache.lucene:lucene-analyzers-common

      @@ -981,7 +978,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-core

      @@ -1008,7 +1005,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-queryparser

      @@ -1035,7 +1032,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.lucene:lucene-test-framework

      @@ -1062,7 +1059,7 @@ -
      jar
      Newer versions4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      6.0.0
      6.0.1
      6.1.0
      6.2.0 Latest Major
      +4.8.0 Next Minor
      4.8.1
      4.9.0
      4.9.1
      4.10.0
      4.10.1
      4.10.2
      4.10.3
      4.10.4 Latest Minor
      5.0.0 Next Major
      5.1.0
      5.2.0
      5.2.1
      5.3.0
      5.3.1
      5.3.2
      5.4.0
      5.4.1
      5.5.0
      5.5.1
      5.5.2
      5.5.3
      6.0.0
      6.0.1
      6.1.0
      6.2.0
      6.2.1 Latest Major

      org.apache.maven:maven-core

      @@ -1164,7 +1161,7 @@
      - + @@ -1173,7 +1170,7 @@ - + @@ -1182,10 +1179,7 @@ - - - -
      Status There is at least one newer minor version available. Minor updates are sometimes passive.
       No newer versions available.
      Group Id org.apache.maven.plugin-tools
      maven-plugin-annotations
      Current Version3.4
      3.5
      Scope
      Typejar
      Newer versions3.5 Next Minor
      +jar

      org.apache.maven.reporting:maven-reporting-api

      @@ -1335,13 +1329,13 @@ -
      jar
      Newer versions1.25 Next Minor
      1.26
      1.27 Latest Minor
      +1.25 Next Minor
      1.26
      1.27
      1.28
      1.29 Latest Minor

      org.jsoup:jsoup

      - + @@ -1359,7 +1353,10 @@ -
      Status No newer versions available.
       There is at least one newer minor version available. Minor updates are sometimes passive.
      Group Id org.jsoup
      Typejar
      +jar + +Newer versions +1.10.1 Next Minor

      org.slf4j:slf4j-api

      diff --git a/general/SampleReport.html b/general/SampleReport.html index d31014370..24ae5e3ef 100644 --- a/general/SampleReport.html +++ b/general/SampleReport.html @@ -60,20 +60,72 @@ setTimeout('$("#modal-content,#modal-background").toggleClass("active");',100); }); $('#modal-add-header').click(function () { - xml = '\n\n '; + xml = '\n\n '; xml += $("#modal-text").text().replace(/\n/g,'\n '); xml += '\n'; $('#modal-text').text(xml).focus().select(); + $('#modal-add-header').toggleClass('active'); }); }); - function copyText(name, sha1, type, val) { + function suppressSwitchTo(switchTo) { + $('#modal-suppress-change-to-sha1').toggleClass('active'); + $('#modal-suppress-change-to-gav').toggleClass('active'); + setCopyText($('#suppress-name').val(), + switchTo, + $('#suppress-'+switchTo).val(), + $('#suppress-type').val(), + $('#suppress-val').val()); + } + function copyText(name, sha1, gav, type, val) { + $('#suppress-name').val(name); + $('#suppress-type').val(type); + $('#suppress-val').val(val); + $('#suppress-sha1').val(sha1); + $('#suppress-gav').val(gav); + if (gav=='') { + if ($('#modal-suppress-change-to-gav').hasClass('active')) { + $('#modal-suppress-change-to-gav').toggleClass('active'); + } + if ($('#modal-suppress-change-to-sha1').hasClass('active')) { + $('#modal-suppress-change-to-sha1').toggleClass('active'); + } + setCopyText(name, 'sha1', sha1, type, val); + } else { + if ($('#modal-suppress-change-to-gav').hasClass('active')) { + $('#modal-suppress-change-to-gav').toggleClass('active'); + } + if (!$('#modal-suppress-change-to-sha1').hasClass('active')) { + $('#modal-suppress-change-to-sha1').toggleClass('active'); + } + setCopyText(name, 'gav', gav, type, val); + } + } + function setCopyText(name, matchType, matchValue, suppressType, suppressVal) { xml = '\n'; xml += ' \n'; - xml += ' ' + sha1 + '\n'; - xml += ' <'+type+'>' + val + '\n'; + if (matchType=='gav') { + v = matchValue.match(/^[^:]+:[^:]+:/); + if (v && v[0]) { + xml += ' <'+matchType+' regex="true">^' + v[0].replace(/\./g,'\\.') + '.*$\n'; + } else { + xml += ' <'+matchType+'>' + matchValue + '\n'; + } + } else { + xml += ' <'+matchType+'>' + matchValue + '\n'; + } + if (suppressType=='cpe') { + v = suppressVal.match(/^cpe:\/a:[^:]+:[^:]+/); + if (v && v[0]) { + xml += ' <'+suppressType+'>' + v[0] + '\n'; + } else { + xml += ' <'+suppressType+'>' + suppressVal + '\n'; + } + } else { + xml += ' <'+suppressType+'>' + suppressVal + '\n'; + } xml += ''; $('#modal-text').text(xml); - $('#modal-content,#modal-background').toggleClass('active'); + $('#modal-content,#modal-background').addClass('active'); $('#modal-text').focus(); $('#modal-text').select(); } @@ -131,6 +183,12 @@ #modal-text:focus { outline: none; } + .suppresstype { + display: none; + } + .suppresstype.active { + display: block; + } .suppressedLabel { cursor: default; padding:1px; @@ -484,8 +542,13 @@
      @@ -496,20 +559,23 @@ the reporting provided constitutes acceptance for use in an AS IS condition, and implied or otherwise, with regard to the analysis or its use. Any use of the tool and the reporting provided is at the user’s risk. In no event shall the copyright holder or OWASP be held liable for any damages whatsoever arising out of or in connection with the use of this tool, the analysis performed, or the resulting report.

      +

      How to read the report | +Suppressing false positives | +Getting Help: google group | +github issues

      Project: DependencyCheck

      - Scan Information (show all):
      + Scan Information (show all):
        -
      • dependency-check version: 1.2.11
      • -
      • Report Generated On: May 11, 2015 at 20:38:49 EDT
      • -
      • Dependencies Scanned: 171
      • -
      • Vulnerable Dependencies: 29
      • -
      • Vulnerabilities Found: 126
      • +
      • dependency-check version: 1.4.4-SNAPSHOT
      • +
      • Report Generated On: Oct 9, 2016 at 07:04:35 EDT
      • +
      • Dependencies Scanned: 306 (289 unique)
      • +
      • Vulnerable Dependencies: 36
      • +
      • Vulnerabilities Found: 289
      • Vulnerabilities Suppressed: 0
      • ...
      • - @@ -522,11 +588,13 @@ arising out of or in connection with the use of this tool, the analysis performe - - - + + + + + - +

      Display: Showing Vulnerable Dependencies (click to show all)

      @@ -537,307 +605,1149 @@ arising out of or in connection with the use of this tool, the analysis performe - + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - - - + + - - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - + - + - - + - + - + - + - + - - + + - + - + - - + + - + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -846,464 +1756,401 @@ arising out of or in connection with the use of this tool, the analysis performe - + - + - + + + + + + + + + + - - + - - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + - + - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + - - + + - - - + + - - + + - - - + + - - + + - + - + - - + + - + - + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - + - + + + + + + + + + + - + - + - - + + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + @@ -1334,135 +2261,323 @@ arising out of or in connection with the use of this tool, the analysis performe - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + + + + + + + + + + - + - + - - + + - + - + - - + + - + - + - - + + + + + + + + + + + - + - + - + - - - + + - - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - + - + - - + + + + + + + + + + - - - + + - + - + - + @@ -1471,109 +2586,144 @@ arising out of or in connection with the use of this tool, the analysis performe - + - + + + + + + + + + - - - - - - - - - - - - - - - - - - - + - - + - - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - + - - - + + - + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + - + - + - - - + + + - - + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + - + - - + - + - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + @@ -1749,885 +3013,1705 @@ arising out of or in connection with the use of this tool, the analysis performe - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - + + + + + + + + + + + - + - - + - - + + - + - - + - + - + - + - - - - - - - - - - - + - - - + + - + - - - + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Highest Severity CVE Count CPE ConfidenceEvidence CountEvidence Count
      annogen-0.1.0.jaractivation-1.1.jar annogen:annogen:0.1.0 - javax.activation:activation:1.1 +   0819
      ant-1.8.2.jarannogen-0.1.0.jar org.apache.ant:ant:1.8.2 - annogen:annogen:0.1.0 +   0 11
      aopalliance-1.0.jarannotations-3.0.1u2.jar aopalliance:aopalliance:1.0 - com.google.code.findbugs:annotations:3.0.1u2 +   0918
      aspectjrt-1.6.5.jarant-1.9.7.jar org.aspectj:aspectjrt:1.6.5 - org.apache.ant:ant:1.9.7 +   01019
      aspectjweaver-1.6.5.jaraopalliance-1.0.jar org.aspectj:aspectjweaver:1.6.5 - aopalliance:aopalliance:1.0 +   01613
      axiom-api-1.2.7.jaraspectjrt-1.6.5.jar org.apache.ws.commons.axiom:axiom-api:1.2.7 - org.aspectj:aspectjrt:1.6.5 +   01618
      axiom-dom-1.2.7.jaraspectjweaver-1.6.5.jar org.apache.ws.commons.axiom:axiom-dom:1.2.7 - org.aspectj:aspectjweaver:1.6.5 +   01719
      axiom-impl-1.2.7.jar - org.apache.ws.commons.axiom:axiom-impl:1.2.7 + binutils/configure +   0174
      binutils/configure.ac + + +   + 03
      axis-1.4.jarghostscript/configure.ac + cpe:/a:ghostscript:ghostscript:8.62 + + + High + 5HIGHEST4
      readable-code/configure + + +   + 06
      readable-code/configure.ac + + +   + 06
      axiom-api-1.2.7.jar + org.apache.ws.commons.axiom:axiom-api:1.2.7 + +   + 016
      axiom-dom-1.2.7.jar + org.apache.ws.commons.axiom:axiom-dom:1.2.7 + +   + 016
      axiom-impl-1.2.7.jar + org.apache.ws.commons.axiom:axiom-impl:1.2.7 + +   + 016
      axis-1.4.jar cpe:/a:apache:axis:1.4 axis:axis:1.4 - axis:axis:1.4 + Medium 2 HIGHEST1017
      axis2-kernel-1.4.1.jaraxis2-kernel-1.4.1.jar cpe:/a:apache:axis2:1.4.1 org.apache.axis2:axis2-kernel:1.4.1 - org.apache.axis2:axis2-kernel:1.4.1 + High 6 HIGHEST1516
      backport-util-concurrent-3.1.jarbackport-util-concurrent-3.1.jar backport-util-concurrent:backport-util-concurrent:3.1 - -   + backport-util-concurrent:backport-util-concurrent:3.1 012
      commons-cli-1.2.jar - commons-cli:commons-cli:1.2 - -   - 022
      commons-codec-1.2.jar - commons-codec:commons-codec:1.2 -   0 16
      bootable-0.1.0.jar + org.owasp.testing:bootable:0.1.0 + +   + 09
      bootable-0.1.0.jar: lib-0.1.0.jar + org.owasp.testing:lib:0.1.0 + +   + 010
      commons-fileupload-1.2.1.jarffmpeg\ffmpeg_version.cmake + cpe:/a:ffmpeg:ffmpeg:55.18.102 + + + High + 3LOW3
      cmake\cl2cpp.cmake + + +   + 02
      cmake\copyAndroidLibs.cmake + + +   + 01
      cmake\FindCUDA.cmake + + +   + 01
      FindCUDA\make2cmake.cmake + + +   + 02
      FindCUDA\parse_cubin.cmake + + +   + 01
      FindCUDA\run_nvcc.cmake + + +   + 01
      cmake\OpenCVCompilerOptions.cmake + + +   + 01
      cmake\OpenCVConfig.cmake + + +   + 01
      cmake\OpenCVCRTLinkage.cmake + + +   + 01
      cmake\OpenCVDetectAndroidSDK.cmake + cpe:/a:android:android_sdk:- + + +   + 0LOW1
      cmake\OpenCVDetectApacheAnt.cmake + + +   + 01
      cmake\OpenCVDetectCStripes.cmake + + +   + 01
      cmake\OpenCVDetectCUDA.cmake + + +   + 01
      cmake\OpenCVDetectCXXCompiler.cmake + + +   + 03
      cmake\OpenCVDetectDirectX.cmake + + +   + 01
      cmake\OpenCVDetectOpenCL.cmake + + +   + 01
      cmake\OpenCVDetectPython.cmake + cpe:/a:python:python:- + + + High + 11LOW1
      cmake\OpenCVDetectTBB.cmake + + +   + 01
      cmake\OpenCVDetectVTK.cmake + + +   + 01
      cmake\OpenCVExtraTargets.cmake + + +   + 01
      cmake\OpenCVFindIntelPerCSDK.cmake + + +   + 01
      cmake\OpenCVFindIPP.cmake + + +   + 01
      cmake\OpenCVFindIPPAsync.cmake + + +   + 01
      cmake\OpenCVFindLATEX.cmake + + +   + 01
      cmake\OpenCVFindLibsGrfmt.cmake + + +   + 01
      cmake\OpenCVFindLibsGUI.cmake + + +   + 01
      cmake\OpenCVFindLibsPerf.cmake + + +   + 01
      cmake\OpenCVFindLibsVideo.cmake + + +   + 01
      cmake\OpenCVFindMatlab.cmake + + +   + 01
      cmake\OpenCVFindOpenEXR.cmake + cpe:/a:openexr:openexr:- + + +   + 0LOW1
      cmake\OpenCVFindOpenNI.cmake + + +   + 01
      cmake\OpenCVFindOpenNI2.cmake + + +   + 02
      cmake\OpenCVFindWebP.cmake + + +   + 01
      cmake\OpenCVFindXimea.cmake + + +   + 01
      cmake\OpenCVGenABI.cmake + + +   + 01
      cmake\OpenCVGenAndroidMK.cmake + + +   + 01
      cmake\OpenCVGenConfig.cmake + + +   + 01
      cmake\OpenCVGenHeaders.cmake + + +   + 01
      cmake\OpenCVGenInfoPlist.cmake + + +   + 01
      cmake\OpenCVGenPkgconfig.cmake + + +   + 01
      cmake\OpenCVMinDepVersions.cmake + + +   + 01
      cmake\OpenCVModule.cmake + + +   + 01
      cmake\OpenCVPackaging.cmake + + +   + 01
      cmake\OpenCVPCHSupport.cmake + + +   + 01
      cmake\OpenCVUtils.cmake + + +   + 01
      cmake\OpenCVVersion.cmake + + +   + 01
      opencv\CMakeLists.txt + + +   + 02
      zlib\CMakeLists.txt + + +   + 02
      commons-cli-1.2.jar + commons-cli:commons-cli:1.2 + +   + 025
      commons-codec-1.2.jar + commons-codec:commons-codec:1.2 + +   + 020
      commons-collections-3.2.2.jar + cpe:/a:apache:commons_collections:3.2.2 + commons-collections:commons-collections:3.2.2 + +   + 0LOW28
      commons-compress-1.12.jar + cpe:/a:apache:commons-compress:1.12 + org.apache.commons:commons-compress:1.12 + +   + 0LOW29
      commons-fileupload-1.2.1.jar cpe:/a:apache:commons_fileupload:1.2.1 commons-fileupload:commons-fileupload:1.2.1 - - Medium + commons-fileupload:commons-fileupload:1.2.1 2 + High + 3 HIGHEST1623
      commons-httpclient-3.1.jarcommons-httpclient-3.1.jar cpe:/a:apache:commons-httpclient:3.1
      cpe:/a:apache:httpclient:3.1
      commons-httpclient:commons-httpclient:3.1 - + commons-httpclient:commons-httpclient:3.1 + Medium 12 LOW1120
      commons-logging-1.1.1.jarcommons-io-2.5.jar commons-logging:commons-logging:1.1.1 - commons-io:commons-io:2.5 +   01928
      commons-pool-1.5.3.jarcommons-lang-2.4.jar commons-pool:commons-pool:1.5.3 - commons-lang:commons-lang:2.4 +   02225
      commons-validator-1.4.0.jarcommons-lang3-3.3.2.jar commons-validator:commons-validator:1.4.0 - org.apache.commons:commons-lang3:3.3.2 +   02326
      daytrader-ear-2.1.7.earcommons-logging-1.1.1.jar + commons-logging:commons-logging:1.1.1 + +   + 021
      commons-pool-1.5.3.jar + commons-pool:commons-pool:1.5.3 + +   + 025
      commons-validator-1.4.0.jar + commons-validator:commons-validator:1.4.0 + +   + 026
      composer.lock +   0 1
      daytrader-ear-2.1.7.ear: dt-ejb.jar - cpe:/a:apache:geronimo:2.1.7 - org.apache.geronimo.daytrader:daytrader-ejb:2.1.7 - - High - 2HIGHEST10
      daytrader-ear-2.1.7.ear: geronimo-jaxrpc_1.1_spec-2.0.0.jar - cpe:/a:apache:geronimo:2.0 - org.apache.geronimo.specs:geronimo-jaxrpc_1.1_spec:2.0.0 - - High - 4HIGHEST11
      daytrader-ear-2.1.7.ear: streamer.jar - cpe:/a:apache:geronimo:2.1.7 - org.apache.geronimo.daytrader:daytrader-streamer:2.1.7 - - High - 2HIGHEST11
      daytrader-ear-2.1.7.ear: web.wardaytrader-ear-2.1.7.ear + +   + 02
      daytrader-ear-2.1.7.ear: dt-ejb.jar + cpe:/a:apache:geronimo:2.1.7 + org.apache.geronimo.daytrader:daytrader-ejb:2.1.7 + + High + 2HIGHEST15
      daytrader-ear-2.1.7.ear: geronimo-jaxrpc_1.1_spec-2.0.0.jar + org.apache.geronimo.specs:geronimo-jaxrpc_1.1_spec:2.0.0 + +   + 018
      daytrader-ear-2.1.7.ear: streamer.jar + cpe:/a:apache:apache_test:2.1.7 +
      + cpe:/a:apache:geronimo:2.1.7 +
      org.apache.geronimo.daytrader:daytrader-streamer:2.1.7 + + High + 2HIGHEST17
      daytrader-ear-2.1.7.ear: web.war + +   5
      daytrader-ear-2.1.7.ear: wsappclient.jardaytrader-ear-2.1.7.ear: wsappclient.jar cpe:/a:apache:geronimo:2.1.7 org.apache.geronimo.daytrader:daytrader-wsappclient:2.1.7 - org.apache.geronimo.daytrader:daytrader-wsappclient:2.1.7 + High 2 HIGHEST1117
      dependency-check-utils-1.4.4-SNAPSHOT.jar + org.owasp:dependency-check-utils:1.4.4-SNAPSHOT + +   + 014
      dojo-war-1.3.0.war - cpe:/a:dojo_toolkit:dojo_toolkit:1.3.0 -
      - cpe:/a:dojotoolkit:dojo:1.3 +
      dojo-war-1.3.0.war + cpe:/a:dojotoolkit:dojo:1.3 org.dojotoolkit:dojo-war:1.3.0 - + org.dojotoolkit:dojo-war:1.3.0 + High 54 HIGHEST712
      dwr-1.1.1.jardwr.jar cpe:/a:getahead:direct_web_remoting:1.1.1 uk.ltd.getahead:dwr:1.1.1 - uk.ltd.getahead:dwr:1.1.1 + High 3 HIGHEST157
      ehcache-core-2.2.0.jarehcache-core-2.2.0.jar net.sf.ehcache:ehcache-core:2.2.0 - net.sf.ehcache:ehcache-core:2.2.0 +   0 12
      FileHelpers.2.0.0.0.nupkg - -   - 02
      FileHelpers.2.0.0.0.nupkg: FileHelpers.nuspec - -   - 05
      FileHelpers.2.0.0.0.nupkg: FileHelpers.dll - -   - 04
      FileHelpers.2.0.0.0.nupkg: FileHelpers.ExcelStorage.dll - -   - 04
      FileHelpers.2.0.0.0.nupkg: Interop.Excel.dll - -   - 03
      FileHelpers.2.0.0.0.nupkg: Interop.Office.dll - -   - 03
      freemarker-2.3.12.jar - org.freemarker:freemarker:2.3.12 - -   - 013
      geronimo-javamail_1.4_spec-1.2.jar - cpe:/a:apache:geronimo:1.2 - org.apache.geronimo.specs:geronimo-javamail_1.4_spec:1.2 - - High - 2HIGHEST13
      geronimo-jms_1.1_spec-1.1.1.jar - cpe:/a:apache:geronimo:1.1.1 - org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1.1 - - High - 2HIGHEST11
      geronimo-jpa_2.0_spec-1.1.jar - cpe:/a:apache:geronimo:1.1 - org.apache.geronimo.specs:geronimo-jpa_2.0_spec:1.1 - - High - 2HIGHEST 16
      geronimo-stax-api_1.0_spec-1.0.1.jar - cpe:/a:apache:geronimo:1.0.1 - org.apache.geronimo.specs:geronimo-stax-api_1.0_spec:1.0.1 + FileHelpers.2.0.0.0.nupkg + cpe:/a:file:file:2.0.0.0 + + High 21 LOW152
      guice-3.0.jar - com.google.inject:guice:3.0 - -   - 020
      hazelcast-2.5.jar - com.hazelcast:hazelcast:2.5 - -   - 019
      hibernate3.jarFileHelpers.2.0.0.0.nupkg: FileHelpers.nuspec -   - 08
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-c3p0/pom.xml - org.hibernate:hibernate-c3p0:3.6.6.Final +   0 6
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-commons-annotations/pom.xml - org.hibernate:hibernate-commons-annotations:3.2.0.Final + FileHelpers.2.0.0.0.nupkg: FileHelpers.dll +   05
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-core/pom.xml - org.hibernate:hibernate-core:3.6.6.Final - -   - 06
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-ehcache/pom.xml - org.hibernate:hibernate-ehcache:3.6.6.Final - -   - 06
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-entitymanager/pom.xml - org.hibernate:hibernate-entitymanager:3.6.6.Final - -   - 06
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-envers/pom.xml - org.hibernate:hibernate-envers:3.6.6.Final - -   - 06
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-infinispan/pom.xml - org.hibernate:hibernate-infinispan:3.6.6.Final - -   - 06
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-jbosscache/pom.xml - org.hibernate:hibernate-jbosscache:3.6.6.Final - -   - 0 4
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-oscache/pom.xml - org.hibernate:hibernate-oscache:3.6.6.Final + FileHelpers.2.0.0.0.nupkg: FileHelpers.ExcelStorage.dll +   064
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-proxool/pom.xml - org.hibernate:hibernate-proxool:3.6.6.Final + FileHelpers.2.0.0.0.nupkg: Interop.Excel.dll +   064
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-swarmcache/pom.xml - org.hibernate:hibernate-swarmcache:3.6.6.Final + FileHelpers.2.0.0.0.nupkg: Interop.Office.dll +   064
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-testing/pom.xmlfreemarker-2.3.12.jar org.hibernate:hibernate-testing:3.6.6.Final - org.freemarker:freemarker:2.3.12 +   0618
      httpcore-4.0-beta1.jargeronimo-activation_1.1_spec-1.0.1.jar org.apache.httpcomponents:httpcore:4.0-beta1 - org.apache.geronimo.specs:geronimo-activation_1.1_spec:1.0.1 +   01218
      httpcore-nio-4.0-beta1.jargeronimo-javamail_1.4_spec-1.2.jar org.apache.httpcomponents:httpcore-nio:4.0-beta1 + org.apache.geronimo.specs:geronimo-javamail_1.4_spec:1.2 + +   + 018
      geronimo-jms_1.1_spec-1.1.1.jar + org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1.1 + +   + 018
      geronimo-jpa_2.0_spec-1.1.jar + org.apache.geronimo.specs:geronimo-jpa_2.0_spec:1.1 + +   + 022
      geronimo-jta_1.1_spec-1.1.1.jar + org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1.1 + +   + 018
      geronimo-stax-api_1.0_spec-1.0.1.jar + org.apache.geronimo.specs:geronimo-stax-api_1.0_spec:1.0.1 + +   + 018
      guice-3.0.jar + com.google.inject:guice:3.0 + +   + 022
      h2-1.3.176.jar + com.h2database:h2:1.3.176 + +   + 018
      hamcrest-core-1.3.jar + org.hamcrest:hamcrest-core:1.3 + +   + 017
      hazelcast-2.5.jar + com.hazelcast:hazelcast:2.5 + +   + 021
      hibernate3.jar +   010
      httpcore-4.0-beta1.jar + org.apache.httpcomponents:httpcore:4.0-beta1 + +   + 015
      httpcore-nio-4.0-beta1.jar + org.apache.httpcomponents:httpcore-nio:4.0-beta1 + +   + 015
      javax.inject-1.jar + javax.inject:javax.inject:1 + +   + 0 13
      javax.inject-1.jarjavax.json-1.0.4.jar javax.inject:javax.inject:1 - org.glassfish:javax.json:1.0.4 +   0920
      jaxb-xercesImpl-1.5.jarjaxb-xercesImpl-1.5.jar activesoap:jaxb-xercesImpl:1.5 - activesoap:jaxb-xercesImpl:1.5 +   022
      jaxen-1.1.1.jar + jaxen:jaxen:1.1.1 + +   + 0 19
      jaxen-1.1.1.jarjcip-annotations-1.0.jar jaxen:jaxen:1.1.1 - net.jcip:jcip-annotations:1.0 +   01513
      jetty-6.1.0.jarjetty-6.1.0.jar cpe:/a:jetty:jetty:6.1.0
      @@ -1311,21 +2158,101 @@ arising out of or in connection with the use of this tool, the analysis performe
      cpe:/a:mortbay_jetty:jetty:6.1
      org.mortbay.jetty:jetty:6.1.0 - org.mortbay.jetty:jetty:6.1.0 + High 10 HIGHEST1214
      log4net.2.0.3.nuspecjmockit-1.24.jar + org.jmockit:jmockit:1.24 + +   + 013
      jsoup-1.9.2.jar + org.jsoup:jsoup:1.9.2 + +   + 017
      jsr305-3.0.1.jar + com.google.code.findbugs:jsr305:3.0.1 + +   + 015
      junit-4.12.jar + junit:junit:4.12 + +   + 017
      junit4-ant-2.0.13.jar + com.carrotsearch.randomizedtesting:junit4-ant:2.0.13 + +   + 015
      log4net.2.0.3.nuspec cpe:/a:apache:log4net:2.0.3 + +   + 0LOW7
      log4net.dll + cpe:/a:apache:log4net:1.2.13.0 + +   5
      log4net.dll - cpe:/a:apache:log4net:1.2.13.0 - logback-classic-1.1.7.jar + ch.qos.logback:logback-classic:1.1.7 + +   + 019
      logback-core-1.1.7.jar + ch.qos.logback:logback-core:1.1.7 + +   + 019
      lucene-analyzers-common-4.7.2.jar + org.apache.lucene:lucene-analyzers-common:4.7.2 + +   + 021
      lucene-codecs-4.7.2.jar + org.apache.lucene:lucene-codecs:4.7.2 + +   + 021
      lucene-core-4.7.2.jar + org.apache.lucene:lucene-core:4.7.2 + +   + 020
      lucene-queries-4.7.2.jar + org.apache.lucene:lucene-queries:4.7.2 + +   + 022
      lucene-queryparser-4.7.2.jar + org.apache.lucene:lucene-queryparser:4.7.2 + +   + 022
      lucene-sandbox-4.7.2.jar + org.apache.lucene:lucene-sandbox:4.7.2 + +   + 022
      lucene-test-framework-4.7.2.jar + cpe:/a:apache:apache_test:4.7.2 + org.apache.lucene:lucene-test-framework:4.7.2 +   0 LOW520
      mail-1.4.jarmail-1.4.jar cpe:/a:sun:javamail:1.4 javax.mail:mail:1.4 - javax.mail:mail:1.4 + Medium 1 LOW1720
      mailapi-1.5.6.jar + cpe:/a:sun:javamail:1.5.6 + com.sun.mail:mailapi:1.5.6 + + Medium + 1LOW27
      maven-scm-api-1.8.1.jarmaven-scm-api-1.8.1.jar org.apache.maven.scm:maven-scm-api:1.8.1 - org.apache.maven.scm:maven-scm-api:1.8.1 +   01318
      maven-scm-provider-cvs-commons-1.8.1.jarmaven-scm-provider-cvs-commons-1.8.1.jar org.apache.maven.scm:maven-scm-provider-cvs-commons:1.8.1 - org.apache.maven.scm:maven-scm-provider-cvs-commons:1.8.1 +   01518
      maven-scm-provider-cvsexe-1.8.1.jarmaven-scm-provider-cvsexe-1.8.1.jar org.apache.maven.scm:maven-scm-provider-cvsexe:1.8.1 - org.apache.maven.scm:maven-scm-provider-cvsexe:1.8.1 +   01418
      mysql-connector-java-5.1.27-bin.jar + cpe:/a:mysql:mysql:5.1.27 + + + High + 97HIGHEST12
      neethi-2.0.4.jarneethi-2.0.4.jar cpe:/a:apache:apache_test:2.0.4 org.apache.neethi:neethi:2.0.4 - org.apache.neethi:neethi:2.0.4 +   0 LOW2116
      ognl-2.6.11.jar - opensymphony:ognl:2.6.11 + debug/package.json +   087
      shelljs/package.json + + +   + 07
      openjpa-2.0.1.jardns-sync/package.json + cpe:/a:dns-sync_project:dns-sync:0.1.0::~~~node.js~~ + + + High + 1HIGHEST6
      ognl-2.6.11.jar + opensymphony:ognl:2.6.11 + +   + 012
      openjpa-2.0.1.jar cpe:/a:apache:openjpa:2.0.1 org.apache.openjpa:openjpa:2.0.1 - org.apache.openjpa:openjpa:2.0.1 + High 1 HIGHEST1422
      org.mortbay.jetty.jar + openssl\opensslv.h + cpe:/a:openssl:openssl:1.0.2c + + + High + 33HIGH4
      org.mortbay.jetty.jar cpe:/a:jetty:jetty:4.2.27
      cpe:/a:mortbay:jetty:4.2.27
      - cpe:/a:mortbay_jetty:jetty:4.2 + cpe:/a:mortbay_jetty:jetty:4.2.27
      jetty:jetty:4.2.27 - - High + jetty:jetty:4.2.27 7 + Medium + 5 HIGHEST919
      org.mortbay.jmx.jarorg.mortbay.jmx.jar +   3
      plexus-utils-3.0.7.jarplexus-utils-3.0.7.jar org.codehaus.plexus:plexus-utils:3.0.7 + org.codehaus.plexus:plexus-utils:3.0.7 + +   + 017
      EggTest-0.0.1-py2.7.egg +   0 14
      EggTest-0.0.1-py2.7.egg - -   - 05
      eggtest/__init__.py - -   - 067
      Django-1.7.2-py2.py3-none-any.whl - cpe:/a:djangoproject:django:1.7.2 + Django-1.7.2-py2.py3-none-any.whl + cpe:/a:django_project:django:1.7.2 +
      + cpe:/a:djangoproject:django:1.7.2
      - Medium + + + High 714 HIGHEST67
      eggtest/__init__.pyeggtest/__init__.py -   - 06
      Django-1.7.2.dist-info/METADATA - -   - 06
      EggTest.egg-info/PKG-INFO - -   - 05
      regexp-1.3.jar - regexp:regexp:1.3 +   0 76
      serp-1.13.1.jarDjango-1.7.2.dist-info/METADATA + cpe:/a:django_project:django:1.7.2 + + +   + 0LOW6
      django/__init__.py + + +   + 01
      EGG-INFO/PKG-INFO + + +   + 06
      randomizedtesting-runner-2.0.13.jar net.sourceforge.serp:serp:1.13.1 + com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.0.13 + +   + 017
      regexp-1.3.jar + regexp:regexp:1.3 + +   + 010
      Gemfile.lock + + +   + 01
      dalli-2.7.5.gemspec +   @@ -1583,164 +2733,278 @@ arising out of or in connection with the use of this tool, the analysis performe 10
      servlet-api-2.5.jar - javax.servlet:servlet-api:2.5 + Gemfile.lock +   0 121
      slf4j-api-1.5.11.jar - org.slf4j:slf4j-api:1.5.11 + activerecord-oracle_enhanced-adapter-1.1.7.gemspec +   0 169
      serp-1.13.1.jar + net.sourceforge.serp:serp:1.13.1 + +   + 013
      spring-core-2.5.5.jar - cpe:/a:springsource:spring_framework:2.5.5 + servlet-api-2.5.jar + cpe:/a:sun:one_application_server:2.5 + javax.servlet:servlet-api:2.5 + + Medium + 3LOW16
      slf4j-api-1.7.21.jar + org.slf4j:slf4j-api:1.7.21 + +   + 020
      spring-aop-3.0.0.RELEASE.jar + org.springframework:spring-aop:3.0.0.RELEASE + +   + 019
      spring-asm-3.0.0.RELEASE.jar + org.springframework:spring-asm:3.0.0.RELEASE + +   + 019
      spring-core-2.5.5.jar + cpe:/a:pivotal:spring_framework:2.5.5 +
      + cpe:/a:pivotal_software:spring_framework:2.5.5 +
      + cpe:/a:springsource:spring_framework:2.5.5
      cpe:/a:vmware:springsource_spring_framework:2.5.5
      org.springframework:spring-core:2.5.5 - org.springframework:spring-core:2.5.5 + High 7 HIGHEST1926
      spring-core-3.0.0.RELEASE.jar - cpe:/a:springsource:spring_framework:3.0.0 + spring-core-3.0.0.RELEASE.jar + cpe:/a:pivotal:spring_framework:3.0.0 +
      + cpe:/a:pivotal_software:spring_framework:3.0.0 +
      + cpe:/a:springsource:spring_framework:3.0.0
      cpe:/a:vmware:springsource_spring_framework:3.0.0
      org.springframework:spring-core:3.0.0.RELEASE - org.springframework:spring-core:3.0.0.RELEASE + High 8 HIGHEST2023
      spring-retry-1.1.0.RELEASE.jar - cpe:/a:vmware:springsource_spring_framework:1.1.0 - org.springframework.retry:spring-retry:1.1.0.RELEASE - spring-expression-3.0.0.RELEASE.jar + org.springframework:spring-expression:3.0.0.RELEASE +   0LOW1719
      spring-retry-1.1.0.RELEASE.jar + org.springframework.retry:spring-retry:1.1.0.RELEASE + +   + 014
      spring-security-core-3.0.0.RELEASE.jarspring-security-core-3.0.0.RELEASE.jar cpe:/a:vmware:springsource_spring_security:3.0.0 org.springframework.security:spring-security-core:3.0.0.RELEASE - org.springframework.security:spring-security-core:3.0.0.RELEASE + Medium 5 HIGHEST1617
      spring-security-web-3.0.0.RELEASE.jar + org.springframework.security:spring-security-web:3.0.0.RELEASE + +   + 014
      spring-tx-3.0.0.RELEASE.jar + org.springframework:spring-tx:3.0.0.RELEASE + +   + 018
      stagedhttp-modified.tar: commons-httpclient-2.0.jarstagedhttp-modified.tar: commons-httpclient-2.0.jar cpe:/a:apache:commons-httpclient:2.0
      cpe:/a:apache:httpclient:2.0
      commons-httpclient:commons-httpclient:2.0 - + commons-httpclient:commons-httpclient:2.0 + Medium 12 LOW1317
      stagedhttp-modified.tar: commons-logging.jarstagedhttp-modified.tar: commons-logging.jar commons-logging:commons-logging:1.0.3 - commons-logging:commons-logging:1.0.3 +   01518
      stagedhttp-modified.tar: dom4j.jarstagedhttp-modified.tar: dom4j.jar dom4j:dom4j:1.4 - dom4j:dom4j:1.4 +   01214
      stagedhttp-modified.tar: jgroups-all.jarstagedhttp-modified.tar: jgroups-all.jar jgroups:jgroups-all:2.2.7 - jgroups:jgroups-all:2.2.7 +   068
      stagedhttp-modified.tar: log4j.jarstagedhttp-modified.tar: log4j.jar +   037
      stagedhttp-modified.tar: mail.jarstagedhttp-modified.tar: mail.jar cpe:/a:sun:javamail:1.3.2 + Medium 11
      stagedhttp-modified.tar: serializer.jarstagedhttp-modified.tar: serializer.jar -   - 04
      stagedhttp-modified.tar: xalan.jar - -   - 02
      stagedhttp-modified.tar: xmlsec-1.3.0.jar - org.codehaus.xfire:xmlsec:1.3.0 +   01311
      stagedhttp-modified.tar: xalan.jar + cpe:/a:apache:xalan-java:2.7.0 + + + High + 1MEDIUM28
      stagedhttp-modified.tar: xss4j.jar - stagedhttp-modified.tar: xmlsec-1.3.0.jar + org.codehaus.xfire:xmlsec:1.3.0 +   0321
      stagedhttp-modified.tar: xss4j.jar + + +   + 04
      struts.jarstruts.jar cpe:/a:apache:struts:1.2.7 struts:struts:1.2.7 - + struts:struts:1.2.7 + High 7HIGHEST 10HIGHEST20
      struts2-core-2.1.2.jarstruts2-core-2.1.2.jar cpe:/a:apache:struts:2.1.2 org.apache.struts:struts2-core:2.1.2 - + org.apache.struts:struts2-core:2.1.2 + High 2632 HIGHEST1116
      uber-1.0-SNAPSHOT.jarEasyPeasy.podspec -   - 01
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.google.guava/guava/pom.xml - com.google.guava:guava:11.0.1 +   0 67
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.googlecode.jtype/jtype/pom.xml - com.googlecode.jtype:jtype:0.1.1 + Gloss.podspec +   0 48
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.sun.jersey/jersey-core/pom.xml - com.sun.jersey:jersey-core:1.11 + uber-1.0-SNAPSHOT.jar +   0 52
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.sun.jersey/jersey-server/pom.xmlvelocity-1.7.jar com.sun.jersey:jersey-server:1.11 - org.apache.velocity:velocity:1.7 +   0 527
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.sun.jersey/jersey-servlet/pom.xmlwar-4.0.war com.sun.jersey:jersey-servlet:1.11 - org.glassfish.main.admingui:war:4.0 +   0 5
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.dropwizard/dropwizard-core/pom.xml - com.yammer.dropwizard:dropwizard-core:0.1.3 - -   - 05
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-annotation/pom.xml - com.yammer.metrics:metrics-annotation:2.0.0-RC0 - -   - 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-core/pom.xml - com.yammer.metrics:metrics-core:2.0.0-RC0 - -   - 05
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-jersey/pom.xml - com.yammer.metrics:metrics-jersey:2.0.0-RC0 - -   - 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-jetty/pom.xml - cpe:/a:jetty:jetty:2.0.0.rc0 - com.yammer.metrics:metrics-jetty:2.0.0-RC0 - -   - 0LOW4
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-log4j/pom.xml - com.yammer.metrics:metrics-log4j:2.0.0-RC0 - -   - 05
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-servlet/pom.xml - com.yammer.metrics:metrics-servlet:2.0.0-RC0 - -   - 05
      uber-1.0-SNAPSHOT.jar\META-INF/maven/commons-io/commons-io/pom.xml - commons-io:commons-io:1.3.2 - -   - 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/javax.validation/validation-api/pom.xml - javax.validation:validation-api:1.0.0.GA - -   - 04
      uber-1.0-SNAPSHOT.jar\META-INF/maven/log4j/log4j/pom.xml - log4j:log4j:1.2.16 - -   - 05
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-continuation/pom.xml - cpe:/a:jetty:jetty:7.6.0.rc4 - org.eclipse.jetty:jetty-continuation:7.6.0.RC4 - -   - 0LOW3
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-http/pom.xml - cpe:/a:jetty:jetty:7.6.0.rc4 - org.eclipse.jetty:jetty-http:7.6.0.RC4 - -   - 0LOW3
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-io/pom.xml - cpe:/a:jetty:jetty:7.6.0.rc4 - org.eclipse.jetty:jetty-io:7.6.0.RC4 - -   - 0LOW3
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-security/pom.xml - cpe:/a:jetty:jetty:7.6.0.rc4 - org.eclipse.jetty:jetty-security:7.6.0.RC4 - -   - 0LOW3
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-server/pom.xml - cpe:/a:jetty:jetty:7.6.0.rc4 - org.eclipse.jetty:jetty-server:7.6.0.RC4 - -   - 0LOW3
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-servlet/pom.xml - cpe:/a:jetty:jetty:7.6.0.rc4 - org.eclipse.jetty:jetty-servlet:7.6.0.RC4 - -   - 0LOW3
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-util/pom.xml - cpe:/a:jetty:jetty:7.6.0.rc4 - org.eclipse.jetty:jetty-util:7.6.0.RC4 - -   - 0LOW39
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.hibernate/hibernate-validator/pom.xml - cpe:/a:hibernate:hibernate_validator:4.2.0 + war-4.0.war: commons-fileupload-1.1.1.jar + cpe:/a:apache:commons_fileupload:1.1.1 + commons-fileupload:commons-fileupload:1.1.1 + + High + 3HIGHEST22
      war-4.0.war: commons-io-1.3.1.jar + commons-io:commons-io:1.3.1 + +   + 022
      war-4.0.war: dojo-ajax-nodemo-0.4.1.jar + cpe:/a:sun:woodstock:0.4.1 + com.sun.woodstock.dependlibs:dojo-ajax-nodemo:0.4.1 + +   + 0LOW8
      war-4.0.war: json-1.0.jar + cpe:/a:sun:woodstock:1.0 + com.sun.woodstock.dependlibs:json:1.0 + +   + 0LOW9
      war-4.0.war: prototype-1.5.0.jar + cpe:/a:sun:woodstock:1.5.0 + com.sun.woodstock.dependlibs:prototype:1.5.0 + +   + 0LOW8
      war-4.0.war: webui-jsf-4.0.2.10.jar + com.sun.woodstock:webui-jsf:4.0.2.10 + +   + 022
      war-4.0.war: webui-jsf-suntheme-4.0.2.10.jar + com.sun.woodstock:webui-jsf-suntheme:4.0.2.10 + +   + 018
      war-4.0.war: console-core-4.0.jar + org.glassfish.main.admingui:console-core:4.0 + +   + 015
      woden-api-1.0M8.jar + org.apache.woden:woden-api:1.0M8 + +   + 016
      woden-impl-dom-1.0M8.jar + org.apache.woden:woden-impl-dom:1.0M8 + +   + 016
      wsdl4j-1.6.2.jar + wsdl4j:wsdl4j:1.6.2 + +   + 019
      wstx-asl-3.2.4.jar + org.codehaus.woodstox:wstx-asl:3.2.4 + +   + 020
      xalan-2.7.0.jar + cpe:/a:apache:xalan-java:2.7.0 org.hibernate:hibernate-validator:4.2.0.Final - xalan:xalan:2.7.0 + + High + 1HIGHEST28
      xercesImpl-2.8.1.jar + xerces:xercesImpl:2.8.1 + +   + 055
      xml-apis-1.0.b2.jar + xml-apis:xml-apis:1.0.b2 + +   + 035
      xmlParserAPIs-2.6.0.jar + xerces:xmlParserAPIs:2.6.0 + +   + 031
      xmlpull-1.1.3.1.jar + xmlpull:xmlpull:1.1.3.1 + +   + 012
      XmlSchema-1.4.2.jar + org.apache.ws.commons.schema:XmlSchema:1.4.2 + +   + 017
      xpp3_min-1.1.4c.jar + xpp3:xpp3_min:1.1.4c + +   + 014
      xstream-1.4.8.jar + cpe:/a:x-stream:xstream:1.4.8 + com.thoughtworks.xstream:xstream:1.4.8 + Medium 1 HIGHEST3
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.owasp.dependency-check/uber/pom.xml - org.owasp.dependency-check:uber:1.0-SNAPSHOT - -   - 03
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.slf4j/jul-to-slf4j/pom.xml - org.slf4j:jul-to-slf4j:1.6.4 - -   - 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.slf4j/slf4j-api/pom.xml - org.slf4j:slf4j-api:1.6.4 - -   - 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.slf4j/slf4j-log4j12/pom.xml - org.slf4j:slf4j-log4j12:1.6.4 - -   - 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.yaml/snakeyaml/pom.xml - org.yaml:snakeyaml:1.9 - -   - 04
      velocity-1.7.jar - org.apache.velocity:velocity:1.7 - -   - 023
      war-4.0.war - org.glassfish.main.admingui:war:4.0 - -   - 0727
      war-4.0.war: commons-fileupload-1.1.1.jar - cpe:/a:apache:commons_fileupload:1.1.1 - commons-fileupload:commons-fileupload:1.1.1 - - Medium - 2HIGHEST13
      war-4.0.war: commons-io-1.3.1.jar - commons-io:commons-io:1.3.1 - -   - 017
      war-4.0.war: dojo-ajax-nodemo-0.4.1.jar - cpe:/a:sun:woodstock:0.4.1 - com.sun.woodstock.dependlibs:dojo-ajax-nodemo:0.4.1 - -   - 0LOW8
      war-4.0.war: json-1.0.jar - com.sun.woodstock.dependlibs:json:1.0 - -   - 06
      war-4.0.war: prototype-1.5.0.jar - cpe:/a:sun:woodstock:1.5.0 - com.sun.woodstock.dependlibs:prototype:1.5.0 - -   - 0LOW8
      war-4.0.war: webui-jsf-4.0.2.10.jar - com.sun.woodstock:webui-jsf:4.0.2.10 - -   - 012
      war-4.0.war: webui-jsf-suntheme-4.0.2.10.jar - com.sun.woodstock:webui-jsf-suntheme:4.0.2.10 - -   - 010
      war-4.0.war: console-core-4.0.jar - org.glassfish.main.admingui:console-core:4.0 - -   - 013
      woden-api-1.0M8.jar - org.apache.woden:woden-api:1.0M8 - -   - 017
      woden-impl-dom-1.0M8.jar - org.apache.woden:woden-impl-dom:1.0M8 - -   - 015
      wsdl4j-1.6.2.jar - wsdl4j:wsdl4j:1.6.2 - -   - 014
      wstx-asl-3.2.4.jar - org.codehaus.woodstox:wstx-asl:3.2.4 - -   - 018
      xalan-2.7.0.jar - xalan:xalan:2.7.0 - -   - 07
      xercesImpl-2.8.1.jar - xerces:xercesImpl:2.8.1 - -   - 011
      xml-apis-1.3.04.jar - xml-apis:xml-apis:1.3.04 - -   - 011
      xmlParserAPIs-2.6.0.jar - xerces:xmlParserAPIs:2.6.0 - -   - 07
      XmlSchema-1.4.2.jar - org.apache.ws.commons.schema:XmlSchema:1.4.2 - -   - 017
      xwork-2.1.1.jarxwork-2.1.1.jar cpe:/a:opensymphony:xwork:2.1.1 com.opensymphony:xwork:2.1.1 - com.opensymphony:xwork:2.1.1 + Medium 3 HIGHEST 14
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-core/pom.xml + org.hibernate:hibernate-core:3.6.6.Final + +   + 07
      junit4-ant-2.0.13.jar\META-INF/maven/com.google.guava/guava/pom.xml + com.google.guava:guava:14.0.1 + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-commons-annotations/pom.xml + org.hibernate:hibernate-commons-annotations:3.2.0.Final + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-ehcache/pom.xml + org.hibernate:hibernate-ehcache:3.6.6.Final + +   + 07
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.owasp.dependency-check/uber/pom.xml + org.owasp.dependency-check:uber:1.0-SNAPSHOT + +   + 05
      junit4-ant-2.0.13.jar\META-INF/maven/commons-io/commons-io/pom.xml + commons-io:commons-io:2.3 + +   + 09
      junit4-ant-2.0.13.jar\META-INF/maven/org.simpleframework/simple-xml/pom.xml + org.simpleframework:simple-xml:2.6.2 + +   + 06
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-jbosscache/pom.xml + org.hibernate:hibernate-jbosscache:3.6.6.Final + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-infinispan/pom.xml + org.hibernate:hibernate-infinispan:3.6.6.Final + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-testing/pom.xml + org.hibernate:hibernate-testing:3.6.6.Final + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-oscache/pom.xml + org.hibernate:hibernate-oscache:3.6.6.Final + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-swarmcache/pom.xml + org.hibernate:hibernate-swarmcache:3.6.6.Final + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-c3p0/pom.xml + org.hibernate:hibernate-c3p0:3.6.6.Final + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-proxool/pom.xml + org.hibernate:hibernate-proxool:3.6.6.Final + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-entitymanager/pom.xml + org.hibernate:hibernate-entitymanager:3.6.6.Final + +   + 07
      hibernate3.jar\META-INF/maven/org.hibernate/hibernate-envers/pom.xml + org.hibernate:hibernate-envers:3.6.6.Final + +   + 07
      uber-1.0-SNAPSHOT.jar\META-INF/maven/commons-io/commons-io/pom.xml + commons-io:commons-io:1.3.2 + +   + 09
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.dropwizard/dropwizard-core/pom.xml + com.yammer.dropwizard:dropwizard-core:0.1.3 + +   + 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.sun.jersey/jersey-core/pom.xml + com.sun.jersey:jersey-core:1.11 + +   + 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.sun.jersey/jersey-server/pom.xml + com.sun.jersey:jersey-server:1.11 + +   + 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.sun.jersey/jersey-servlet/pom.xml + com.sun.jersey:jersey-servlet:1.11 + +   + 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-core/pom.xml + com.yammer.metrics:metrics-core:2.0.0-RC0 + +   + 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-servlet/pom.xml + com.yammer.metrics:metrics-servlet:2.0.0-RC0 + +   + 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-jetty/pom.xml + cpe:/a:jetty:jetty:2.0.0.rc0 + com.yammer.metrics:metrics-jetty:2.0.0-RC0 + +   + 0LOW6
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-log4j/pom.xml + com.yammer.metrics:metrics-log4j:2.0.0-RC0 + +   + 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/log4j/log4j/pom.xml + log4j:log4j:1.2.16 + +   + 07
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-jersey/pom.xml + com.yammer.metrics:metrics-jersey:2.0.0-RC0 + +   + 07
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.yammer.metrics/metrics-annotation/pom.xml + com.yammer.metrics:metrics-annotation:2.0.0-RC0 + +   + 07
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.slf4j/slf4j-api/pom.xml + org.slf4j:slf4j-api:1.6.4 + +   + 08
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.slf4j/slf4j-log4j12/pom.xml + org.slf4j:slf4j-log4j12:1.6.4 + +   + 08
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.slf4j/jul-to-slf4j/pom.xml + org.slf4j:jul-to-slf4j:1.6.4 + +   + 08
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-server/pom.xml + cpe:/a:jetty:jetty:7.6.0.rc4 + org.eclipse.jetty:jetty-server:7.6.0.RC4 + +   + 0LOW8
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-continuation/pom.xml + cpe:/a:jetty:jetty:7.6.0.rc4 + org.eclipse.jetty:jetty-continuation:7.6.0.RC4 + +   + 0LOW7
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-servlet/pom.xml + cpe:/a:jetty:jetty:7.6.0.rc4 + org.eclipse.jetty:jetty-servlet:7.6.0.RC4 + +   + 0LOW7
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-security/pom.xml + cpe:/a:jetty:jetty:7.6.0.rc4 + org.eclipse.jetty:jetty-security:7.6.0.RC4 + +   + 0LOW7
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-http/pom.xml + cpe:/a:jetty:jetty:7.6.0.rc4 + org.eclipse.jetty:jetty-http:7.6.0.RC4 + +   + 0LOW6
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-io/pom.xml + org.eclipse.jetty:jetty-io:7.6.0.RC4 + +   + 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.eclipse.jetty/jetty-util/pom.xml + cpe:/a:jetty:jetty:7.6.0.rc4 + org.eclipse.jetty:jetty-util:7.6.0.RC4 + +   + 0LOW7
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.google.guava/guava/pom.xml + com.google.guava:guava:11.0.1 + +   + 07
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.hibernate/hibernate-validator/pom.xml + cpe:/a:hibernate:hibernate_validator:4.2.0 + org.hibernate:hibernate-validator:4.2.0.Final + + Medium + 1HIGHEST7
      uber-1.0-SNAPSHOT.jar\META-INF/maven/com.googlecode.jtype/jtype/pom.xml + com.googlecode.jtype:jtype:0.1.1 + +   + 06
      uber-1.0-SNAPSHOT.jar\META-INF/maven/javax.validation/validation-api/pom.xml + javax.validation:validation-api:1.0.0.GA + +   + 05
      uber-1.0-SNAPSHOT.jar\META-INF/maven/org.yaml/snakeyaml/pom.xml + org.yaml:snakeyaml:1.9 + +   + 06
      ffmpeg\ffmpeg_version.cmake:libavformat + + +   + 02
      ffmpeg\ffmpeg_version.cmake:libavutil + + +   + 02
      ffmpeg\ffmpeg_version.cmake:libswscale + + +   + 02
      ffmpeg\ffmpeg_version.cmake:libavresample + + +   + 02
      composer.lock:classpreloader/classpreloader + + +   + 03
      composer.lock:danielstjules/stringy + + +   + 03
      composer.lock:dnoegel/php-xdg-base-dir + + +   + 03
      composer.lock:doctrine/inflector + + +   + 03
      composer.lock:jakub-onderka/php-console-color + + +   + 03
      composer.lock:jakub-onderka/php-console-highlighter + + +   + 03
      composer.lock:jeremeamia/SuperClosure + + +   + 03
      composer.lock:laravel/framework + + +   + 03
      composer.lock:laravel/laravel + + +   + 03
      composer.lock:league/flysystem + + +   + 03
      composer.lock:monolog/monolog + + +   + 03
      composer.lock:mtdowling/cron-expression + + +   + 03
      composer.lock:nesbot/carbon + + +   + 03
      composer.lock:nikic/php-parser + + +   + 03
      composer.lock:psr/log + + +   + 03
      composer.lock:psy/psysh + + +   + 03
      composer.lock:swiftmailer/swiftmailer + + +   + 03
      composer.lock:symfony/console + + +   + 04
      composer.lock:symfony/css-selector + + +   + 04
      composer.lock:symfony/debug + + +   + 04
      composer.lock:symfony/dom-crawler + + +   + 04
      composer.lock:symfony/event-dispatcher + + +   + 04
      composer.lock:symfony/finder + + +   + 04
      composer.lock:symfony/http-foundation + + +   + 04
      composer.lock:symfony/http-kernel + + +   + 04
      composer.lock:symfony/process + + +   + 04
      composer.lock:symfony/routing + + +   + 04
      composer.lock:symfony/translation + + +   + 04
      composer.lock:symfony/var-dumper + + +   + 04
      composer.lock:vlucas/phpdotenv + + +   + 03

      Dependencies

      -

      annogen-0.1.0.jar

      +

      activation-1.1.jar

      +

      Description:  + JavaBeans Activation Framework (JAF) is a standard extension to the Java platform that lets you take advantage of standard services to: determine the type of an arbitrary piece of data; encapsulate access to it; discover the operations available on it; and instantiate the appropriate bean to perform the operation(s). +

      - File Path: target\test-classes\annogen-0.1.0.jar
      - MD5: ff275c3491ac6715ad9f6c22a9660503
      - SHA1: a8de34ea7aa93765d24dc16ec9c61af5160bb899 + License:

      Common Development and Distribution License (CDDL) v1.0: https://glassfish.dev.java.net/public/CDDLv1.0.html
      + File Path: C:\Users\jerem\projects\DependencyCheck\dependency-check-core\target\test-classes\activation-1.1.jar
      + MD5: 8ae38e87cd4f86059c0294a8fe3e0b18
      + SHA1: e6cb541461c2834bdea3eb920f1884d1eb508b50

      Identifiers

      -

      ant-1.8.2.jar

      +

      annogen-0.1.0.jar

      - File Path: target\test-classes\ant-1.8.2.jar
      - MD5: 9463f65940f928d650a95aeb057a4e0a
      - SHA1: fc33bf7cd8c5309dd7b81228e8626515ee42efd9 + File Path: C:\Users\jerem\projects\DependencyCheck\dependency-check-core\target\test-classes\annogen-0.1.0.jar
      + MD5: ff275c3491ac6715ad9f6c22a9660503
      + SHA1: a8de34ea7aa93765d24dc16ec9c61af5160bb899

      Identifiers

      -

      aopalliance-1.0.jar

      +

      annotations-3.0.1u2.jar

      -

      Description: AOP Alliance

      +

      Description: Annotation the FindBugs tool supports

      - License:

      Public Domain
      - File Path: target\test-classes\aopalliance-1.0.jar
      - MD5: 04177054e180d09e3998808efa0401c7
      - SHA1: 0235ba8b489512805ac13a8f9ea77a1ca5ebe3e8 + License:
      GNU Lesser Public License: http://www.gnu.org/licenses/lgpl.html
      + File Path: C:\Users\jerem\projects\DependencyCheck\dependency-check-core\target\test-classes\annotations-3.0.1u2.jar
      + MD5: 4242c4e6b7719eeb3f91d3fe4c7af12c
      + SHA1: 89a670596c98e416fb2583c08ae34cc5c3ce2097

      +

      Identifiers

      +
      + +
      +
      +

      ant-1.9.7.jar

      +
      +

      + File Path: C:\Users\jerem\projects\DependencyCheck\dependency-check-core\target\test-classes\ant-1.9.7.jar
      + MD5: a14502c25ee6bc76c4614315845b29e9
      + SHA1: 3b2a10512ee6537d3852c9b693a0284dcab5de68 +

      + + +

      Identifiers

      +
      + +
      +
      +

      aopalliance-1.0.jar

      +
      +

      Description: AOP Alliance

      +

      + License:

      Public Domain
      + File Path: C:\Users\jerem\projects\DependencyCheck\dependency-check-core\target\test-classes\aopalliance-1.0.jar
      + MD5: 04177054e180d09e3998808efa0401c7
      + SHA1: 0235ba8b489512805ac13a8f9ea77a1ca5ebe3e8 +

      + + -

      Identifiers

      -
      +

      Identifiers

      +
      -

      aspectjrt-1.6.5.jar

      +

      aspectjrt-1.6.5.jar

      Description: The runtime needed to execute a program using AspectJ

      License:

      Eclipse Public License - v 1.0: http://www.eclipse.org/legal/epl-v10.html
      - File Path: target\test-classes\aspectjrt-1.6.5.jar
      + File Path: C:\Users\jerem\projects\DependencyCheck\dependency-check-core\target\test-classes\aspectjrt-1.6.5.jar
      MD5: 71d9982a11bf94ac21221e2f052f3869
      SHA1: d35f32a63eb823dc2dffc7ee6fdb8e00a680d114

      - -
    125. BID - 65400
    126. BUGTRAQ - 20140625 NEW VMSA-2014-0007 - VMware product updates address security vulnerabilities in Apache Struts library
    127. BUGTRAQ - 20141205 NEW: VMSA-2014-0012 - VMware vSphere product updates address security vulnerabilities
    128. -
    129. BUGTRAQ - 20150402 NEW : VMSA-2015-0003 VMware product updates address critical information disclosure issue in JRE
    130. CONFIRM - http://advisories.mageia.org/MGASA-2014-0110.html
    131. CONFIRM - http://svn.apache.org/r1565143
    132. CONFIRM - http://tomcat.apache.org/security-7.html
    133. CONFIRM - http://tomcat.apache.org/security-8.html
    134. +
    135. CONFIRM - http://www-01.ibm.com/support/docview.wss?uid=swg21669554
    136. CONFIRM - http://www-01.ibm.com/support/docview.wss?uid=swg21675432
    137. +
    138. CONFIRM - http://www-01.ibm.com/support/docview.wss?uid=swg21676091
    139. +
    140. CONFIRM - http://www-01.ibm.com/support/docview.wss?uid=swg21676092
    141. CONFIRM - http://www-01.ibm.com/support/docview.wss?uid=swg21676401
    142. CONFIRM - http://www-01.ibm.com/support/docview.wss?uid=swg21676403
    143. CONFIRM - http://www-01.ibm.com/support/docview.wss?uid=swg21676405
    144. @@ -3370,98 +7868,107 @@ arising out of or in connection with the use of this tool, the analysis performe
    145. CONFIRM - http://www.huawei.com/en/security/psirt/security-bulletins/security-advisories/hw-350733.htm
    146. CONFIRM - http://www.oracle.com/technetwork/topics/security/cpuapr2015-2365600.html
    147. CONFIRM - http://www.oracle.com/technetwork/topics/security/cpujan2015-1972971.html
    148. +
    149. CONFIRM - http://www.oracle.com/technetwork/topics/security/cpujan2016-2367955.html
    150. CONFIRM - http://www.oracle.com/technetwork/topics/security/cpujul2014-1972956.html
    151. CONFIRM - http://www.oracle.com/technetwork/topics/security/cpuoct2014-1972960.html
    152. +
    153. CONFIRM - http://www.oracle.com/technetwork/topics/security/cpuoct2015-2367953.html
    154. CONFIRM - http://www.vmware.com/security/advisories/VMSA-2014-0007.html
    155. CONFIRM - http://www.vmware.com/security/advisories/VMSA-2014-0012.html
    156. CONFIRM - https://bugzilla.redhat.com/show_bug.cgi?id=1062337
    157. FULLDISC - 20141205 NEW: VMSA-2014-0012 - VMware vSphere product updates address security vulnerabilities
    158. -
    159. FULLDISC - 20150402 NEW : VMSA-2015-0003 VMware product updates address critical information disclosure issue in JRE
    160. +
    161. HP - HPSBGN03329
    162. JVN - JVN#14876762
    163. JVNDB - JVNDB-2014-000017
    164. MANDRIVA - MDVSA-2015:084
    165. MISC - http://blog.spiderlabs.com/2014/02/cve-2014-0050-exploit-with-boundaries-loops-without-boundaries.html
    166. MISC - http://packetstormsecurity.com/files/127215/VMware-Security-Advisory-2014-0007.html
    167. -
    168. MISC - http://packetstormsecurity.com/files/131271/VMware-Security-Advisory-2015-0003.html
    169. MLIST - [commons-dev] 20140206 [SECURITY] CVE-2014-0050 Apache Commons FileUpload and Apache Tomcat DoS
    170. REDHAT - RHSA-2014:0400
    171. -

      Vulnerable Software & Versions: (show all)

      -

      Vulnerable Software & Versions: (show all)

      -

      Vulnerable Software & Versions: (show all)

      -

      Vulnerable Software & Versions: (show all)

      -

      Vulnerable Software & Versions: (show all)

      -

      Vulnerable Software & Versions: (show all)

      -

      Vulnerable Software & Versions: (show all)

      @@ -74,7 +74,7 @@ - +
    172. diff --git a/index.html b/index.html index 0b21233db..a6d589547 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,13 @@ - + dependency-check – About @@ -59,9 +59,9 @@
    173. About
    174. -
    175. | Last Published: 2016-09-06
    176. +
    177. | Last Published: 2016-11-05
    178. - Version: 1.4.3 + Version: 1.4.4
    179. @@ -74,7 +74,7 @@
      - +
    180. @@ -236,7 +243,7 @@
    181. Jenkins Plugin
    182. -
    183. Maven Plugin
    184. +
    185. Maven Plugin - Maven 3.1 or newer required
    186. SBT Plugin
    187. diff --git a/integration.html b/integration.html index 811d2f152..b23842e20 100644 --- a/integration.html +++ b/integration.html @@ -1,13 +1,13 @@ - + dependency-check – CI Management @@ -59,9 +59,9 @@
    188. CI Management
    189. -
    190. | Last Published: 2016-09-06
    191. +
    192. | Last Published: 2016-11-05
    193. - Version: 1.4.3 + Version: 1.4.4
    194. @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@ @@ -74,7 +74,7 @@ - +
    195. diff --git a/source-repository.html b/source-repository.html index d5f0acedb..410d3b9d5 100644 --- a/source-repository.html +++ b/source-repository.html @@ -1,13 +1,13 @@ - + dependency-check – Source Code Management @@ -59,9 +59,9 @@
    196. Source Code Management
    197. -
    198. | Last Published: 2016-09-06
    199. +
    200. | Last Published: 2016-11-05
    201. - Version: 1.4.3 + Version: 1.4.4
    202. @@ -74,14 +74,14 @@
      @@ -74,14 +74,14 @@ @@ -74,14 +74,14 @@ -

      Dependency-Check 1.4.3 Reference

      +

      Dependency-Check 1.4.4 Reference

      diff --git a/xref/allclasses-frame.html b/xref/allclasses-frame.html index 7d0ad7978..60b243866 100644 --- a/xref/allclasses-frame.html +++ b/xref/allclasses-frame.html @@ -37,6 +37,9 @@
    203. AnalysisPhase +
    204. +
    205. + AnalysisTask
    206. Analyzer @@ -325,12 +328,6 @@
    207. MavenEngine -
    208. -
    209. - MavenLoggerAdapter -
    210. -
    211. - MavenLoggerFactory
    212. Model diff --git a/xref/index.html b/xref/index.html index b705ec2b8..a203f5628 100644 --- a/xref/index.html +++ b/xref/index.html @@ -4,7 +4,7 @@ - Dependency-Check 1.4.3 Reference + Dependency-Check 1.4.4 Reference diff --git a/xref/org/owasp/dependencycheck/AnalysisTask.html b/xref/org/owasp/dependencycheck/AnalysisTask.html new file mode 100644 index 000000000..266b3f14a --- /dev/null +++ b/xref/org/owasp/dependencycheck/AnalysisTask.html @@ -0,0 +1,132 @@ + + + +AnalysisTask xref + + + +
      +1   /*
      +2    * This file is part of dependency-check-core.
      +3    *
      +4    * Licensed under the Apache License, Version 2.0 (the "License");
      +5    * you may not use this file except in compliance with the License.
      +6    * You may obtain a copy of the License at
      +7    *
      +8    *     http://www.apache.org/licenses/LICENSE-2.0
      +9    *
      +10   * Unless required by applicable law or agreed to in writing, software
      +11   * distributed under the License is distributed on an "AS IS" BASIS,
      +12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      +13   * See the License for the specific language governing permissions and
      +14   * limitations under the License.
      +15   *
      +16   * Copyright (c) 2016 Stefan Neuhaus. All Rights Reserved.
      +17   */
      +18  package org.owasp.dependencycheck;
      +19  
      +20  import org.owasp.dependencycheck.analyzer.Analyzer;
      +21  import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
      +22  import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
      +23  import org.owasp.dependencycheck.dependency.Dependency;
      +24  import org.owasp.dependencycheck.utils.Settings;
      +25  import org.slf4j.Logger;
      +26  import org.slf4j.LoggerFactory;
      +27  
      +28  import java.util.List;
      +29  import java.util.concurrent.Callable;
      +30  
      +31  /**
      +32   * Task to support parallelism of dependency-check analysis.
      +33   * Analyses a single {@link Dependency} by a specific {@link Analyzer}.
      +34   *
      +35   * @author Stefan Neuhaus
      +36   */
      +37  class AnalysisTask implements Callable<Void> {
      +38  
      +39      /**
      +40       * Instance of the logger.
      +41       */
      +42      private static final Logger LOGGER = LoggerFactory.getLogger(AnalysisTask.class);
      +43  
      +44      /**
      +45       * A reference to the analyzer.
      +46       */
      +47      private final Analyzer analyzer;
      +48      /**
      +49       * The dependency to analyze.
      +50       */
      +51      private final Dependency dependency;
      +52      /**
      +53       * A reference to the dependency-check engine.
      +54       */
      +55      private final Engine engine;
      +56      /**
      +57       * The list of exceptions that may occur during analysis.
      +58       */
      +59      private final List<Throwable> exceptions;
      +60  
      +61      /**
      +62       * Creates a new analysis task.
      +63       *
      +64       * @param analyzer a reference of the analyzer to execute
      +65       * @param dependency the dependency to analyze
      +66       * @param engine the dependency-check engine
      +67       * @param exceptions exceptions that occur during analysis will be added to
      +68       * this collection of exceptions
      +69       */
      +70      AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List<Throwable> exceptions) {
      +71          this.analyzer = analyzer;
      +72          this.dependency = dependency;
      +73          this.engine = engine;
      +74          this.exceptions = exceptions;
      +75      }
      +76  
      +77      /**
      +78       * Executes the analysis task.
      +79       *
      +80       * @return null
      +81       * @throws Exception thrown if unable to execute the analysis task
      +82       */
      +83      @Override
      +84      public Void call() {
      +85          Settings.initialize();
      +86  
      +87          if (shouldAnalyze()) {
      +88              LOGGER.debug("Begin Analysis of '{}' ({})", dependency.getActualFilePath(), analyzer.getName());
      +89              try {
      +90                  analyzer.analyze(dependency, engine);
      +91              } catch (AnalysisException ex) {
      +92                  LOGGER.warn("An error occurred while analyzing '{}' ({}).", dependency.getActualFilePath(), analyzer.getName());
      +93                  LOGGER.debug("", ex);
      +94                  exceptions.add(ex);
      +95              } catch (Throwable ex) {
      +96                  LOGGER.warn("An unexpected error occurred during analysis of '{}' ({}): {}",
      +97                          dependency.getActualFilePath(), analyzer.getName(), ex.getMessage());
      +98                  LOGGER.debug("", ex);
      +99                  exceptions.add(ex);
      +100             }
      +101         }
      +102 
      +103         return null;
      +104     }
      +105 
      +106     /**
      +107      * Determines if the analyzer can analyze the given dependency.
      +108      *
      +109      * @return whether or not the analyzer can analyze the dependency
      +110      */
      +111     boolean shouldAnalyze() {
      +112         if (analyzer instanceof FileTypeAnalyzer) {
      +113             final FileTypeAnalyzer fileTypeAnalyzer = (FileTypeAnalyzer) analyzer;
      +114             return fileTypeAnalyzer.accept(dependency.getActualFile());
      +115         }
      +116 
      +117         return true;
      +118     }
      +119 }
      +
      +
      + + + diff --git a/xref/org/owasp/dependencycheck/App.html b/xref/org/owasp/dependencycheck/App.html index 03aba4333..e70c6040e 100644 --- a/xref/org/owasp/dependencycheck/App.html +++ b/xref/org/owasp/dependencycheck/App.html @@ -27,508 +27,511 @@ 19 20 import ch.qos.logback.classic.LoggerContext; 21 import ch.qos.logback.classic.encoder.PatternLayoutEncoder; -22 import java.io.File; -23 import java.io.FileNotFoundException; -24 import java.io.IOException; -25 import java.util.ArrayList; -26 import java.util.HashSet; -27 import java.util.List; -28 import java.util.Set; -29 import org.apache.commons.cli.ParseException; -30 import org.owasp.dependencycheck.data.nvdcve.CveDB; -31 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -32 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; -33 import org.owasp.dependencycheck.dependency.Dependency; -34 import org.apache.tools.ant.DirectoryScanner; -35 import org.owasp.dependencycheck.reporting.ReportGenerator; -36 import org.owasp.dependencycheck.utils.Settings; -37 import org.slf4j.Logger; -38 import org.slf4j.LoggerFactory; -39 import ch.qos.logback.core.FileAppender; -40 import org.owasp.dependencycheck.data.update.exception.UpdateException; -41 import org.owasp.dependencycheck.exception.ExceptionCollection; -42 import org.owasp.dependencycheck.exception.ReportException; -43 import org.owasp.dependencycheck.utils.InvalidSettingException; -44 import org.slf4j.impl.StaticLoggerBinder; -45 -46 /** -47 * The command line interface for the DependencyCheck application. -48 * -49 * @author Jeremy Long -50 */ -51 public class App { -52 -53 /** -54 * The logger. -55 */ -56 private static final Logger LOGGER = LoggerFactory.getLogger(App.class); -57 -58 /** -59 * The main method for the application. -60 * -61 * @param args the command line arguments -62 */ -63 public static void main(String[] args) { -64 int exitCode = 0; -65 try { -66 Settings.initialize(); -67 final App app = new App(); -68 exitCode = app.run(args); -69 LOGGER.debug("Exit code: " + exitCode); -70 } finally { -71 Settings.cleanup(true); -72 } -73 System.exit(exitCode); -74 } -75 -76 /** -77 * Main CLI entry-point into the application. -78 * -79 * @param args the command line arguments -80 * @return the exit code to return -81 */ -82 public int run(String[] args) { -83 int exitCode = 0; -84 final CliParser cli = new CliParser(); -85 -86 try { -87 cli.parse(args); -88 } catch (FileNotFoundException ex) { -89 System.err.println(ex.getMessage()); -90 cli.printHelp(); -91 return -1; -92 } catch (ParseException ex) { -93 System.err.println(ex.getMessage()); -94 cli.printHelp(); -95 return -2; -96 } -97 -98 if (cli.getVerboseLog() != null) { -99 prepareLogger(cli.getVerboseLog()); -100 } -101 -102 if (cli.isPurge()) { -103 if (cli.getConnectionString() != null) { -104 LOGGER.error("Unable to purge the database when using a non-default connection string"); -105 exitCode = -3; -106 } else { -107 try { -108 populateSettings(cli); -109 } catch (InvalidSettingException ex) { -110 LOGGER.error(ex.getMessage()); -111 LOGGER.debug("Error loading properties file", ex); -112 exitCode = -4; -113 } -114 File db; -115 try { -116 db = new File(Settings.getDataDirectory(), "dc.h2.db"); -117 if (db.exists()) { -118 if (db.delete()) { -119 LOGGER.info("Database file purged; local copy of the NVD has been removed"); -120 } else { -121 LOGGER.error("Unable to delete '{}'; please delete the file manually", db.getAbsolutePath()); -122 exitCode = -5; -123 } -124 } else { -125 LOGGER.error("Unable to purge database; the database file does not exists: {}", db.getAbsolutePath()); -126 exitCode = -6; -127 } -128 } catch (IOException ex) { -129 LOGGER.error("Unable to delete the database"); -130 exitCode = -7; -131 } -132 } -133 } else if (cli.isGetVersion()) { -134 cli.printVersionInfo(); -135 } else if (cli.isUpdateOnly()) { -136 try { -137 populateSettings(cli); -138 } catch (InvalidSettingException ex) { -139 LOGGER.error(ex.getMessage()); -140 LOGGER.debug("Error loading properties file", ex); -141 exitCode = -4; -142 } -143 try { -144 runUpdateOnly(); -145 } catch (UpdateException ex) { -146 LOGGER.error(ex.getMessage()); -147 exitCode = -8; -148 } catch (DatabaseException ex) { -149 LOGGER.error(ex.getMessage()); -150 exitCode = -9; -151 } -152 } else if (cli.isRunScan()) { -153 try { -154 populateSettings(cli); -155 } catch (InvalidSettingException ex) { -156 LOGGER.error(ex.getMessage()); -157 LOGGER.debug("Error loading properties file", ex); -158 exitCode = -4; -159 } -160 try { -161 final String[] scanFiles = cli.getScanFiles(); -162 if (scanFiles != null) { -163 runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles, -164 cli.getExcludeList(), cli.getSymLinkDepth()); -165 } else { -166 LOGGER.error("No scan files configured"); -167 } -168 } catch (InvalidScanPathException ex) { -169 LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths"); -170 exitCode = -10; -171 } catch (DatabaseException ex) { -172 LOGGER.error(ex.getMessage()); -173 exitCode = -11; -174 } catch (ReportException ex) { -175 LOGGER.error(ex.getMessage()); -176 exitCode = -12; -177 } catch (ExceptionCollection ex) { -178 if (ex.isFatal()) { -179 exitCode = -13; -180 LOGGER.error("One or more fatal errors occured"); -181 } else { -182 exitCode = -14; -183 } -184 for (Throwable e : ex.getExceptions()) { -185 LOGGER.error(e.getMessage()); -186 } -187 } -188 } else { -189 cli.printHelp(); -190 } -191 return exitCode; -192 } -193 -194 /** -195 * Scans the specified directories and writes the dependency reports to the -196 * reportDirectory. -197 * -198 * @param reportDirectory the path to the directory where the reports will -199 * be written -200 * @param outputFormat the output format of the report -201 * @param applicationName the application name for the report -202 * @param files the files/directories to scan -203 * @param excludes the patterns for files/directories to exclude -204 * @param symLinkDepth the depth that symbolic links will be followed -205 * -206 * @throws InvalidScanPathException thrown if the path to scan starts with -207 * "//" -208 * @throws ReportException thrown when the report cannot be generated -209 * @throws DatabaseException thrown when there is an error connecting to the -210 * database -211 * @throws ExceptionCollection thrown when an exception occurs during -212 * analysis; there may be multiple exceptions contained within the -213 * collection. -214 */ -215 private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files, -216 String[] excludes, int symLinkDepth) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException { -217 Engine engine = null; -218 try { -219 engine = new Engine(); -220 final List<String> antStylePaths = new ArrayList<String>(); -221 for (String file : files) { -222 final String antPath = ensureCanonicalPath(file); -223 antStylePaths.add(antPath); -224 } -225 -226 final Set<File> paths = new HashSet<File>(); -227 for (String file : antStylePaths) { -228 LOGGER.debug("Scanning {}", file); -229 final DirectoryScanner scanner = new DirectoryScanner(); -230 String include = file.replace('\\', '/'); -231 File baseDir; -232 -233 if (include.startsWith("//")) { -234 throw new InvalidScanPathException("Unable to scan paths specified by //"); -235 } else { -236 final int pos = getLastFileSeparator(include); -237 final String tmpBase = include.substring(0, pos); -238 final String tmpInclude = include.substring(pos + 1); -239 if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0 -240 || (new File(include)).isFile()) { -241 baseDir = new File(tmpBase); -242 include = tmpInclude; -243 } else { -244 baseDir = new File(tmpBase, tmpInclude); -245 include = "**/*"; -246 } -247 } -248 scanner.setBasedir(baseDir); -249 final String[] includes = {include}; -250 scanner.setIncludes(includes); -251 scanner.setMaxLevelsOfSymlinks(symLinkDepth); -252 if (symLinkDepth <= 0) { -253 scanner.setFollowSymlinks(false); -254 } -255 if (excludes != null && excludes.length > 0) { -256 scanner.addExcludes(excludes); -257 } -258 scanner.scan(); -259 if (scanner.getIncludedFilesCount() > 0) { -260 for (String s : scanner.getIncludedFiles()) { -261 final File f = new File(baseDir, s); -262 LOGGER.debug("Found file {}", f.toString()); -263 paths.add(f); -264 } -265 } -266 } -267 engine.scan(paths); -268 -269 ExceptionCollection exCol = null; -270 try { -271 engine.analyzeDependencies(); -272 } catch (ExceptionCollection ex) { -273 if (ex.isFatal()) { -274 throw ex; -275 } -276 exCol = ex; -277 } -278 final List<Dependency> dependencies = engine.getDependencies(); -279 DatabaseProperties prop = null; -280 CveDB cve = null; -281 try { -282 cve = new CveDB(); -283 cve.open(); -284 prop = cve.getDatabaseProperties(); -285 } finally { -286 if (cve != null) { -287 cve.close(); -288 } -289 } -290 final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop); -291 try { -292 report.generateReports(reportDirectory, outputFormat); -293 } catch (ReportException ex) { -294 if (exCol != null) { -295 exCol.addException(ex); -296 throw exCol; -297 } else { -298 throw ex; -299 } -300 } -301 if (exCol != null && exCol.getExceptions().size() > 0) { -302 throw exCol; -303 } -304 } finally { -305 if (engine != null) { -306 engine.cleanup(); -307 } -308 } -309 -310 } -311 -312 /** -313 * Only executes the update phase of dependency-check. -314 * -315 * @throws UpdateException thrown if there is an error updating -316 * @throws DatabaseException thrown if a fatal error occurred and a -317 * connection to the database could not be established -318 */ -319 private void runUpdateOnly() throws UpdateException, DatabaseException { -320 Engine engine = null; -321 try { -322 engine = new Engine(); -323 engine.doUpdates(); -324 } finally { -325 if (engine != null) { -326 engine.cleanup(); -327 } -328 } -329 } -330 -331 /** -332 * Updates the global Settings. -333 * -334 * @param cli a reference to the CLI Parser that contains the command line -335 * arguments used to set the corresponding settings in the core engine. -336 * -337 * @throws InvalidSettingException thrown when a user defined properties -338 * file is unable to be loaded. -339 */ -340 private void populateSettings(CliParser cli) throws InvalidSettingException { -341 final boolean autoUpdate = cli.isAutoUpdate(); -342 final String connectionTimeout = cli.getConnectionTimeout(); -343 final String proxyServer = cli.getProxyServer(); -344 final String proxyPort = cli.getProxyPort(); -345 final String proxyUser = cli.getProxyUsername(); -346 final String proxyPass = cli.getProxyPassword(); -347 final String dataDirectory = cli.getDataDirectory(); -348 final File propertiesFile = cli.getPropertiesFile(); -349 final String suppressionFile = cli.getSuppressionFile(); -350 final String nexusUrl = cli.getNexusUrl(); -351 final String databaseDriverName = cli.getDatabaseDriverName(); -352 final String databaseDriverPath = cli.getDatabaseDriverPath(); -353 final String connectionString = cli.getConnectionString(); -354 final String databaseUser = cli.getDatabaseUser(); -355 final String databasePassword = cli.getDatabasePassword(); -356 final String additionalZipExtensions = cli.getAdditionalZipExtensions(); -357 final String pathToMono = cli.getPathToMono(); -358 final String cveMod12 = cli.getModifiedCve12Url(); -359 final String cveMod20 = cli.getModifiedCve20Url(); -360 final String cveBase12 = cli.getBaseCve12Url(); -361 final String cveBase20 = cli.getBaseCve20Url(); -362 final Integer cveValidForHours = cli.getCveValidForHours(); -363 final boolean experimentalEnabled = cli.isExperimentalEnabled(); -364 -365 if (propertiesFile != null) { -366 try { -367 Settings.mergeProperties(propertiesFile); -368 } catch (FileNotFoundException ex) { -369 throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex); -370 } catch (IOException ex) { -371 throw new InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex); -372 } -373 } -374 // We have to wait until we've merged the properties before attempting to set whether we use -375 // the proxy for Nexus since it could be disabled in the properties, but not explicitly stated -376 // on the command line -377 final boolean nexusUsesProxy = cli.isNexusUsesProxy(); -378 if (dataDirectory != null) { -379 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory); -380 } else if (System.getProperty("basedir") != null) { -381 final File dataDir = new File(System.getProperty("basedir"), "data"); -382 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); -383 } else { -384 final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath()); -385 final File base = jarPath.getParentFile(); -386 final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY); -387 final File dataDir = new File(base, sub); -388 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); -389 } -390 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); -391 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer); -392 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort); -393 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser); -394 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPass); -395 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); -396 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); -397 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); -398 -399 //File Type Analyzer Settings -400 Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled); -401 Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled()); -402 Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled()); -403 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled()); -404 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !cli.isPythonPackageDisabled()); -405 Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, !cli.isAutoconfDisabled()); -406 Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, !cli.isCmakeDisabled()); -407 Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !cli.isNuspecDisabled()); -408 Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !cli.isAssemblyDisabled()); -409 Settings.setBoolean(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, !cli.isBundleAuditDisabled()); -410 Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, !cli.isOpenSSLDisabled()); -411 Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, !cli.isComposerDisabled()); -412 Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, !cli.isNodeJsDisabled()); -413 Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, !cli.isRubyGemspecDisabled()); -414 Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !cli.isCentralDisabled()); -415 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !cli.isNexusDisabled()); -416 -417 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, cli.getPathToBundleAudit()); -418 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); -419 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); -420 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); -421 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); -422 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); -423 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); -424 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); -425 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions); -426 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); -427 if (cveBase12 != null && !cveBase12.isEmpty()) { -428 Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveBase12); -429 Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveBase20); -430 Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveMod12); -431 Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveMod20); -432 } -433 } -434 -435 /** -436 * Creates a file appender and adds it to logback. -437 * -438 * @param verboseLog the path to the verbose log file -439 */ -440 private void prepareLogger(String verboseLog) { -441 final StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton(); -442 final LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory(); -443 -444 final PatternLayoutEncoder encoder = new PatternLayoutEncoder(); -445 encoder.setPattern("%d %C:%L%n%-5level - %msg%n"); -446 encoder.setContext(context); -447 encoder.start(); -448 final FileAppender fa = new FileAppender(); -449 fa.setAppend(true); -450 fa.setEncoder(encoder); -451 fa.setContext(context); -452 fa.setFile(verboseLog); -453 final File f = new File(verboseLog); -454 String name = f.getName(); -455 final int i = name.lastIndexOf('.'); -456 if (i > 1) { -457 name = name.substring(0, i); -458 } -459 fa.setName(name); -460 fa.start(); -461 final ch.qos.logback.classic.Logger rootLogger = context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); -462 rootLogger.addAppender(fa); -463 } -464 -465 /** -466 * Takes a path and resolves it to be a canonical &amp; absolute path. The -467 * caveats are that this method will take an Ant style file selector path -468 * (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at -469 * least to the left of the first * or ?). -470 * -471 * @param path the path to canonicalize -472 * @return the canonical path -473 */ -474 protected String ensureCanonicalPath(String path) { -475 String basePath; -476 String wildCards = null; -477 final String file = path.replace('\\', '/'); -478 if (file.contains("*") || file.contains("?")) { -479 -480 int pos = getLastFileSeparator(file); -481 if (pos < 0) { -482 return file; -483 } -484 pos += 1; -485 basePath = file.substring(0, pos); -486 wildCards = file.substring(pos); -487 } else { -488 basePath = file; -489 } -490 -491 File f = new File(basePath); -492 try { -493 f = f.getCanonicalFile(); -494 if (wildCards != null) { -495 f = new File(f, wildCards); -496 } -497 } catch (IOException ex) { -498 LOGGER.warn("Invalid path '{}' was provided.", path); -499 LOGGER.debug("Invalid path provided", ex); -500 } -501 return f.getAbsolutePath().replace('\\', '/'); -502 } -503 -504 /** -505 * Returns the position of the last file separator. -506 * -507 * @param file a file path -508 * @return the position of the last file separator -509 */ -510 private int getLastFileSeparator(String file) { -511 if (file.contains("*") || file.contains("?")) { -512 int p1 = file.indexOf('*'); -513 int p2 = file.indexOf('?'); -514 p1 = p1 > 0 ? p1 : file.length(); -515 p2 = p2 > 0 ? p2 : file.length(); -516 int pos = p1 < p2 ? p1 : p2; -517 pos = file.lastIndexOf('/', pos); -518 return pos; -519 } else { -520 return file.lastIndexOf('/'); -521 } -522 } -523 } +22 import ch.qos.logback.classic.spi.ILoggingEvent; +23 import java.io.File; +24 import java.io.FileNotFoundException; +25 import java.io.IOException; +26 import java.util.ArrayList; +27 import java.util.HashSet; +28 import java.util.List; +29 import java.util.Set; +30 import org.apache.commons.cli.ParseException; +31 import org.owasp.dependencycheck.data.nvdcve.CveDB; +32 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +33 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; +34 import org.owasp.dependencycheck.dependency.Dependency; +35 import org.apache.tools.ant.DirectoryScanner; +36 import org.owasp.dependencycheck.reporting.ReportGenerator; +37 import org.owasp.dependencycheck.utils.Settings; +38 import org.slf4j.Logger; +39 import org.slf4j.LoggerFactory; +40 import ch.qos.logback.core.FileAppender; +41 import org.owasp.dependencycheck.data.update.exception.UpdateException; +42 import org.owasp.dependencycheck.exception.ExceptionCollection; +43 import org.owasp.dependencycheck.exception.ReportException; +44 import org.owasp.dependencycheck.utils.InvalidSettingException; +45 import org.slf4j.impl.StaticLoggerBinder; +46 +47 /** +48 * The command line interface for the DependencyCheck application. +49 * +50 * @author Jeremy Long +51 */ +52 public class App { +53 +54 /** +55 * The logger. +56 */ +57 private static final Logger LOGGER = LoggerFactory.getLogger(App.class); +58 +59 /** +60 * The main method for the application. +61 * +62 * @param args the command line arguments +63 */ +64 public static void main(String[] args) { +65 int exitCode = 0; +66 try { +67 Settings.initialize(); +68 final App app = new App(); +69 exitCode = app.run(args); +70 LOGGER.debug("Exit code: " + exitCode); +71 } finally { +72 Settings.cleanup(true); +73 } +74 System.exit(exitCode); +75 } +76 +77 /** +78 * Main CLI entry-point into the application. +79 * +80 * @param args the command line arguments +81 * @return the exit code to return +82 */ +83 public int run(String[] args) { +84 int exitCode = 0; +85 final CliParser cli = new CliParser(); +86 +87 try { +88 cli.parse(args); +89 } catch (FileNotFoundException ex) { +90 System.err.println(ex.getMessage()); +91 cli.printHelp(); +92 return -1; +93 } catch (ParseException ex) { +94 System.err.println(ex.getMessage()); +95 cli.printHelp(); +96 return -2; +97 } +98 +99 if (cli.getVerboseLog() != null) { +100 prepareLogger(cli.getVerboseLog()); +101 } +102 +103 if (cli.isPurge()) { +104 if (cli.getConnectionString() != null) { +105 LOGGER.error("Unable to purge the database when using a non-default connection string"); +106 exitCode = -3; +107 } else { +108 try { +109 populateSettings(cli); +110 } catch (InvalidSettingException ex) { +111 LOGGER.error(ex.getMessage()); +112 LOGGER.debug("Error loading properties file", ex); +113 exitCode = -4; +114 } +115 File db; +116 try { +117 db = new File(Settings.getDataDirectory(), "dc.h2.db"); +118 if (db.exists()) { +119 if (db.delete()) { +120 LOGGER.info("Database file purged; local copy of the NVD has been removed"); +121 } else { +122 LOGGER.error("Unable to delete '{}'; please delete the file manually", db.getAbsolutePath()); +123 exitCode = -5; +124 } +125 } else { +126 LOGGER.error("Unable to purge database; the database file does not exists: {}", db.getAbsolutePath()); +127 exitCode = -6; +128 } +129 } catch (IOException ex) { +130 LOGGER.error("Unable to delete the database"); +131 exitCode = -7; +132 } +133 } +134 } else if (cli.isGetVersion()) { +135 cli.printVersionInfo(); +136 } else if (cli.isUpdateOnly()) { +137 try { +138 populateSettings(cli); +139 } catch (InvalidSettingException ex) { +140 LOGGER.error(ex.getMessage()); +141 LOGGER.debug("Error loading properties file", ex); +142 exitCode = -4; +143 } +144 try { +145 runUpdateOnly(); +146 } catch (UpdateException ex) { +147 LOGGER.error(ex.getMessage()); +148 exitCode = -8; +149 } catch (DatabaseException ex) { +150 LOGGER.error(ex.getMessage()); +151 exitCode = -9; +152 } +153 } else if (cli.isRunScan()) { +154 try { +155 populateSettings(cli); +156 } catch (InvalidSettingException ex) { +157 LOGGER.error(ex.getMessage()); +158 LOGGER.debug("Error loading properties file", ex); +159 exitCode = -4; +160 } +161 try { +162 final String[] scanFiles = cli.getScanFiles(); +163 if (scanFiles != null) { +164 runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles, +165 cli.getExcludeList(), cli.getSymLinkDepth()); +166 } else { +167 LOGGER.error("No scan files configured"); +168 } +169 } catch (InvalidScanPathException ex) { +170 LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths"); +171 exitCode = -10; +172 } catch (DatabaseException ex) { +173 LOGGER.error(ex.getMessage()); +174 exitCode = -11; +175 } catch (ReportException ex) { +176 LOGGER.error(ex.getMessage()); +177 exitCode = -12; +178 } catch (ExceptionCollection ex) { +179 if (ex.isFatal()) { +180 exitCode = -13; +181 LOGGER.error("One or more fatal errors occurred"); +182 } else { +183 exitCode = -14; +184 } +185 for (Throwable e : ex.getExceptions()) { +186 LOGGER.error(e.getMessage()); +187 } +188 } +189 } else { +190 cli.printHelp(); +191 } +192 return exitCode; +193 } +194 +195 /** +196 * Scans the specified directories and writes the dependency reports to the +197 * reportDirectory. +198 * +199 * @param reportDirectory the path to the directory where the reports will +200 * be written +201 * @param outputFormat the output format of the report +202 * @param applicationName the application name for the report +203 * @param files the files/directories to scan +204 * @param excludes the patterns for files/directories to exclude +205 * @param symLinkDepth the depth that symbolic links will be followed +206 * +207 * @throws InvalidScanPathException thrown if the path to scan starts with +208 * "//" +209 * @throws ReportException thrown when the report cannot be generated +210 * @throws DatabaseException thrown when there is an error connecting to the +211 * database +212 * @throws ExceptionCollection thrown when an exception occurs during +213 * analysis; there may be multiple exceptions contained within the +214 * collection. +215 */ +216 private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files, +217 String[] excludes, int symLinkDepth) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException { +218 Engine engine = null; +219 try { +220 engine = new Engine(); +221 final List<String> antStylePaths = new ArrayList<String>(); +222 for (String file : files) { +223 final String antPath = ensureCanonicalPath(file); +224 antStylePaths.add(antPath); +225 } +226 +227 final Set<File> paths = new HashSet<File>(); +228 for (String file : antStylePaths) { +229 LOGGER.debug("Scanning {}", file); +230 final DirectoryScanner scanner = new DirectoryScanner(); +231 String include = file.replace('\\', '/'); +232 File baseDir; +233 +234 if (include.startsWith("//")) { +235 throw new InvalidScanPathException("Unable to scan paths specified by //"); +236 } else { +237 final int pos = getLastFileSeparator(include); +238 final String tmpBase = include.substring(0, pos); +239 final String tmpInclude = include.substring(pos + 1); +240 if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0 +241 || (new File(include)).isFile()) { +242 baseDir = new File(tmpBase); +243 include = tmpInclude; +244 } else { +245 baseDir = new File(tmpBase, tmpInclude); +246 include = "**/*"; +247 } +248 } +249 scanner.setBasedir(baseDir); +250 final String[] includes = {include}; +251 scanner.setIncludes(includes); +252 scanner.setMaxLevelsOfSymlinks(symLinkDepth); +253 if (symLinkDepth <= 0) { +254 scanner.setFollowSymlinks(false); +255 } +256 if (excludes != null && excludes.length > 0) { +257 scanner.addExcludes(excludes); +258 } +259 scanner.scan(); +260 if (scanner.getIncludedFilesCount() > 0) { +261 for (String s : scanner.getIncludedFiles()) { +262 final File f = new File(baseDir, s); +263 LOGGER.debug("Found file {}", f.toString()); +264 paths.add(f); +265 } +266 } +267 } +268 engine.scan(paths); +269 +270 ExceptionCollection exCol = null; +271 try { +272 engine.analyzeDependencies(); +273 } catch (ExceptionCollection ex) { +274 if (ex.isFatal()) { +275 throw ex; +276 } +277 exCol = ex; +278 } +279 final List<Dependency> dependencies = engine.getDependencies(); +280 DatabaseProperties prop = null; +281 CveDB cve = null; +282 try { +283 cve = new CveDB(); +284 cve.open(); +285 prop = cve.getDatabaseProperties(); +286 } finally { +287 if (cve != null) { +288 cve.close(); +289 } +290 } +291 final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop); +292 try { +293 report.generateReports(reportDirectory, outputFormat); +294 } catch (ReportException ex) { +295 if (exCol != null) { +296 exCol.addException(ex); +297 throw exCol; +298 } else { +299 throw ex; +300 } +301 } +302 if (exCol != null && exCol.getExceptions().size() > 0) { +303 throw exCol; +304 } +305 } finally { +306 if (engine != null) { +307 engine.cleanup(); +308 } +309 } +310 +311 } +312 +313 /** +314 * Only executes the update phase of dependency-check. +315 * +316 * @throws UpdateException thrown if there is an error updating +317 * @throws DatabaseException thrown if a fatal error occurred and a +318 * connection to the database could not be established +319 */ +320 private void runUpdateOnly() throws UpdateException, DatabaseException { +321 Engine engine = null; +322 try { +323 engine = new Engine(); +324 engine.doUpdates(); +325 } finally { +326 if (engine != null) { +327 engine.cleanup(); +328 } +329 } +330 } +331 +332 /** +333 * Updates the global Settings. +334 * +335 * @param cli a reference to the CLI Parser that contains the command line +336 * arguments used to set the corresponding settings in the core engine. +337 * +338 * @throws InvalidSettingException thrown when a user defined properties +339 * file is unable to be loaded. +340 */ +341 private void populateSettings(CliParser cli) throws InvalidSettingException { +342 final boolean autoUpdate = cli.isAutoUpdate(); +343 final String connectionTimeout = cli.getConnectionTimeout(); +344 final String proxyServer = cli.getProxyServer(); +345 final String proxyPort = cli.getProxyPort(); +346 final String proxyUser = cli.getProxyUsername(); +347 final String proxyPass = cli.getProxyPassword(); +348 final String dataDirectory = cli.getDataDirectory(); +349 final File propertiesFile = cli.getPropertiesFile(); +350 final String suppressionFile = cli.getSuppressionFile(); +351 final String hintsFile = cli.getHintsFile(); +352 final String nexusUrl = cli.getNexusUrl(); +353 final String databaseDriverName = cli.getDatabaseDriverName(); +354 final String databaseDriverPath = cli.getDatabaseDriverPath(); +355 final String connectionString = cli.getConnectionString(); +356 final String databaseUser = cli.getDatabaseUser(); +357 final String databasePassword = cli.getDatabasePassword(); +358 final String additionalZipExtensions = cli.getAdditionalZipExtensions(); +359 final String pathToMono = cli.getPathToMono(); +360 final String cveMod12 = cli.getModifiedCve12Url(); +361 final String cveMod20 = cli.getModifiedCve20Url(); +362 final String cveBase12 = cli.getBaseCve12Url(); +363 final String cveBase20 = cli.getBaseCve20Url(); +364 final Integer cveValidForHours = cli.getCveValidForHours(); +365 final boolean experimentalEnabled = cli.isExperimentalEnabled(); +366 +367 if (propertiesFile != null) { +368 try { +369 Settings.mergeProperties(propertiesFile); +370 } catch (FileNotFoundException ex) { +371 throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex); +372 } catch (IOException ex) { +373 throw new InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex); +374 } +375 } +376 // We have to wait until we've merged the properties before attempting to set whether we use +377 // the proxy for Nexus since it could be disabled in the properties, but not explicitly stated +378 // on the command line +379 final boolean nexusUsesProxy = cli.isNexusUsesProxy(); +380 if (dataDirectory != null) { +381 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory); +382 } else if (System.getProperty("basedir") != null) { +383 final File dataDir = new File(System.getProperty("basedir"), "data"); +384 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); +385 } else { +386 final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath()); +387 final File base = jarPath.getParentFile(); +388 final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY); +389 final File dataDir = new File(base, sub); +390 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath()); +391 } +392 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); +393 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer); +394 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort); +395 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser); +396 Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPass); +397 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); +398 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); +399 Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile); +400 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); +401 +402 //File Type Analyzer Settings +403 Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled); +404 Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled()); +405 Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled()); +406 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled()); +407 Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !cli.isPythonPackageDisabled()); +408 Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, !cli.isAutoconfDisabled()); +409 Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, !cli.isCmakeDisabled()); +410 Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !cli.isNuspecDisabled()); +411 Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !cli.isAssemblyDisabled()); +412 Settings.setBoolean(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, !cli.isBundleAuditDisabled()); +413 Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, !cli.isOpenSSLDisabled()); +414 Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, !cli.isComposerDisabled()); +415 Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, !cli.isNodeJsDisabled()); +416 Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, !cli.isRubyGemspecDisabled()); +417 Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !cli.isCentralDisabled()); +418 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !cli.isNexusDisabled()); +419 +420 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, cli.getPathToBundleAudit()); +421 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); +422 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); +423 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); +424 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); +425 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); +426 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); +427 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); +428 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions); +429 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); +430 if (cveBase12 != null && !cveBase12.isEmpty()) { +431 Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveBase12); +432 Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveBase20); +433 Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveMod12); +434 Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveMod20); +435 } +436 } +437 +438 /** +439 * Creates a file appender and adds it to logback. +440 * +441 * @param verboseLog the path to the verbose log file +442 */ +443 private void prepareLogger(String verboseLog) { +444 final StaticLoggerBinder loggerBinder = StaticLoggerBinder.getSingleton(); +445 final LoggerContext context = (LoggerContext) loggerBinder.getLoggerFactory(); +446 +447 final PatternLayoutEncoder encoder = new PatternLayoutEncoder(); +448 encoder.setPattern("%d %C:%L%n%-5level - %msg%n"); +449 encoder.setContext(context); +450 encoder.start(); +451 final FileAppender<ILoggingEvent> fa = new FileAppender<ILoggingEvent>(); +452 fa.setAppend(true); +453 fa.setEncoder(encoder); +454 fa.setContext(context); +455 fa.setFile(verboseLog); +456 final File f = new File(verboseLog); +457 String name = f.getName(); +458 final int i = name.lastIndexOf('.'); +459 if (i > 1) { +460 name = name.substring(0, i); +461 } +462 fa.setName(name); +463 fa.start(); +464 final ch.qos.logback.classic.Logger rootLogger = context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); +465 rootLogger.addAppender(fa); +466 } +467 +468 /** +469 * Takes a path and resolves it to be a canonical &amp; absolute path. The +470 * caveats are that this method will take an Ant style file selector path +471 * (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at +472 * least to the left of the first * or ?). +473 * +474 * @param path the path to canonicalize +475 * @return the canonical path +476 */ +477 protected String ensureCanonicalPath(String path) { +478 String basePath; +479 String wildCards = null; +480 final String file = path.replace('\\', '/'); +481 if (file.contains("*") || file.contains("?")) { +482 +483 int pos = getLastFileSeparator(file); +484 if (pos < 0) { +485 return file; +486 } +487 pos += 1; +488 basePath = file.substring(0, pos); +489 wildCards = file.substring(pos); +490 } else { +491 basePath = file; +492 } +493 +494 File f = new File(basePath); +495 try { +496 f = f.getCanonicalFile(); +497 if (wildCards != null) { +498 f = new File(f, wildCards); +499 } +500 } catch (IOException ex) { +501 LOGGER.warn("Invalid path '{}' was provided.", path); +502 LOGGER.debug("Invalid path provided", ex); +503 } +504 return f.getAbsolutePath().replace('\\', '/'); +505 } +506 +507 /** +508 * Returns the position of the last file separator. +509 * +510 * @param file a file path +511 * @return the position of the last file separator +512 */ +513 private int getLastFileSeparator(String file) { +514 if (file.contains("*") || file.contains("?")) { +515 int p1 = file.indexOf('*'); +516 int p2 = file.indexOf('?'); +517 p1 = p1 > 0 ? p1 : file.length(); +518 p2 = p2 > 0 ? p2 : file.length(); +519 int pos = p1 < p2 ? p1 : p2; +520 pos = file.lastIndexOf('/', pos); +521 return pos; +522 } else { +523 return file.lastIndexOf('/'); +524 } +525 } +526 }
      diff --git a/xref/org/owasp/dependencycheck/CliParser.html b/xref/org/owasp/dependencycheck/CliParser.html index 133d1cec5..4b3456f45 100644 --- a/xref/org/owasp/dependencycheck/CliParser.html +++ b/xref/org/owasp/dependencycheck/CliParser.html @@ -285,1120 +285,1139 @@ 277 .desc("The file path to the suppression XML file.") 278 .build(); 279 -280 final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS) -281 .desc("The number of hours to wait before checking for new updates from the NVD.") +280 final Option hintsFile = Option.builder().argName("file").hasArg().longOpt(ARGUMENT.HINTS_FILE) +281 .desc("The file path to the hints XML file.") 282 .build(); 283 -284 final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL) -285 .desc("Enables the experimental analzers.") +284 final Option cveValidForHours = Option.builder().argName("hours").hasArg().longOpt(ARGUMENT.CVE_VALID_FOR_HOURS) +285 .desc("The number of hours to wait before checking for new updates from the NVD.") 286 .build(); 287 -288 //This is an option group because it can be specified more then once. -289 final OptionGroup og = new OptionGroup(); -290 og.addOption(path); +288 final Option experimentalEnabled = Option.builder().longOpt(ARGUMENT.EXPERIMENTAL) +289 .desc("Enables the experimental analzers.") +290 .build(); 291 -292 final OptionGroup exog = new OptionGroup(); -293 exog.addOption(excludes); -294 -295 options.addOptionGroup(og) -296 .addOptionGroup(exog) -297 .addOption(projectName) -298 .addOption(out) -299 .addOption(outputFormat) -300 .addOption(version) -301 .addOption(help) -302 .addOption(advancedHelp) -303 .addOption(noUpdate) -304 .addOption(symLinkDepth) -305 .addOption(props) -306 .addOption(verboseLog) -307 .addOption(suppressionFile) -308 .addOption(cveValidForHours) -309 .addOption(experimentalEnabled); -310 } -311 -312 /** -313 * Adds the advanced command line options to the given options collection. -314 * These are split out for purposes of being able to display two different -315 * help messages. -316 * -317 * @param options a collection of command line arguments -318 * @throws IllegalArgumentException thrown if there is an exception -319 */ -320 @SuppressWarnings("static-access") -321 private void addAdvancedOptions(final Options options) throws IllegalArgumentException { -322 -323 final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12) -324 .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ") -325 .build(); -326 -327 final Option cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20) -328 .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.") -329 .build(); -330 -331 final Option cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12) -332 .desc("URL for the modified CVE 1.2.") -333 .build(); -334 -335 final Option cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20) -336 .desc("URL for the modified CVE 2.0.") -337 .build(); -338 -339 final Option updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY) -340 .desc("Only update the local NVD data cache; no scan will be executed.").build(); -341 -342 final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY) -343 .desc("The location of the H2 Database file. This option should generally not be set.") -344 .build(); -345 -346 final Option nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL) -347 .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). " -348 + "If not set the Nexus Analyzer will be disabled.").build(); -349 -350 final Option nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY) -351 .desc("Whether or not the configured proxy should be used when connecting to Nexus.") -352 .build(); -353 -354 final Option additionalZipExtensions = Option.builder().argName("extensions").hasArg() -355 .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS) -356 .desc("A comma separated list of additional extensions to be scanned as ZIP files " -357 + "(ZIP, EAR, WAR are already treated as zip files)").build(); +292 //This is an option group because it can be specified more then once. +293 final OptionGroup og = new OptionGroup(); +294 og.addOption(path); +295 +296 final OptionGroup exog = new OptionGroup(); +297 exog.addOption(excludes); +298 +299 options.addOptionGroup(og) +300 .addOptionGroup(exog) +301 .addOption(projectName) +302 .addOption(out) +303 .addOption(outputFormat) +304 .addOption(version) +305 .addOption(help) +306 .addOption(advancedHelp) +307 .addOption(noUpdate) +308 .addOption(symLinkDepth) +309 .addOption(props) +310 .addOption(verboseLog) +311 .addOption(suppressionFile) +312 .addOption(hintsFile) +313 .addOption(cveValidForHours) +314 .addOption(experimentalEnabled); +315 } +316 +317 /** +318 * Adds the advanced command line options to the given options collection. +319 * These are split out for purposes of being able to display two different +320 * help messages. +321 * +322 * @param options a collection of command line arguments +323 * @throws IllegalArgumentException thrown if there is an exception +324 */ +325 @SuppressWarnings("static-access") +326 private void addAdvancedOptions(final Options options) throws IllegalArgumentException { +327 +328 final Option cve12Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_12) +329 .desc("Base URL for each year’s CVE 1.2, the %d will be replaced with the year. ") +330 .build(); +331 +332 final Option cve20Base = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_BASE_20) +333 .desc("Base URL for each year’s CVE 2.0, the %d will be replaced with the year.") +334 .build(); +335 +336 final Option cve12Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_12) +337 .desc("URL for the modified CVE 1.2.") +338 .build(); +339 +340 final Option cve20Modified = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.CVE_MOD_20) +341 .desc("URL for the modified CVE 2.0.") +342 .build(); +343 +344 final Option updateOnly = Option.builder().longOpt(ARGUMENT.UPDATE_ONLY) +345 .desc("Only update the local NVD data cache; no scan will be executed.").build(); +346 +347 final Option data = Option.builder(ARGUMENT.DATA_DIRECTORY_SHORT).argName("path").hasArg().longOpt(ARGUMENT.DATA_DIRECTORY) +348 .desc("The location of the H2 Database file. This option should generally not be set.") +349 .build(); +350 +351 final Option nexusUrl = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.NEXUS_URL) +352 .desc("The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). " +353 + "If not set the Nexus Analyzer will be disabled.").build(); +354 +355 final Option nexusUsesProxy = Option.builder().argName("true/false").hasArg().longOpt(ARGUMENT.NEXUS_USES_PROXY) +356 .desc("Whether or not the configured proxy should be used when connecting to Nexus.") +357 .build(); 358 -359 final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO) -360 .desc("The path to Mono for .NET Assembly analysis on non-windows systems.") -361 .build(); -362 -363 final Option pathToBundleAudit = Option.builder().argName("path").hasArg() -364 .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT) -365 .desc("The path to bundle-audit for Gem bundle analysis.").build(); -366 -367 final Option connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg() -368 .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.") -369 .build(); -370 -371 final Option proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER) -372 .desc("The proxy server to use when downloading resources.").build(); -373 -374 final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT) -375 .desc("The proxy port to use when downloading resources.").build(); -376 -377 final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME) -378 .desc("The proxy username to use when downloading resources.").build(); -379 -380 final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD) -381 .desc("The proxy password to use when downloading resources.").build(); -382 -383 final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING) -384 .desc("The connection string to the database.").build(); -385 -386 final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME) -387 .desc("The username used to connect to the database.").build(); -388 -389 final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD) -390 .desc("The password for connecting to the database.").build(); -391 -392 final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER) -393 .desc("The database driver name.").build(); -394 -395 final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH) -396 .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.") -397 .build(); -398 -399 final Option disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR) -400 .desc("Disable the Jar Analyzer.").build(); -401 -402 final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE) -403 .desc("Disable the Archive Analyzer.").build(); -404 -405 final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC) -406 .desc("Disable the Nuspec Analyzer.").build(); -407 -408 final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY) -409 .desc("Disable the .NET Assembly Analyzer.").build(); -410 -411 final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST) -412 .desc("Disable the Python Distribution Analyzer.").build(); -413 -414 final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG) -415 .desc("Disable the Python Package Analyzer.").build(); -416 -417 final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER) -418 .desc("Disable the PHP Composer Analyzer.").build(); -419 -420 final Option disableAutoconfAnalyzer = Option.builder() -421 .longOpt(ARGUMENT.DISABLE_AUTOCONF) -422 .desc("Disable the Autoconf Analyzer.").build(); -423 -424 final Option disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL) -425 .desc("Disable the OpenSSL Analyzer.").build(); -426 final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE) -427 .desc("Disable the Cmake Analyzer.").build(); +359 final Option additionalZipExtensions = Option.builder().argName("extensions").hasArg() +360 .longOpt(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS) +361 .desc("A comma separated list of additional extensions to be scanned as ZIP files " +362 + "(ZIP, EAR, WAR are already treated as zip files)").build(); +363 +364 final Option pathToMono = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.PATH_TO_MONO) +365 .desc("The path to Mono for .NET Assembly analysis on non-windows systems.") +366 .build(); +367 +368 final Option pathToBundleAudit = Option.builder().argName("path").hasArg() +369 .longOpt(ARGUMENT.PATH_TO_BUNDLE_AUDIT) +370 .desc("The path to bundle-audit for Gem bundle analysis.").build(); +371 +372 final Option connectionTimeout = Option.builder(ARGUMENT.CONNECTION_TIMEOUT_SHORT).argName("timeout").hasArg() +373 .longOpt(ARGUMENT.CONNECTION_TIMEOUT).desc("The connection timeout (in milliseconds) to use when downloading resources.") +374 .build(); +375 +376 final Option proxyServer = Option.builder().argName("server").hasArg().longOpt(ARGUMENT.PROXY_SERVER) +377 .desc("The proxy server to use when downloading resources.").build(); +378 +379 final Option proxyPort = Option.builder().argName("port").hasArg().longOpt(ARGUMENT.PROXY_PORT) +380 .desc("The proxy port to use when downloading resources.").build(); +381 +382 final Option proxyUsername = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.PROXY_USERNAME) +383 .desc("The proxy username to use when downloading resources.").build(); +384 +385 final Option proxyPassword = Option.builder().argName("pass").hasArg().longOpt(ARGUMENT.PROXY_PASSWORD) +386 .desc("The proxy password to use when downloading resources.").build(); +387 +388 final Option connectionString = Option.builder().argName("connStr").hasArg().longOpt(ARGUMENT.CONNECTION_STRING) +389 .desc("The connection string to the database.").build(); +390 +391 final Option dbUser = Option.builder().argName("user").hasArg().longOpt(ARGUMENT.DB_NAME) +392 .desc("The username used to connect to the database.").build(); +393 +394 final Option dbPassword = Option.builder().argName("password").hasArg().longOpt(ARGUMENT.DB_PASSWORD) +395 .desc("The password for connecting to the database.").build(); +396 +397 final Option dbDriver = Option.builder().argName("driver").hasArg().longOpt(ARGUMENT.DB_DRIVER) +398 .desc("The database driver name.").build(); +399 +400 final Option dbDriverPath = Option.builder().argName("path").hasArg().longOpt(ARGUMENT.DB_DRIVER_PATH) +401 .desc("The path to the database driver; note, this does not need to be set unless the JAR is outside of the classpath.") +402 .build(); +403 +404 final Option disableJarAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_JAR) +405 .desc("Disable the Jar Analyzer.").build(); +406 +407 final Option disableArchiveAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ARCHIVE) +408 .desc("Disable the Archive Analyzer.").build(); +409 +410 final Option disableNuspecAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NUSPEC) +411 .desc("Disable the Nuspec Analyzer.").build(); +412 +413 final Option disableAssemblyAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_ASSEMBLY) +414 .desc("Disable the .NET Assembly Analyzer.").build(); +415 +416 final Option disablePythonDistributionAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_DIST) +417 .desc("Disable the Python Distribution Analyzer.").build(); +418 +419 final Option disablePythonPackageAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_PY_PKG) +420 .desc("Disable the Python Package Analyzer.").build(); +421 +422 final Option disableComposerAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_COMPOSER) +423 .desc("Disable the PHP Composer Analyzer.").build(); +424 +425 final Option disableAutoconfAnalyzer = Option.builder() +426 .longOpt(ARGUMENT.DISABLE_AUTOCONF) +427 .desc("Disable the Autoconf Analyzer.").build(); 428 -429 final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL) -430 .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable " -431 + "the Nexus Analyzer.").build(); -432 -433 final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS) -434 .desc("Disable the Nexus Analyzer.").build(); -435 -436 final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD) -437 .desc("Purges the local NVD data cache") -438 .build(); -439 -440 options.addOption(updateOnly) -441 .addOption(cve12Base) -442 .addOption(cve20Base) -443 .addOption(cve12Modified) -444 .addOption(cve20Modified) -445 .addOption(proxyPort) -446 .addOption(proxyServer) -447 .addOption(proxyUsername) -448 .addOption(proxyPassword) -449 .addOption(connectionTimeout) -450 .addOption(connectionString) -451 .addOption(dbUser) -452 .addOption(data) -453 .addOption(dbPassword) -454 .addOption(dbDriver) -455 .addOption(dbDriverPath) -456 .addOption(disableJarAnalyzer) -457 .addOption(disableArchiveAnalyzer) -458 .addOption(disableAssemblyAnalyzer) -459 .addOption(pathToBundleAudit) -460 .addOption(disablePythonDistributionAnalyzer) -461 .addOption(disableCmakeAnalyzer) -462 .addOption(disablePythonPackageAnalyzer) -463 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS) -464 .desc("Disable the Ruby Gemspec Analyzer.").build()) -465 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT) -466 .desc("Disable the Ruby Bundler-Audit Analyzer.").build()) -467 .addOption(disableAutoconfAnalyzer) -468 .addOption(disableComposerAnalyzer) -469 .addOption(disableOpenSSLAnalyzer) -470 .addOption(disableNuspecAnalyzer) -471 .addOption(disableCentralAnalyzer) -472 .addOption(disableNexusAnalyzer) -473 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS) -474 .desc("Disable the Node.js Package Analyzer.").build()) -475 .addOption(nexusUrl) -476 .addOption(nexusUsesProxy) -477 .addOption(additionalZipExtensions) -478 .addOption(pathToMono) -479 .addOption(pathToBundleAudit) -480 .addOption(purge); -481 } -482 -483 /** -484 * Adds the deprecated command line options to the given options collection. -485 * These are split out for purposes of not including them in the help -486 * message. We need to add the deprecated options so as not to break -487 * existing scripts. -488 * -489 * @param options a collection of command line arguments -490 * @throws IllegalArgumentException thrown if there is an exception -491 */ -492 @SuppressWarnings({"static-access", "deprecation"}) -493 private void addDeprecatedOptions(final Options options) throws IllegalArgumentException { -494 -495 final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL) -496 .desc("The proxy url argument is deprecated, use proxyserver instead.") -497 .build(); -498 final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME) -499 .desc("The name of the project being scanned.") -500 .build(); -501 -502 options.addOption(proxyServer); -503 options.addOption(appName); -504 } -505 -506 /** -507 * Determines if the 'version' command line argument was passed in. -508 * -509 * @return whether or not the 'version' command line argument was passed in -510 */ -511 public boolean isGetVersion() { -512 return (line != null) && line.hasOption(ARGUMENT.VERSION); -513 } -514 -515 /** -516 * Determines if the 'help' command line argument was passed in. -517 * -518 * @return whether or not the 'help' command line argument was passed in -519 */ -520 public boolean isGetHelp() { -521 return (line != null) && line.hasOption(ARGUMENT.HELP); -522 } -523 -524 /** -525 * Determines if the 'scan' command line argument was passed in. -526 * -527 * @return whether or not the 'scan' command line argument was passed in -528 */ -529 public boolean isRunScan() { -530 return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN); -531 } -532 -533 /** -534 * Returns the symbolic link depth (how deeply symbolic links will be -535 * followed). -536 * -537 * @return the symbolic link depth -538 */ -539 public int getSymLinkDepth() { -540 int value = 0; -541 try { -542 value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0")); -543 if (value < 0) { -544 value = 0; -545 } -546 } catch (NumberFormatException ex) { -547 LOGGER.debug("Symbolic link was not a number"); -548 } -549 return value; -550 } -551 -552 /** -553 * Returns true if the disableJar command line argument was specified. -554 * -555 * @return true if the disableJar command line argument was specified; -556 * otherwise false -557 */ -558 public boolean isJarDisabled() { -559 return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR); -560 } -561 -562 /** -563 * Returns true if the disableArchive command line argument was specified. -564 * -565 * @return true if the disableArchive command line argument was specified; -566 * otherwise false -567 */ -568 public boolean isArchiveDisabled() { -569 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE); -570 } -571 -572 /** -573 * Returns true if the disableNuspec command line argument was specified. -574 * -575 * @return true if the disableNuspec command line argument was specified; -576 * otherwise false -577 */ -578 public boolean isNuspecDisabled() { -579 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC); -580 } -581 -582 /** -583 * Returns true if the disableAssembly command line argument was specified. -584 * -585 * @return true if the disableAssembly command line argument was specified; -586 * otherwise false -587 */ -588 public boolean isAssemblyDisabled() { -589 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY); -590 } -591 -592 /** -593 * Returns true if the disableBundleAudit command line argument was -594 * specified. -595 * -596 * @return true if the disableBundleAudit command line argument was -597 * specified; otherwise false -598 */ -599 public boolean isBundleAuditDisabled() { -600 return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT); -601 } -602 -603 /** -604 * Returns true if the disablePyDist command line argument was specified. -605 * -606 * @return true if the disablePyDist command line argument was specified; -607 * otherwise false -608 */ -609 public boolean isPythonDistributionDisabled() { -610 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST); -611 } -612 -613 /** -614 * Returns true if the disablePyPkg command line argument was specified. -615 * -616 * @return true if the disablePyPkg command line argument was specified; -617 * otherwise false -618 */ -619 public boolean isPythonPackageDisabled() { -620 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG); -621 } -622 -623 /** -624 * Returns whether the Ruby gemspec analyzer is disabled. -625 * -626 * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line -627 * argument was specified; otherwise false -628 */ -629 public boolean isRubyGemspecDisabled() { -630 return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS); -631 } -632 -633 /** -634 * Returns true if the disableCmake command line argument was specified. -635 * -636 * @return true if the disableCmake command line argument was specified; -637 * otherwise false -638 */ -639 public boolean isCmakeDisabled() { -640 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE); -641 } -642 -643 /** -644 * Returns true if the disableAutoconf command line argument was specified. -645 * -646 * @return true if the disableAutoconf command line argument was specified; -647 * otherwise false -648 */ -649 public boolean isAutoconfDisabled() { -650 return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF); -651 } -652 -653 /** -654 * Returns true if the disableComposer command line argument was specified. -655 * -656 * @return true if the disableComposer command line argument was specified; -657 * otherwise false -658 */ -659 public boolean isComposerDisabled() { -660 return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER); -661 } -662 -663 /** -664 * Returns true if the disableNexus command line argument was specified. -665 * -666 * @return true if the disableNexus command line argument was specified; -667 * otherwise false -668 */ -669 public boolean isNexusDisabled() { -670 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS); -671 } -672 -673 /** -674 * Returns true if the disableOpenSSL command line argument was specified. -675 * -676 * @return true if the disableOpenSSL command line argument was specified; -677 * otherwise false -678 */ -679 public boolean isOpenSSLDisabled() { -680 return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL); -681 } -682 -683 /** -684 * Returns true if the disableNodeJS command line argument was specified. -685 * -686 * @return true if the disableNodeJS command line argument was specified; -687 * otherwise false -688 */ -689 public boolean isNodeJsDisabled() { -690 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS); -691 } -692 -693 /** -694 * Returns true if the disableCentral command line argument was specified. -695 * -696 * @return true if the disableCentral command line argument was specified; -697 * otherwise false -698 */ -699 public boolean isCentralDisabled() { -700 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL); -701 } -702 -703 /** -704 * Returns the url to the nexus server if one was specified. -705 * -706 * @return the url to the nexus server; if none was specified this will -707 * return null; -708 */ -709 public String getNexusUrl() { -710 if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) { -711 return null; -712 } else { -713 return line.getOptionValue(ARGUMENT.NEXUS_URL); -714 } -715 } -716 -717 /** -718 * Returns true if the Nexus Analyzer should use the configured proxy to -719 * connect to Nexus; otherwise false is returned. -720 * -721 * @return true if the Nexus Analyzer should use the configured proxy to -722 * connect to Nexus; otherwise false -723 */ -724 public boolean isNexusUsesProxy() { -725 // If they didn't specify whether Nexus needs to use the proxy, we should -726 // still honor the property if it's set. -727 if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) { -728 try { -729 return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY); -730 } catch (InvalidSettingException ise) { -731 return true; -732 } -733 } else { -734 return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY)); -735 } -736 } -737 -738 /** -739 * Displays the command line help message to the standard output. -740 */ -741 public void printHelp() { -742 final HelpFormatter formatter = new HelpFormatter(); -743 final Options options = new Options(); -744 addStandardOptions(options); -745 if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) { -746 addAdvancedOptions(options); -747 } -748 final String helpMsg = String.format("%n%s" -749 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. " -750 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n", -751 Settings.getString("application.name", "DependencyCheck"), -752 Settings.getString("application.name", "DependencyCheck")); -753 -754 formatter.printHelp(Settings.getString("application.name", "DependencyCheck"), -755 helpMsg, -756 options, -757 "", -758 true); -759 } -760 -761 /** -762 * Retrieves the file command line parameter(s) specified for the 'scan' -763 * argument. -764 * -765 * @return the file paths specified on the command line for scan -766 */ -767 public String[] getScanFiles() { -768 return line.getOptionValues(ARGUMENT.SCAN); -769 } -770 -771 /** -772 * Retrieves the list of excluded file patterns specified by the 'exclude' -773 * argument. -774 * -775 * @return the excluded file patterns -776 */ -777 public String[] getExcludeList() { -778 return line.getOptionValues(ARGUMENT.EXCLUDE); -779 } -780 -781 /** -782 * Returns the directory to write the reports to specified on the command -783 * line. -784 * -785 * @return the path to the reports directory. -786 */ -787 public String getReportDirectory() { -788 return line.getOptionValue(ARGUMENT.OUT, "."); -789 } -790 -791 /** -792 * Returns the path to Mono for .NET Assembly analysis on non-windows -793 * systems. -794 * -795 * @return the path to Mono -796 */ -797 public String getPathToMono() { -798 return line.getOptionValue(ARGUMENT.PATH_TO_MONO); -799 } -800 -801 /** -802 * Returns the path to bundle-audit for Ruby bundle analysis. -803 * -804 * @return the path to Mono -805 */ -806 public String getPathToBundleAudit() { -807 return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT); -808 } -809 -810 /** -811 * Returns the output format specified on the command line. Defaults to HTML -812 * if no format was specified. -813 * -814 * @return the output format name. -815 */ -816 public String getReportFormat() { -817 return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML"); -818 } -819 -820 /** -821 * Returns the application name specified on the command line. -822 * -823 * @return the application name. -824 */ -825 public String getProjectName() { -826 final String appName = line.getOptionValue(ARGUMENT.APP_NAME); -827 String name = line.getOptionValue(ARGUMENT.PROJECT); -828 if (name == null && appName != null) { -829 name = appName; -830 LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead."); -831 } -832 return name; -833 } -834 -835 /** -836 * Returns the base URL for the CVE 1.2 XMl file. -837 * -838 * @return the URL to the CVE 1.2 XML file. -839 */ -840 public String getBaseCve12Url() { -841 return line.getOptionValue(ARGUMENT.CVE_BASE_12); -842 } -843 -844 /** -845 * Returns the base URL for the CVE 2.0 XMl file. -846 * -847 * @return the URL to the CVE 2.0 XML file. -848 */ -849 public String getBaseCve20Url() { -850 return line.getOptionValue(ARGUMENT.CVE_BASE_20); -851 } -852 -853 /** -854 * Returns the URL for the modified CVE 1.2 XMl file. -855 * -856 * @return the URL to the modified CVE 1.2 XML file. -857 */ -858 public String getModifiedCve12Url() { -859 return line.getOptionValue(ARGUMENT.CVE_MOD_12); -860 } -861 -862 /** -863 * Returns the URL for the modified CVE 2.0 XMl file. -864 * -865 * @return the URL to the modified CVE 2.0 XML file. -866 */ -867 public String getModifiedCve20Url() { -868 return line.getOptionValue(ARGUMENT.CVE_MOD_20); -869 } -870 -871 /** -872 * Returns the connection timeout. -873 * -874 * @return the connection timeout -875 */ -876 public String getConnectionTimeout() { -877 return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT); -878 } -879 -880 /** -881 * Returns the proxy server. -882 * -883 * @return the proxy server -884 */ -885 @SuppressWarnings("deprecation") -886 public String getProxyServer() { -887 -888 String server = line.getOptionValue(ARGUMENT.PROXY_SERVER); -889 if (server == null) { -890 server = line.getOptionValue(ARGUMENT.PROXY_URL); -891 if (server != null) { -892 LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead"); -893 } -894 } -895 return server; -896 } -897 -898 /** -899 * Returns the proxy port. -900 * -901 * @return the proxy port -902 */ -903 public String getProxyPort() { -904 return line.getOptionValue(ARGUMENT.PROXY_PORT); -905 } -906 -907 /** -908 * Returns the proxy username. -909 * -910 * @return the proxy username -911 */ -912 public String getProxyUsername() { -913 return line.getOptionValue(ARGUMENT.PROXY_USERNAME); -914 } -915 -916 /** -917 * Returns the proxy password. -918 * -919 * @return the proxy password -920 */ -921 public String getProxyPassword() { -922 return line.getOptionValue(ARGUMENT.PROXY_PASSWORD); -923 } -924 -925 /** -926 * Get the value of dataDirectory. -927 * -928 * @return the value of dataDirectory -929 */ -930 public String getDataDirectory() { -931 return line.getOptionValue(ARGUMENT.DATA_DIRECTORY); -932 } -933 -934 /** -935 * Returns the properties file specified on the command line. -936 * -937 * @return the properties file specified on the command line -938 */ -939 public File getPropertiesFile() { -940 final String path = line.getOptionValue(ARGUMENT.PROP); -941 if (path != null) { -942 return new File(path); -943 } -944 return null; -945 } -946 -947 /** -948 * Returns the path to the verbose log file. -949 * -950 * @return the path to the verbose log file -951 */ -952 public String getVerboseLog() { -953 return line.getOptionValue(ARGUMENT.VERBOSE_LOG); -954 } -955 -956 /** -957 * Returns the path to the suppression file. -958 * -959 * @return the path to the suppression file -960 */ -961 public String getSuppressionFile() { -962 return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE); -963 } -964 -965 /** -966 * <p> -967 * Prints the manifest information to standard output.</p> -968 * <ul><li>Implementation-Title: ${pom.name}</li> -969 * <li>Implementation-Version: ${pom.version}</li></ul> -970 */ -971 public void printVersionInfo() { -972 final String version = String.format("%s version %s", -973 Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"), -974 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown")); -975 System.out.println(version); -976 } -977 -978 /** -979 * Checks if the auto update feature has been disabled. If it has been -980 * disabled via the command line this will return false. -981 * -982 * @return <code>true</code> if auto-update is allowed; otherwise -983 * <code>false</code> +429 final Option disableOpenSSLAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_OPENSSL) +430 .desc("Disable the OpenSSL Analyzer.").build(); +431 final Option disableCmakeAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CMAKE) +432 .desc("Disable the Cmake Analyzer.").build(); +433 +434 final Option disableCentralAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_CENTRAL) +435 .desc("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable " +436 + "the Nexus Analyzer.").build(); +437 +438 final Option disableNexusAnalyzer = Option.builder().longOpt(ARGUMENT.DISABLE_NEXUS) +439 .desc("Disable the Nexus Analyzer.").build(); +440 +441 final Option purge = Option.builder().longOpt(ARGUMENT.PURGE_NVD) +442 .desc("Purges the local NVD data cache") +443 .build(); +444 +445 options.addOption(updateOnly) +446 .addOption(cve12Base) +447 .addOption(cve20Base) +448 .addOption(cve12Modified) +449 .addOption(cve20Modified) +450 .addOption(proxyPort) +451 .addOption(proxyServer) +452 .addOption(proxyUsername) +453 .addOption(proxyPassword) +454 .addOption(connectionTimeout) +455 .addOption(connectionString) +456 .addOption(dbUser) +457 .addOption(data) +458 .addOption(dbPassword) +459 .addOption(dbDriver) +460 .addOption(dbDriverPath) +461 .addOption(disableJarAnalyzer) +462 .addOption(disableArchiveAnalyzer) +463 .addOption(disableAssemblyAnalyzer) +464 .addOption(pathToBundleAudit) +465 .addOption(disablePythonDistributionAnalyzer) +466 .addOption(disableCmakeAnalyzer) +467 .addOption(disablePythonPackageAnalyzer) +468 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_RUBYGEMS) +469 .desc("Disable the Ruby Gemspec Analyzer.").build()) +470 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_BUNDLE_AUDIT) +471 .desc("Disable the Ruby Bundler-Audit Analyzer.").build()) +472 .addOption(disableAutoconfAnalyzer) +473 .addOption(disableComposerAnalyzer) +474 .addOption(disableOpenSSLAnalyzer) +475 .addOption(disableNuspecAnalyzer) +476 .addOption(disableCentralAnalyzer) +477 .addOption(disableNexusAnalyzer) +478 .addOption(Option.builder().longOpt(ARGUMENT.DISABLE_NODE_JS) +479 .desc("Disable the Node.js Package Analyzer.").build()) +480 .addOption(nexusUrl) +481 .addOption(nexusUsesProxy) +482 .addOption(additionalZipExtensions) +483 .addOption(pathToMono) +484 .addOption(pathToBundleAudit) +485 .addOption(purge); +486 } +487 +488 /** +489 * Adds the deprecated command line options to the given options collection. +490 * These are split out for purposes of not including them in the help +491 * message. We need to add the deprecated options so as not to break +492 * existing scripts. +493 * +494 * @param options a collection of command line arguments +495 * @throws IllegalArgumentException thrown if there is an exception +496 */ +497 @SuppressWarnings({"static-access", "deprecation"}) +498 private void addDeprecatedOptions(final Options options) throws IllegalArgumentException { +499 +500 final Option proxyServer = Option.builder().argName("url").hasArg().longOpt(ARGUMENT.PROXY_URL) +501 .desc("The proxy url argument is deprecated, use proxyserver instead.") +502 .build(); +503 final Option appName = Option.builder(ARGUMENT.APP_NAME_SHORT).argName("name").hasArg().longOpt(ARGUMENT.APP_NAME) +504 .desc("The name of the project being scanned.") +505 .build(); +506 +507 options.addOption(proxyServer); +508 options.addOption(appName); +509 } +510 +511 /** +512 * Determines if the 'version' command line argument was passed in. +513 * +514 * @return whether or not the 'version' command line argument was passed in +515 */ +516 public boolean isGetVersion() { +517 return (line != null) && line.hasOption(ARGUMENT.VERSION); +518 } +519 +520 /** +521 * Determines if the 'help' command line argument was passed in. +522 * +523 * @return whether or not the 'help' command line argument was passed in +524 */ +525 public boolean isGetHelp() { +526 return (line != null) && line.hasOption(ARGUMENT.HELP); +527 } +528 +529 /** +530 * Determines if the 'scan' command line argument was passed in. +531 * +532 * @return whether or not the 'scan' command line argument was passed in +533 */ +534 public boolean isRunScan() { +535 return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN); +536 } +537 +538 /** +539 * Returns the symbolic link depth (how deeply symbolic links will be +540 * followed). +541 * +542 * @return the symbolic link depth +543 */ +544 public int getSymLinkDepth() { +545 int value = 0; +546 try { +547 value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0")); +548 if (value < 0) { +549 value = 0; +550 } +551 } catch (NumberFormatException ex) { +552 LOGGER.debug("Symbolic link was not a number"); +553 } +554 return value; +555 } +556 +557 /** +558 * Returns true if the disableJar command line argument was specified. +559 * +560 * @return true if the disableJar command line argument was specified; +561 * otherwise false +562 */ +563 public boolean isJarDisabled() { +564 return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR); +565 } +566 +567 /** +568 * Returns true if the disableArchive command line argument was specified. +569 * +570 * @return true if the disableArchive command line argument was specified; +571 * otherwise false +572 */ +573 public boolean isArchiveDisabled() { +574 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE); +575 } +576 +577 /** +578 * Returns true if the disableNuspec command line argument was specified. +579 * +580 * @return true if the disableNuspec command line argument was specified; +581 * otherwise false +582 */ +583 public boolean isNuspecDisabled() { +584 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC); +585 } +586 +587 /** +588 * Returns true if the disableAssembly command line argument was specified. +589 * +590 * @return true if the disableAssembly command line argument was specified; +591 * otherwise false +592 */ +593 public boolean isAssemblyDisabled() { +594 return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY); +595 } +596 +597 /** +598 * Returns true if the disableBundleAudit command line argument was +599 * specified. +600 * +601 * @return true if the disableBundleAudit command line argument was +602 * specified; otherwise false +603 */ +604 public boolean isBundleAuditDisabled() { +605 return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT); +606 } +607 +608 /** +609 * Returns true if the disablePyDist command line argument was specified. +610 * +611 * @return true if the disablePyDist command line argument was specified; +612 * otherwise false +613 */ +614 public boolean isPythonDistributionDisabled() { +615 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST); +616 } +617 +618 /** +619 * Returns true if the disablePyPkg command line argument was specified. +620 * +621 * @return true if the disablePyPkg command line argument was specified; +622 * otherwise false +623 */ +624 public boolean isPythonPackageDisabled() { +625 return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG); +626 } +627 +628 /** +629 * Returns whether the Ruby gemspec analyzer is disabled. +630 * +631 * @return true if the {@link ARGUMENT#DISABLE_RUBYGEMS} command line +632 * argument was specified; otherwise false +633 */ +634 public boolean isRubyGemspecDisabled() { +635 return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS); +636 } +637 +638 /** +639 * Returns true if the disableCmake command line argument was specified. +640 * +641 * @return true if the disableCmake command line argument was specified; +642 * otherwise false +643 */ +644 public boolean isCmakeDisabled() { +645 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE); +646 } +647 +648 /** +649 * Returns true if the disableAutoconf command line argument was specified. +650 * +651 * @return true if the disableAutoconf command line argument was specified; +652 * otherwise false +653 */ +654 public boolean isAutoconfDisabled() { +655 return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF); +656 } +657 +658 /** +659 * Returns true if the disableComposer command line argument was specified. +660 * +661 * @return true if the disableComposer command line argument was specified; +662 * otherwise false +663 */ +664 public boolean isComposerDisabled() { +665 return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER); +666 } +667 +668 /** +669 * Returns true if the disableNexus command line argument was specified. +670 * +671 * @return true if the disableNexus command line argument was specified; +672 * otherwise false +673 */ +674 public boolean isNexusDisabled() { +675 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS); +676 } +677 +678 /** +679 * Returns true if the disableOpenSSL command line argument was specified. +680 * +681 * @return true if the disableOpenSSL command line argument was specified; +682 * otherwise false +683 */ +684 public boolean isOpenSSLDisabled() { +685 return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL); +686 } +687 +688 /** +689 * Returns true if the disableNodeJS command line argument was specified. +690 * +691 * @return true if the disableNodeJS command line argument was specified; +692 * otherwise false +693 */ +694 public boolean isNodeJsDisabled() { +695 return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS); +696 } +697 +698 /** +699 * Returns true if the disableCentral command line argument was specified. +700 * +701 * @return true if the disableCentral command line argument was specified; +702 * otherwise false +703 */ +704 public boolean isCentralDisabled() { +705 return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL); +706 } +707 +708 /** +709 * Returns the url to the nexus server if one was specified. +710 * +711 * @return the url to the nexus server; if none was specified this will +712 * return null; +713 */ +714 public String getNexusUrl() { +715 if (line == null || !line.hasOption(ARGUMENT.NEXUS_URL)) { +716 return null; +717 } else { +718 return line.getOptionValue(ARGUMENT.NEXUS_URL); +719 } +720 } +721 +722 /** +723 * Returns true if the Nexus Analyzer should use the configured proxy to +724 * connect to Nexus; otherwise false is returned. +725 * +726 * @return true if the Nexus Analyzer should use the configured proxy to +727 * connect to Nexus; otherwise false +728 */ +729 public boolean isNexusUsesProxy() { +730 // If they didn't specify whether Nexus needs to use the proxy, we should +731 // still honor the property if it's set. +732 if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) { +733 try { +734 return Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY); +735 } catch (InvalidSettingException ise) { +736 return true; +737 } +738 } else { +739 return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY)); +740 } +741 } +742 +743 /** +744 * Displays the command line help message to the standard output. +745 */ +746 public void printHelp() { +747 final HelpFormatter formatter = new HelpFormatter(); +748 final Options options = new Options(); +749 addStandardOptions(options); +750 if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) { +751 addAdvancedOptions(options); +752 } +753 final String helpMsg = String.format("%n%s" +754 + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. " +755 + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n", +756 Settings.getString("application.name", "DependencyCheck"), +757 Settings.getString("application.name", "DependencyCheck")); +758 +759 formatter.printHelp(Settings.getString("application.name", "DependencyCheck"), +760 helpMsg, +761 options, +762 "", +763 true); +764 } +765 +766 /** +767 * Retrieves the file command line parameter(s) specified for the 'scan' +768 * argument. +769 * +770 * @return the file paths specified on the command line for scan +771 */ +772 public String[] getScanFiles() { +773 return line.getOptionValues(ARGUMENT.SCAN); +774 } +775 +776 /** +777 * Retrieves the list of excluded file patterns specified by the 'exclude' +778 * argument. +779 * +780 * @return the excluded file patterns +781 */ +782 public String[] getExcludeList() { +783 return line.getOptionValues(ARGUMENT.EXCLUDE); +784 } +785 +786 /** +787 * Returns the directory to write the reports to specified on the command +788 * line. +789 * +790 * @return the path to the reports directory. +791 */ +792 public String getReportDirectory() { +793 return line.getOptionValue(ARGUMENT.OUT, "."); +794 } +795 +796 /** +797 * Returns the path to Mono for .NET Assembly analysis on non-windows +798 * systems. +799 * +800 * @return the path to Mono +801 */ +802 public String getPathToMono() { +803 return line.getOptionValue(ARGUMENT.PATH_TO_MONO); +804 } +805 +806 /** +807 * Returns the path to bundle-audit for Ruby bundle analysis. +808 * +809 * @return the path to Mono +810 */ +811 public String getPathToBundleAudit() { +812 return line.getOptionValue(ARGUMENT.PATH_TO_BUNDLE_AUDIT); +813 } +814 +815 /** +816 * Returns the output format specified on the command line. Defaults to HTML +817 * if no format was specified. +818 * +819 * @return the output format name. +820 */ +821 public String getReportFormat() { +822 return line.getOptionValue(ARGUMENT.OUTPUT_FORMAT, "HTML"); +823 } +824 +825 /** +826 * Returns the application name specified on the command line. +827 * +828 * @return the application name. +829 */ +830 public String getProjectName() { +831 final String appName = line.getOptionValue(ARGUMENT.APP_NAME); +832 String name = line.getOptionValue(ARGUMENT.PROJECT); +833 if (name == null && appName != null) { +834 name = appName; +835 LOGGER.warn("The '" + ARGUMENT.APP_NAME + "' argument should no longer be used; use '" + ARGUMENT.PROJECT + "' instead."); +836 } +837 return name; +838 } +839 +840 /** +841 * Returns the base URL for the CVE 1.2 XMl file. +842 * +843 * @return the URL to the CVE 1.2 XML file. +844 */ +845 public String getBaseCve12Url() { +846 return line.getOptionValue(ARGUMENT.CVE_BASE_12); +847 } +848 +849 /** +850 * Returns the base URL for the CVE 2.0 XMl file. +851 * +852 * @return the URL to the CVE 2.0 XML file. +853 */ +854 public String getBaseCve20Url() { +855 return line.getOptionValue(ARGUMENT.CVE_BASE_20); +856 } +857 +858 /** +859 * Returns the URL for the modified CVE 1.2 XMl file. +860 * +861 * @return the URL to the modified CVE 1.2 XML file. +862 */ +863 public String getModifiedCve12Url() { +864 return line.getOptionValue(ARGUMENT.CVE_MOD_12); +865 } +866 +867 /** +868 * Returns the URL for the modified CVE 2.0 XMl file. +869 * +870 * @return the URL to the modified CVE 2.0 XML file. +871 */ +872 public String getModifiedCve20Url() { +873 return line.getOptionValue(ARGUMENT.CVE_MOD_20); +874 } +875 +876 /** +877 * Returns the connection timeout. +878 * +879 * @return the connection timeout +880 */ +881 public String getConnectionTimeout() { +882 return line.getOptionValue(ARGUMENT.CONNECTION_TIMEOUT); +883 } +884 +885 /** +886 * Returns the proxy server. +887 * +888 * @return the proxy server +889 */ +890 @SuppressWarnings("deprecation") +891 public String getProxyServer() { +892 +893 String server = line.getOptionValue(ARGUMENT.PROXY_SERVER); +894 if (server == null) { +895 server = line.getOptionValue(ARGUMENT.PROXY_URL); +896 if (server != null) { +897 LOGGER.warn("An old command line argument 'proxyurl' was detected; use proxyserver instead"); +898 } +899 } +900 return server; +901 } +902 +903 /** +904 * Returns the proxy port. +905 * +906 * @return the proxy port +907 */ +908 public String getProxyPort() { +909 return line.getOptionValue(ARGUMENT.PROXY_PORT); +910 } +911 +912 /** +913 * Returns the proxy username. +914 * +915 * @return the proxy username +916 */ +917 public String getProxyUsername() { +918 return line.getOptionValue(ARGUMENT.PROXY_USERNAME); +919 } +920 +921 /** +922 * Returns the proxy password. +923 * +924 * @return the proxy password +925 */ +926 public String getProxyPassword() { +927 return line.getOptionValue(ARGUMENT.PROXY_PASSWORD); +928 } +929 +930 /** +931 * Get the value of dataDirectory. +932 * +933 * @return the value of dataDirectory +934 */ +935 public String getDataDirectory() { +936 return line.getOptionValue(ARGUMENT.DATA_DIRECTORY); +937 } +938 +939 /** +940 * Returns the properties file specified on the command line. +941 * +942 * @return the properties file specified on the command line +943 */ +944 public File getPropertiesFile() { +945 final String path = line.getOptionValue(ARGUMENT.PROP); +946 if (path != null) { +947 return new File(path); +948 } +949 return null; +950 } +951 +952 /** +953 * Returns the path to the verbose log file. +954 * +955 * @return the path to the verbose log file +956 */ +957 public String getVerboseLog() { +958 return line.getOptionValue(ARGUMENT.VERBOSE_LOG); +959 } +960 +961 /** +962 * Returns the path to the suppression file. +963 * +964 * @return the path to the suppression file +965 */ +966 public String getSuppressionFile() { +967 return line.getOptionValue(ARGUMENT.SUPPRESSION_FILE); +968 } +969 +970 /** +971 * Returns the path to the hints file. +972 * +973 * @return the path to the hints file +974 */ +975 public String getHintsFile() { +976 return line.getOptionValue(ARGUMENT.HINTS_FILE); +977 } +978 +979 /** +980 * <p> +981 * Prints the manifest information to standard output.</p> +982 * <ul><li>Implementation-Title: ${pom.name}</li> +983 * <li>Implementation-Version: ${pom.version}</li></ul> 984 */ -985 public boolean isAutoUpdate() { -986 return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE); -987 } -988 -989 /** -990 * Checks if the update only flag has been set. -991 * -992 * @return <code>true</code> if the update only flag has been set; otherwise -993 * <code>false</code>. -994 */ -995 public boolean isUpdateOnly() { -996 return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY); -997 } -998 -999 /** -1000 * Checks if the purge NVD flag has been set. -1001 * -1002 * @return <code>true</code> if the purge nvd flag has been set; otherwise -1003 * <code>false</code>. -1004 */ -1005 public boolean isPurge() { -1006 return line != null && line.hasOption(ARGUMENT.PURGE_NVD); -1007 } -1008 -1009 /** -1010 * Returns the database driver name if specified; otherwise null is -1011 * returned. -1012 * -1013 * @return the database driver name if specified; otherwise null is returned -1014 */ -1015 public String getDatabaseDriverName() { -1016 return line.getOptionValue(ARGUMENT.DB_DRIVER); -1017 } -1018 -1019 /** -1020 * Returns the database driver path if specified; otherwise null is -1021 * returned. -1022 * -1023 * @return the database driver name if specified; otherwise null is returned -1024 */ -1025 public String getDatabaseDriverPath() { -1026 return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH); -1027 } -1028 -1029 /** -1030 * Returns the database connection string if specified; otherwise null is -1031 * returned. -1032 * -1033 * @return the database connection string if specified; otherwise null is -1034 * returned -1035 */ -1036 public String getConnectionString() { -1037 return line.getOptionValue(ARGUMENT.CONNECTION_STRING); -1038 } -1039 -1040 /** -1041 * Returns the database database user name if specified; otherwise null is -1042 * returned. -1043 * -1044 * @return the database database user name if specified; otherwise null is -1045 * returned -1046 */ -1047 public String getDatabaseUser() { -1048 return line.getOptionValue(ARGUMENT.DB_NAME); -1049 } -1050 -1051 /** -1052 * Returns the database database password if specified; otherwise null is -1053 * returned. -1054 * -1055 * @return the database database password if specified; otherwise null is -1056 * returned -1057 */ -1058 public String getDatabasePassword() { -1059 return line.getOptionValue(ARGUMENT.DB_PASSWORD); -1060 } -1061 -1062 /** -1063 * Returns the additional Extensions if specified; otherwise null is -1064 * returned. -1065 * -1066 * @return the additional Extensions; otherwise null is returned -1067 */ -1068 public String getAdditionalZipExtensions() { -1069 return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS); -1070 } -1071 -1072 /** -1073 * Get the value of cveValidForHours. -1074 * -1075 * @return the value of cveValidForHours -1076 */ -1077 public Integer getCveValidForHours() { -1078 final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS); -1079 if (v != null) { -1080 return Integer.parseInt(v); -1081 } -1082 return null; -1083 } -1084 -1085 /** -1086 * Returns true if the experimental analyzers are enabled. -1087 * -1088 * @return true if the experimental analyzers are enabled; otherwise false -1089 */ -1090 public boolean isExperimentalEnabled() { -1091 return line.hasOption(ARGUMENT.EXPERIMENTAL); -1092 } -1093 -1094 /** -1095 * A collection of static final strings that represent the possible command -1096 * line arguments. -1097 */ -1098 public static class ARGUMENT { -1099 -1100 /** -1101 * The long CLI argument name specifying the directory/file to scan. -1102 */ -1103 public static final String SCAN = "scan"; -1104 /** -1105 * The short CLI argument name specifying the directory/file to scan. -1106 */ -1107 public static final String SCAN_SHORT = "s"; -1108 /** -1109 * The long CLI argument name specifying that the CPE/CVE/etc. data -1110 * should not be automatically updated. -1111 */ -1112 public static final String DISABLE_AUTO_UPDATE = "noupdate"; -1113 /** -1114 * The short CLI argument name specifying that the CPE/CVE/etc. data -1115 * should not be automatically updated. +985 public void printVersionInfo() { +986 final String version = String.format("%s version %s", +987 Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"), +988 Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown")); +989 System.out.println(version); +990 } +991 +992 /** +993 * Checks if the auto update feature has been disabled. If it has been +994 * disabled via the command line this will return false. +995 * +996 * @return <code>true</code> if auto-update is allowed; otherwise +997 * <code>false</code> +998 */ +999 public boolean isAutoUpdate() { +1000 return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE); +1001 } +1002 +1003 /** +1004 * Checks if the update only flag has been set. +1005 * +1006 * @return <code>true</code> if the update only flag has been set; otherwise +1007 * <code>false</code>. +1008 */ +1009 public boolean isUpdateOnly() { +1010 return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY); +1011 } +1012 +1013 /** +1014 * Checks if the purge NVD flag has been set. +1015 * +1016 * @return <code>true</code> if the purge nvd flag has been set; otherwise +1017 * <code>false</code>. +1018 */ +1019 public boolean isPurge() { +1020 return line != null && line.hasOption(ARGUMENT.PURGE_NVD); +1021 } +1022 +1023 /** +1024 * Returns the database driver name if specified; otherwise null is +1025 * returned. +1026 * +1027 * @return the database driver name if specified; otherwise null is returned +1028 */ +1029 public String getDatabaseDriverName() { +1030 return line.getOptionValue(ARGUMENT.DB_DRIVER); +1031 } +1032 +1033 /** +1034 * Returns the database driver path if specified; otherwise null is +1035 * returned. +1036 * +1037 * @return the database driver name if specified; otherwise null is returned +1038 */ +1039 public String getDatabaseDriverPath() { +1040 return line.getOptionValue(ARGUMENT.DB_DRIVER_PATH); +1041 } +1042 +1043 /** +1044 * Returns the database connection string if specified; otherwise null is +1045 * returned. +1046 * +1047 * @return the database connection string if specified; otherwise null is +1048 * returned +1049 */ +1050 public String getConnectionString() { +1051 return line.getOptionValue(ARGUMENT.CONNECTION_STRING); +1052 } +1053 +1054 /** +1055 * Returns the database database user name if specified; otherwise null is +1056 * returned. +1057 * +1058 * @return the database database user name if specified; otherwise null is +1059 * returned +1060 */ +1061 public String getDatabaseUser() { +1062 return line.getOptionValue(ARGUMENT.DB_NAME); +1063 } +1064 +1065 /** +1066 * Returns the database database password if specified; otherwise null is +1067 * returned. +1068 * +1069 * @return the database database password if specified; otherwise null is +1070 * returned +1071 */ +1072 public String getDatabasePassword() { +1073 return line.getOptionValue(ARGUMENT.DB_PASSWORD); +1074 } +1075 +1076 /** +1077 * Returns the additional Extensions if specified; otherwise null is +1078 * returned. +1079 * +1080 * @return the additional Extensions; otherwise null is returned +1081 */ +1082 public String getAdditionalZipExtensions() { +1083 return line.getOptionValue(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS); +1084 } +1085 +1086 /** +1087 * Get the value of cveValidForHours. +1088 * +1089 * @return the value of cveValidForHours +1090 */ +1091 public Integer getCveValidForHours() { +1092 final String v = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS); +1093 if (v != null) { +1094 return Integer.parseInt(v); +1095 } +1096 return null; +1097 } +1098 +1099 /** +1100 * Returns true if the experimental analyzers are enabled. +1101 * +1102 * @return true if the experimental analyzers are enabled; otherwise false +1103 */ +1104 public boolean isExperimentalEnabled() { +1105 return line.hasOption(ARGUMENT.EXPERIMENTAL); +1106 } +1107 +1108 /** +1109 * A collection of static final strings that represent the possible command +1110 * line arguments. +1111 */ +1112 public static class ARGUMENT { +1113 +1114 /** +1115 * The long CLI argument name specifying the directory/file to scan. 1116 */ -1117 public static final String DISABLE_AUTO_UPDATE_SHORT = "n"; +1117 public static final String SCAN = "scan"; 1118 /** -1119 * The long CLI argument name specifying that only the update phase -1120 * should be executed; no scan should be run. -1121 */ -1122 public static final String UPDATE_ONLY = "updateonly"; -1123 /** -1124 * The long CLI argument name specifying that only the update phase -1125 * should be executed; no scan should be run. -1126 */ -1127 public static final String PURGE_NVD = "purge"; -1128 /** -1129 * The long CLI argument name specifying the directory to write the -1130 * reports to. -1131 */ -1132 public static final String OUT = "out"; -1133 /** -1134 * The short CLI argument name specifying the directory to write the -1135 * reports to. -1136 */ -1137 public static final String OUT_SHORT = "o"; -1138 /** -1139 * The long CLI argument name specifying the output format to write the -1140 * reports to. -1141 */ -1142 public static final String OUTPUT_FORMAT = "format"; -1143 /** -1144 * The short CLI argument name specifying the output format to write the -1145 * reports to. -1146 */ -1147 public static final String OUTPUT_FORMAT_SHORT = "f"; -1148 /** -1149 * The long CLI argument name specifying the name of the project to be -1150 * scanned. -1151 */ -1152 public static final String PROJECT = "project"; -1153 /** -1154 * The long CLI argument name specifying the name of the application to -1155 * be scanned. -1156 * -1157 * @deprecated project should be used instead -1158 */ -1159 @Deprecated -1160 public static final String APP_NAME = "app"; -1161 /** -1162 * The short CLI argument name specifying the name of the application to -1163 * be scanned. -1164 * -1165 * @deprecated project should be used instead -1166 */ -1167 @Deprecated -1168 public static final String APP_NAME_SHORT = "a"; -1169 /** -1170 * The long CLI argument name asking for help. -1171 */ -1172 public static final String HELP = "help"; -1173 /** -1174 * The long CLI argument name asking for advanced help. -1175 */ -1176 public static final String ADVANCED_HELP = "advancedHelp"; -1177 /** -1178 * The short CLI argument name asking for help. -1179 */ -1180 public static final String HELP_SHORT = "h"; -1181 /** -1182 * The long CLI argument name asking for the version. -1183 */ -1184 public static final String VERSION_SHORT = "v"; -1185 /** -1186 * The short CLI argument name asking for the version. -1187 */ -1188 public static final String VERSION = "version"; -1189 /** -1190 * The CLI argument name indicating the proxy port. -1191 */ -1192 public static final String PROXY_PORT = "proxyport"; -1193 /** -1194 * The CLI argument name indicating the proxy server. -1195 */ -1196 public static final String PROXY_SERVER = "proxyserver"; -1197 /** -1198 * The CLI argument name indicating the proxy url. -1199 * -1200 * @deprecated use {@link #PROXY_SERVER} instead +1119 * The short CLI argument name specifying the directory/file to scan. +1120 */ +1121 public static final String SCAN_SHORT = "s"; +1122 /** +1123 * The long CLI argument name specifying that the CPE/CVE/etc. data +1124 * should not be automatically updated. +1125 */ +1126 public static final String DISABLE_AUTO_UPDATE = "noupdate"; +1127 /** +1128 * The short CLI argument name specifying that the CPE/CVE/etc. data +1129 * should not be automatically updated. +1130 */ +1131 public static final String DISABLE_AUTO_UPDATE_SHORT = "n"; +1132 /** +1133 * The long CLI argument name specifying that only the update phase +1134 * should be executed; no scan should be run. +1135 */ +1136 public static final String UPDATE_ONLY = "updateonly"; +1137 /** +1138 * The long CLI argument name specifying that only the update phase +1139 * should be executed; no scan should be run. +1140 */ +1141 public static final String PURGE_NVD = "purge"; +1142 /** +1143 * The long CLI argument name specifying the directory to write the +1144 * reports to. +1145 */ +1146 public static final String OUT = "out"; +1147 /** +1148 * The short CLI argument name specifying the directory to write the +1149 * reports to. +1150 */ +1151 public static final String OUT_SHORT = "o"; +1152 /** +1153 * The long CLI argument name specifying the output format to write the +1154 * reports to. +1155 */ +1156 public static final String OUTPUT_FORMAT = "format"; +1157 /** +1158 * The short CLI argument name specifying the output format to write the +1159 * reports to. +1160 */ +1161 public static final String OUTPUT_FORMAT_SHORT = "f"; +1162 /** +1163 * The long CLI argument name specifying the name of the project to be +1164 * scanned. +1165 */ +1166 public static final String PROJECT = "project"; +1167 /** +1168 * The long CLI argument name specifying the name of the application to +1169 * be scanned. +1170 * +1171 * @deprecated project should be used instead +1172 */ +1173 @Deprecated +1174 public static final String APP_NAME = "app"; +1175 /** +1176 * The short CLI argument name specifying the name of the application to +1177 * be scanned. +1178 * +1179 * @deprecated project should be used instead +1180 */ +1181 @Deprecated +1182 public static final String APP_NAME_SHORT = "a"; +1183 /** +1184 * The long CLI argument name asking for help. +1185 */ +1186 public static final String HELP = "help"; +1187 /** +1188 * The long CLI argument name asking for advanced help. +1189 */ +1190 public static final String ADVANCED_HELP = "advancedHelp"; +1191 /** +1192 * The short CLI argument name asking for help. +1193 */ +1194 public static final String HELP_SHORT = "h"; +1195 /** +1196 * The long CLI argument name asking for the version. +1197 */ +1198 public static final String VERSION_SHORT = "v"; +1199 /** +1200 * The short CLI argument name asking for the version. 1201 */ -1202 @Deprecated -1203 public static final String PROXY_URL = "proxyurl"; -1204 /** -1205 * The CLI argument name indicating the proxy username. -1206 */ -1207 public static final String PROXY_USERNAME = "proxyuser"; -1208 /** -1209 * The CLI argument name indicating the proxy password. -1210 */ -1211 public static final String PROXY_PASSWORD = "proxypass"; -1212 /** -1213 * The short CLI argument name indicating the connection timeout. -1214 */ -1215 public static final String CONNECTION_TIMEOUT_SHORT = "c"; -1216 /** -1217 * The CLI argument name indicating the connection timeout. -1218 */ -1219 public static final String CONNECTION_TIMEOUT = "connectiontimeout"; -1220 /** -1221 * The short CLI argument name for setting the location of an additional -1222 * properties file. -1223 */ -1224 public static final String PROP_SHORT = "P"; -1225 /** -1226 * The CLI argument name for setting the location of an additional -1227 * properties file. +1202 public static final String VERSION = "version"; +1203 /** +1204 * The CLI argument name indicating the proxy port. +1205 */ +1206 public static final String PROXY_PORT = "proxyport"; +1207 /** +1208 * The CLI argument name indicating the proxy server. +1209 */ +1210 public static final String PROXY_SERVER = "proxyserver"; +1211 /** +1212 * The CLI argument name indicating the proxy url. +1213 * +1214 * @deprecated use {@link #PROXY_SERVER} instead +1215 */ +1216 @Deprecated +1217 public static final String PROXY_URL = "proxyurl"; +1218 /** +1219 * The CLI argument name indicating the proxy username. +1220 */ +1221 public static final String PROXY_USERNAME = "proxyuser"; +1222 /** +1223 * The CLI argument name indicating the proxy password. +1224 */ +1225 public static final String PROXY_PASSWORD = "proxypass"; +1226 /** +1227 * The short CLI argument name indicating the connection timeout. 1228 */ -1229 public static final String PROP = "propertyfile"; +1229 public static final String CONNECTION_TIMEOUT_SHORT = "c"; 1230 /** -1231 * The CLI argument name for setting the location of the data directory. +1231 * The CLI argument name indicating the connection timeout. 1232 */ -1233 public static final String DATA_DIRECTORY = "data"; +1233 public static final String CONNECTION_TIMEOUT = "connectiontimeout"; 1234 /** -1235 * The CLI argument name for setting the URL for the CVE Data Files. -1236 */ -1237 public static final String CVE_MOD_12 = "cveUrl12Modified"; -1238 /** -1239 * The CLI argument name for setting the URL for the CVE Data Files. -1240 */ -1241 public static final String CVE_MOD_20 = "cveUrl20Modified"; -1242 /** -1243 * The CLI argument name for setting the URL for the CVE Data Files. -1244 */ -1245 public static final String CVE_BASE_12 = "cveUrl12Base"; -1246 /** -1247 * The CLI argument name for setting the URL for the CVE Data Files. -1248 */ -1249 public static final String CVE_BASE_20 = "cveUrl20Base"; -1250 /** -1251 * The short CLI argument name for setting the location of the data -1252 * directory. -1253 */ -1254 public static final String DATA_DIRECTORY_SHORT = "d"; -1255 /** -1256 * The CLI argument name for setting the location of the data directory. -1257 */ -1258 public static final String VERBOSE_LOG = "log"; -1259 /** -1260 * The short CLI argument name for setting the location of the data -1261 * directory. +1235 * The short CLI argument name for setting the location of an additional +1236 * properties file. +1237 */ +1238 public static final String PROP_SHORT = "P"; +1239 /** +1240 * The CLI argument name for setting the location of an additional +1241 * properties file. +1242 */ +1243 public static final String PROP = "propertyfile"; +1244 /** +1245 * The CLI argument name for setting the location of the data directory. +1246 */ +1247 public static final String DATA_DIRECTORY = "data"; +1248 /** +1249 * The CLI argument name for setting the URL for the CVE Data Files. +1250 */ +1251 public static final String CVE_MOD_12 = "cveUrl12Modified"; +1252 /** +1253 * The CLI argument name for setting the URL for the CVE Data Files. +1254 */ +1255 public static final String CVE_MOD_20 = "cveUrl20Modified"; +1256 /** +1257 * The CLI argument name for setting the URL for the CVE Data Files. +1258 */ +1259 public static final String CVE_BASE_12 = "cveUrl12Base"; +1260 /** +1261 * The CLI argument name for setting the URL for the CVE Data Files. 1262 */ -1263 public static final String VERBOSE_LOG_SHORT = "l"; -1264 -1265 /** -1266 * The CLI argument name for setting the depth of symbolic links that -1267 * will be followed. -1268 */ -1269 public static final String SYM_LINK_DEPTH = "symLink"; -1270 /** -1271 * The CLI argument name for setting the location of the suppression -1272 * file. -1273 */ -1274 public static final String SUPPRESSION_FILE = "suppression"; -1275 /** -1276 * The CLI argument name for setting the location of the suppression -1277 * file. -1278 */ -1279 public static final String CVE_VALID_FOR_HOURS = "cveValidForHours"; -1280 /** -1281 * Disables the Jar Analyzer. +1263 public static final String CVE_BASE_20 = "cveUrl20Base"; +1264 /** +1265 * The short CLI argument name for setting the location of the data +1266 * directory. +1267 */ +1268 public static final String DATA_DIRECTORY_SHORT = "d"; +1269 /** +1270 * The CLI argument name for setting the location of the data directory. +1271 */ +1272 public static final String VERBOSE_LOG = "log"; +1273 /** +1274 * The short CLI argument name for setting the location of the data +1275 * directory. +1276 */ +1277 public static final String VERBOSE_LOG_SHORT = "l"; +1278 +1279 /** +1280 * The CLI argument name for setting the depth of symbolic links that +1281 * will be followed. 1282 */ -1283 public static final String DISABLE_JAR = "disableJar"; +1283 public static final String SYM_LINK_DEPTH = "symLink"; 1284 /** -1285 * Disables the Archive Analyzer. -1286 */ -1287 public static final String DISABLE_ARCHIVE = "disableArchive"; -1288 /** -1289 * Disables the Python Distribution Analyzer. -1290 */ -1291 public static final String DISABLE_PY_DIST = "disablePyDist"; -1292 /** -1293 * Disables the Python Package Analyzer. -1294 */ -1295 public static final String DISABLE_PY_PKG = "disablePyPkg"; -1296 /** -1297 * Disables the Python Package Analyzer. -1298 */ -1299 public static final String DISABLE_COMPOSER = "disableComposer"; -1300 /** -1301 * Disables the Ruby Gemspec Analyzer. -1302 */ -1303 public static final String DISABLE_RUBYGEMS = "disableRubygems"; -1304 /** -1305 * Disables the Autoconf Analyzer. -1306 */ -1307 public static final String DISABLE_AUTOCONF = "disableAutoconf"; -1308 /** -1309 * Disables the Cmake Analyzer. -1310 */ -1311 public static final String DISABLE_CMAKE = "disableCmake"; -1312 /** -1313 * Disables the Assembly Analyzer. -1314 */ -1315 public static final String DISABLE_ASSEMBLY = "disableAssembly"; -1316 /** -1317 * Disables the Ruby Bundler Audit Analyzer. -1318 */ -1319 public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit"; -1320 /** -1321 * Disables the Nuspec Analyzer. -1322 */ -1323 public static final String DISABLE_NUSPEC = "disableNuspec"; -1324 /** -1325 * Disables the Central Analyzer. -1326 */ -1327 public static final String DISABLE_CENTRAL = "disableCentral"; -1328 /** -1329 * Disables the Nexus Analyzer. -1330 */ -1331 public static final String DISABLE_NEXUS = "disableNexus"; -1332 /** -1333 * Disables the OpenSSL Analyzer. -1334 */ -1335 public static final String DISABLE_OPENSSL = "disableOpenSSL"; -1336 /** -1337 * Disables the Node.js Package Analyzer. -1338 */ -1339 public static final String DISABLE_NODE_JS = "disableNodeJS"; -1340 /** -1341 * The URL of the nexus server. -1342 */ -1343 public static final String NEXUS_URL = "nexus"; -1344 /** -1345 * Whether or not the defined proxy should be used when connecting to -1346 * Nexus. -1347 */ -1348 public static final String NEXUS_USES_PROXY = "nexusUsesProxy"; -1349 /** -1350 * The CLI argument name for setting the connection string. -1351 */ -1352 public static final String CONNECTION_STRING = "connectionString"; -1353 /** -1354 * The CLI argument name for setting the database user name. -1355 */ -1356 public static final String DB_NAME = "dbUser"; -1357 /** -1358 * The CLI argument name for setting the database password. -1359 */ -1360 public static final String DB_PASSWORD = "dbPassword"; -1361 /** -1362 * The CLI argument name for setting the database driver name. -1363 */ -1364 public static final String DB_DRIVER = "dbDriverName"; -1365 /** -1366 * The CLI argument name for setting the path to the database driver; in -1367 * case it is not on the class path. -1368 */ -1369 public static final String DB_DRIVER_PATH = "dbDriverPath"; -1370 /** -1371 * The CLI argument name for setting the path to mono for .NET Assembly -1372 * analysis on non-windows systems. -1373 */ -1374 public static final String PATH_TO_MONO = "mono"; -1375 /** -1376 * The CLI argument name for setting extra extensions. -1377 */ -1378 public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions"; -1379 /** -1380 * Exclude path argument. -1381 */ -1382 public static final String EXCLUDE = "exclude"; -1383 /** -1384 * The CLI argument name for setting the path to bundle-audit for Ruby -1385 * bundle analysis. -1386 */ -1387 public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit"; -1388 /** -1389 * The CLI argument to enable the experimental analyzers. -1390 */ -1391 private static final String EXPERIMENTAL = "enableExperimental"; -1392 } -1393 } +1285 * The CLI argument name for setting the location of the suppression +1286 * file. +1287 */ +1288 public static final String SUPPRESSION_FILE = "suppression"; +1289 /** +1290 * The CLI argument name for setting the location of the hint +1291 * file. +1292 */ +1293 public static final String HINTS_FILE = "hints"; +1294 /** +1295 * The CLI argument name for setting the number of hours to wait before +1296 * checking for new updates from the NVD. +1297 */ +1298 public static final String CVE_VALID_FOR_HOURS = "cveValidForHours"; +1299 /** +1300 * Disables the Jar Analyzer. +1301 */ +1302 public static final String DISABLE_JAR = "disableJar"; +1303 /** +1304 * Disables the Archive Analyzer. +1305 */ +1306 public static final String DISABLE_ARCHIVE = "disableArchive"; +1307 /** +1308 * Disables the Python Distribution Analyzer. +1309 */ +1310 public static final String DISABLE_PY_DIST = "disablePyDist"; +1311 /** +1312 * Disables the Python Package Analyzer. +1313 */ +1314 public static final String DISABLE_PY_PKG = "disablePyPkg"; +1315 /** +1316 * Disables the Python Package Analyzer. +1317 */ +1318 public static final String DISABLE_COMPOSER = "disableComposer"; +1319 /** +1320 * Disables the Ruby Gemspec Analyzer. +1321 */ +1322 public static final String DISABLE_RUBYGEMS = "disableRubygems"; +1323 /** +1324 * Disables the Autoconf Analyzer. +1325 */ +1326 public static final String DISABLE_AUTOCONF = "disableAutoconf"; +1327 /** +1328 * Disables the Cmake Analyzer. +1329 */ +1330 public static final String DISABLE_CMAKE = "disableCmake"; +1331 /** +1332 * Disables the Assembly Analyzer. +1333 */ +1334 public static final String DISABLE_ASSEMBLY = "disableAssembly"; +1335 /** +1336 * Disables the Ruby Bundler Audit Analyzer. +1337 */ +1338 public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit"; +1339 /** +1340 * Disables the Nuspec Analyzer. +1341 */ +1342 public static final String DISABLE_NUSPEC = "disableNuspec"; +1343 /** +1344 * Disables the Central Analyzer. +1345 */ +1346 public static final String DISABLE_CENTRAL = "disableCentral"; +1347 /** +1348 * Disables the Nexus Analyzer. +1349 */ +1350 public static final String DISABLE_NEXUS = "disableNexus"; +1351 /** +1352 * Disables the OpenSSL Analyzer. +1353 */ +1354 public static final String DISABLE_OPENSSL = "disableOpenSSL"; +1355 /** +1356 * Disables the Node.js Package Analyzer. +1357 */ +1358 public static final String DISABLE_NODE_JS = "disableNodeJS"; +1359 /** +1360 * The URL of the nexus server. +1361 */ +1362 public static final String NEXUS_URL = "nexus"; +1363 /** +1364 * Whether or not the defined proxy should be used when connecting to +1365 * Nexus. +1366 */ +1367 public static final String NEXUS_USES_PROXY = "nexusUsesProxy"; +1368 /** +1369 * The CLI argument name for setting the connection string. +1370 */ +1371 public static final String CONNECTION_STRING = "connectionString"; +1372 /** +1373 * The CLI argument name for setting the database user name. +1374 */ +1375 public static final String DB_NAME = "dbUser"; +1376 /** +1377 * The CLI argument name for setting the database password. +1378 */ +1379 public static final String DB_PASSWORD = "dbPassword"; +1380 /** +1381 * The CLI argument name for setting the database driver name. +1382 */ +1383 public static final String DB_DRIVER = "dbDriverName"; +1384 /** +1385 * The CLI argument name for setting the path to the database driver; in +1386 * case it is not on the class path. +1387 */ +1388 public static final String DB_DRIVER_PATH = "dbDriverPath"; +1389 /** +1390 * The CLI argument name for setting the path to mono for .NET Assembly +1391 * analysis on non-windows systems. +1392 */ +1393 public static final String PATH_TO_MONO = "mono"; +1394 /** +1395 * The CLI argument name for setting extra extensions. +1396 */ +1397 public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions"; +1398 /** +1399 * Exclude path argument. +1400 */ +1401 public static final String EXCLUDE = "exclude"; +1402 /** +1403 * The CLI argument name for setting the path to bundle-audit for Ruby +1404 * bundle analysis. +1405 */ +1406 public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit"; +1407 /** +1408 * The CLI argument to enable the experimental analyzers. +1409 */ +1410 private static final String EXPERIMENTAL = "enableExperimental"; +1411 } +1412 }
      diff --git a/xref/org/owasp/dependencycheck/Engine.html b/xref/org/owasp/dependencycheck/Engine.html index e4cd6cf99..587799cf5 100644 --- a/xref/org/owasp/dependencycheck/Engine.html +++ b/xref/org/owasp/dependencycheck/Engine.html @@ -29,546 +29,758 @@ 21 import org.owasp.dependencycheck.analyzer.Analyzer; 22 import org.owasp.dependencycheck.analyzer.AnalyzerService; 23 import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer; -24 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -25 import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory; -26 import org.owasp.dependencycheck.data.nvdcve.CveDB; -27 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -28 import org.owasp.dependencycheck.data.update.CachedWebDataSource; -29 import org.owasp.dependencycheck.data.update.UpdateService; -30 import org.owasp.dependencycheck.data.update.exception.UpdateException; -31 import org.owasp.dependencycheck.dependency.Dependency; -32 import org.owasp.dependencycheck.exception.NoDataException; -33 import org.owasp.dependencycheck.exception.ExceptionCollection; -34 import org.owasp.dependencycheck.exception.InitializationException; -35 import org.owasp.dependencycheck.utils.InvalidSettingException; -36 import org.owasp.dependencycheck.utils.Settings; -37 import org.slf4j.Logger; -38 import org.slf4j.LoggerFactory; -39 -40 import java.io.File; -41 import java.io.FileFilter; -42 import java.util.ArrayList; -43 import java.util.Collection; +24 import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory; +25 import org.owasp.dependencycheck.data.nvdcve.CveDB; +26 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +27 import org.owasp.dependencycheck.data.update.CachedWebDataSource; +28 import org.owasp.dependencycheck.data.update.UpdateService; +29 import org.owasp.dependencycheck.data.update.exception.UpdateException; +30 import org.owasp.dependencycheck.dependency.Dependency; +31 import org.owasp.dependencycheck.exception.ExceptionCollection; +32 import org.owasp.dependencycheck.exception.InitializationException; +33 import org.owasp.dependencycheck.exception.NoDataException; +34 import org.owasp.dependencycheck.utils.InvalidSettingException; +35 import org.owasp.dependencycheck.utils.Settings; +36 import org.slf4j.Logger; +37 import org.slf4j.LoggerFactory; +38 +39 import java.io.File; +40 import java.io.FileFilter; +41 import java.util.ArrayList; +42 import java.util.Collection; +43 import java.util.Collections; 44 import java.util.EnumMap; 45 import java.util.HashSet; 46 import java.util.Iterator; 47 import java.util.List; 48 import java.util.Map; 49 import java.util.Set; -50 -51 /** -52 * Scans files, directories, etc. for Dependencies. Analyzers are loaded and -53 * used to process the files found by the scan, if a file is encountered and an -54 * Analyzer is associated with the file type then the file is turned into a -55 * dependency. -56 * -57 * @author Jeremy Long -58 */ -59 public class Engine implements FileFilter { -60 -61 /** -62 * The list of dependencies. -63 */ -64 private List<Dependency> dependencies = new ArrayList<Dependency>(); -65 /** -66 * A Map of analyzers grouped by Analysis phase. -67 */ -68 private final Map<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class); -69 -70 /** -71 * A Map of analyzers grouped by Analysis phase. -72 */ -73 private final Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>(); -74 -75 /** -76 * The ClassLoader to use when dynamically loading Analyzer and Update -77 * services. +50 import java.util.concurrent.CancellationException; +51 import java.util.concurrent.ExecutionException; +52 import java.util.concurrent.ExecutorService; +53 import java.util.concurrent.Executors; +54 import java.util.concurrent.Future; +55 import java.util.concurrent.TimeUnit; +56 +57 /** +58 * Scans files, directories, etc. for Dependencies. Analyzers are loaded and +59 * used to process the files found by the scan, if a file is encountered and an +60 * Analyzer is associated with the file type then the file is turned into a +61 * dependency. +62 * +63 * @author Jeremy Long +64 */ +65 public class Engine implements FileFilter { +66 +67 /** +68 * The list of dependencies. +69 */ +70 private final List<Dependency> dependencies = Collections.synchronizedList(new ArrayList<Dependency>()); +71 /** +72 * A Map of analyzers grouped by Analysis phase. +73 */ +74 private final Map<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class); +75 +76 /** +77 * A Map of analyzers grouped by Analysis phase. 78 */ -79 private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader(); -80 /** -81 * The Logger for use throughout the class. -82 */ -83 private static final Logger LOGGER = LoggerFactory.getLogger(Engine.class); -84 -85 /** -86 * Creates a new Engine. -87 * -88 * @throws DatabaseException thrown if there is an error connecting to the -89 * database -90 */ -91 public Engine() throws DatabaseException { -92 initializeEngine(); -93 } -94 -95 /** -96 * Creates a new Engine. -97 * -98 * @param serviceClassLoader a reference the class loader being used -99 * @throws DatabaseException thrown if there is an error connecting to the -100 * database -101 */ -102 public Engine(ClassLoader serviceClassLoader) throws DatabaseException { -103 this.serviceClassLoader = serviceClassLoader; -104 initializeEngine(); -105 } -106 -107 /** -108 * Creates a new Engine using the specified classloader to dynamically load -109 * Analyzer and Update services. -110 * -111 * @throws DatabaseException thrown if there is an error connecting to the -112 * database -113 */ -114 protected final void initializeEngine() throws DatabaseException { -115 ConnectionFactory.initialize(); -116 loadAnalyzers(); -117 } -118 -119 /** -120 * Properly cleans up resources allocated during analysis. -121 */ -122 public void cleanup() { -123 ConnectionFactory.cleanup(); -124 } -125 -126 /** -127 * Loads the analyzers specified in the configuration file (or system -128 * properties). -129 */ -130 private void loadAnalyzers() { -131 if (!analyzers.isEmpty()) { -132 return; -133 } -134 for (AnalysisPhase phase : AnalysisPhase.values()) { -135 analyzers.put(phase, new ArrayList<Analyzer>()); -136 } -137 -138 final AnalyzerService service = new AnalyzerService(serviceClassLoader); -139 final List<Analyzer> iterator = service.getAnalyzers(); -140 for (Analyzer a : iterator) { -141 analyzers.get(a.getAnalysisPhase()).add(a); -142 if (a instanceof FileTypeAnalyzer) { -143 this.fileTypeAnalyzers.add((FileTypeAnalyzer) a); -144 } -145 } -146 } -147 -148 /** -149 * Get the List of the analyzers for a specific phase of analysis. -150 * -151 * @param phase the phase to get the configured analyzers. -152 * @return the analyzers loaded -153 */ -154 public List<Analyzer> getAnalyzers(AnalysisPhase phase) { -155 return analyzers.get(phase); -156 } -157 -158 /** -159 * Get the dependencies identified. -160 * -161 * @return the dependencies identified -162 */ -163 public List<Dependency> getDependencies() { -164 return dependencies; -165 } -166 -167 /** -168 * Sets the dependencies. +79 private final Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>(); +80 +81 /** +82 * The ClassLoader to use when dynamically loading Analyzer and Update +83 * services. +84 */ +85 private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader(); +86 /** +87 * The Logger for use throughout the class. +88 */ +89 private static final Logger LOGGER = LoggerFactory.getLogger(Engine.class); +90 +91 /** +92 * Creates a new Engine. +93 * +94 * @throws DatabaseException thrown if there is an error connecting to the +95 * database +96 */ +97 public Engine() throws DatabaseException { +98 initializeEngine(); +99 } +100 +101 /** +102 * Creates a new Engine. +103 * +104 * @param serviceClassLoader a reference the class loader being used +105 * @throws DatabaseException thrown if there is an error connecting to the +106 * database +107 */ +108 public Engine(ClassLoader serviceClassLoader) throws DatabaseException { +109 this.serviceClassLoader = serviceClassLoader; +110 initializeEngine(); +111 } +112 +113 /** +114 * Creates a new Engine using the specified classloader to dynamically load +115 * Analyzer and Update services. +116 * +117 * @throws DatabaseException thrown if there is an error connecting to the +118 * database +119 */ +120 protected final void initializeEngine() throws DatabaseException { +121 ConnectionFactory.initialize(); +122 loadAnalyzers(); +123 } +124 +125 /** +126 * Properly cleans up resources allocated during analysis. +127 */ +128 public void cleanup() { +129 ConnectionFactory.cleanup(); +130 } +131 +132 /** +133 * Loads the analyzers specified in the configuration file (or system +134 * properties). +135 */ +136 private void loadAnalyzers() { +137 if (!analyzers.isEmpty()) { +138 return; +139 } +140 for (AnalysisPhase phase : AnalysisPhase.values()) { +141 analyzers.put(phase, new ArrayList<Analyzer>()); +142 } +143 +144 final AnalyzerService service = new AnalyzerService(serviceClassLoader); +145 final List<Analyzer> iterator = service.getAnalyzers(); +146 for (Analyzer a : iterator) { +147 analyzers.get(a.getAnalysisPhase()).add(a); +148 if (a instanceof FileTypeAnalyzer) { +149 this.fileTypeAnalyzers.add((FileTypeAnalyzer) a); +150 } +151 } +152 } +153 +154 /** +155 * Get the List of the analyzers for a specific phase of analysis. +156 * +157 * @param phase the phase to get the configured analyzers. +158 * @return the analyzers loaded +159 */ +160 public List<Analyzer> getAnalyzers(AnalysisPhase phase) { +161 return analyzers.get(phase); +162 } +163 +164 /** +165 * Get the dependencies identified. The returned list is a reference to the +166 * engine's synchronized list. You must synchronize on it, when you modify +167 * and iterate over it from multiple threads. E.g. this holds for analyzers +168 * supporting parallel processing during their analysis phase. 169 * -170 * @param dependencies the dependencies -171 */ -172 public void setDependencies(List<Dependency> dependencies) { -173 this.dependencies = dependencies; -174 } -175 -176 /** -177 * Scans an array of files or directories. If a directory is specified, it -178 * will be scanned recursively. Any dependencies identified are added to the -179 * dependency collection. +170 * @return the dependencies identified +171 * @see Collections#synchronizedList(List) +172 * @see Analyzer#supportsParallelProcessing() +173 */ +174 public List<Dependency> getDependencies() { +175 return dependencies; +176 } +177 +178 /** +179 * Sets the dependencies. 180 * -181 * @param paths an array of paths to files or directories to be analyzed -182 * @return the list of dependencies scanned -183 * @since v0.3.2.5 -184 */ -185 public List<Dependency> scan(String[] paths) { -186 final List<Dependency> deps = new ArrayList<Dependency>(); -187 for (String path : paths) { -188 final List<Dependency> d = scan(path); -189 if (d != null) { -190 deps.addAll(d); -191 } -192 } -193 return deps; -194 } -195 -196 /** -197 * Scans a given file or directory. If a directory is specified, it will be -198 * scanned recursively. Any dependencies identified are added to the -199 * dependency collection. -200 * -201 * @param path the path to a file or directory to be analyzed -202 * @return the list of dependencies scanned -203 */ -204 public List<Dependency> scan(String path) { -205 final File file = new File(path); -206 return scan(file); -207 } -208 -209 /** -210 * Scans an array of files or directories. If a directory is specified, it -211 * will be scanned recursively. Any dependencies identified are added to the -212 * dependency collection. -213 * -214 * @param files an array of paths to files or directories to be analyzed. -215 * @return the list of dependencies -216 * @since v0.3.2.5 -217 */ -218 public List<Dependency> scan(File[] files) { -219 final List<Dependency> deps = new ArrayList<Dependency>(); -220 for (File file : files) { -221 final List<Dependency> d = scan(file); -222 if (d != null) { -223 deps.addAll(d); -224 } -225 } -226 return deps; -227 } -228 -229 /** -230 * Scans a collection of files or directories. If a directory is specified, -231 * it will be scanned recursively. Any dependencies identified are added to -232 * the dependency collection. -233 * -234 * @param files a set of paths to files or directories to be analyzed -235 * @return the list of dependencies scanned -236 * @since v0.3.2.5 -237 */ -238 public List<Dependency> scan(Collection<File> files) { -239 final List<Dependency> deps = new ArrayList<Dependency>(); -240 for (File file : files) { -241 final List<Dependency> d = scan(file); -242 if (d != null) { -243 deps.addAll(d); -244 } -245 } -246 return deps; -247 } -248 -249 /** -250 * Scans a given file or directory. If a directory is specified, it will be -251 * scanned recursively. Any dependencies identified are added to the -252 * dependency collection. -253 * -254 * @param file the path to a file or directory to be analyzed -255 * @return the list of dependencies scanned -256 * @since v0.3.2.4 -257 */ -258 public List<Dependency> scan(File file) { -259 if (file.exists()) { -260 if (file.isDirectory()) { -261 return scanDirectory(file); -262 } else { -263 final Dependency d = scanFile(file); -264 if (d != null) { -265 final List<Dependency> deps = new ArrayList<Dependency>(); -266 deps.add(d); -267 return deps; -268 } -269 } -270 } -271 return null; -272 } -273 -274 /** -275 * Recursively scans files and directories. Any dependencies identified are -276 * added to the dependency collection. -277 * -278 * @param dir the directory to scan -279 * @return the list of Dependency objects scanned -280 */ -281 protected List<Dependency> scanDirectory(File dir) { -282 final File[] files = dir.listFiles(); -283 final List<Dependency> deps = new ArrayList<Dependency>(); -284 if (files != null) { -285 for (File f : files) { -286 if (f.isDirectory()) { -287 final List<Dependency> d = scanDirectory(f); -288 if (d != null) { -289 deps.addAll(d); -290 } -291 } else { -292 final Dependency d = scanFile(f); -293 deps.add(d); -294 } -295 } -296 } -297 return deps; -298 } -299 -300 /** -301 * Scans a specified file. If a dependency is identified it is added to the -302 * dependency collection. -303 * -304 * @param file The file to scan -305 * @return the scanned dependency -306 */ -307 protected Dependency scanFile(File file) { -308 Dependency dependency = null; -309 if (file.isFile()) { -310 if (accept(file)) { -311 dependency = new Dependency(file); -312 dependencies.add(dependency); -313 } -314 } else { -315 LOGGER.debug("Path passed to scanFile(File) is not a file: {}. Skipping the file.", file); -316 } -317 return dependency; -318 } -319 -320 /** -321 * Runs the analyzers against all of the dependencies. Since the mutable -322 * dependencies list is exposed via {@link #getDependencies()}, this method -323 * iterates over a copy of the dependencies list. Thus, the potential for -324 * {@link java.util.ConcurrentModificationException}s is avoided, and -325 * analyzers may safely add or remove entries from the dependencies list. -326 * -327 * Every effort is made to complete analysis on the dependencies. In some -328 * cases an exception will occur with part of the analysis being performed -329 * which may not affect the entire analysis. If an exception occurs it will -330 * be included in the thrown exception collection. -331 * -332 * @throws ExceptionCollection a collections of any exceptions that occurred -333 * during analysis -334 */ -335 public void analyzeDependencies() throws ExceptionCollection { -336 final List<Throwable> exceptions = new ArrayList<Throwable>(); -337 boolean autoUpdate = true; -338 try { -339 autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); -340 } catch (InvalidSettingException ex) { -341 LOGGER.debug("Invalid setting for auto-update; using true."); -342 exceptions.add(ex); -343 } -344 if (autoUpdate) { -345 try { -346 doUpdates(); -347 } catch (UpdateException ex) { -348 exceptions.add(ex); -349 LOGGER.warn("Unable to update Cached Web DataSource, using local " -350 + "data instead. Results may not include recent vulnerabilities."); -351 LOGGER.debug("Update Error", ex); -352 } -353 } -354 -355 //need to ensure that data exists -356 try { -357 ensureDataExists(); -358 } catch (NoDataException ex) { -359 LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage()); -360 LOGGER.debug("", ex); -361 exceptions.add(ex); -362 throw new ExceptionCollection("Unable to continue dependency-check analysis.", exceptions, true); -363 } catch (DatabaseException ex) { -364 LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage()); -365 LOGGER.debug("", ex); -366 exceptions.add(ex); -367 throw new ExceptionCollection("Unable to connect to the dependency-check database", exceptions, true); -368 } -369 -370 LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------"); -371 LOGGER.info("Analysis Started"); -372 final long analysisStart = System.currentTimeMillis(); +181 * @param dependencies the dependencies +182 */ +183 public void setDependencies(List<Dependency> dependencies) { +184 synchronized (this.dependencies) { +185 this.dependencies.clear(); +186 this.dependencies.addAll(dependencies); +187 } +188 } +189 +190 /** +191 * Scans an array of files or directories. If a directory is specified, it +192 * will be scanned recursively. Any dependencies identified are added to the +193 * dependency collection. +194 * +195 * @param paths an array of paths to files or directories to be analyzed +196 * @return the list of dependencies scanned +197 * @since v0.3.2.5 +198 */ +199 public List<Dependency> scan(String[] paths) { +200 return scan(paths, null); +201 } +202 +203 /** +204 * Scans an array of files or directories. If a directory is specified, it +205 * will be scanned recursively. Any dependencies identified are added to the +206 * dependency collection. +207 * +208 * @param paths an array of paths to files or directories to be analyzed +209 * @param projectReference the name of the project or scope in which the +210 * dependency was identified +211 * @return the list of dependencies scanned +212 * @since v1.4.4 +213 */ +214 public List<Dependency> scan(String[] paths, String projectReference) { +215 final List<Dependency> deps = new ArrayList<Dependency>(); +216 for (String path : paths) { +217 final List<Dependency> d = scan(path, projectReference); +218 if (d != null) { +219 deps.addAll(d); +220 } +221 } +222 return deps; +223 } +224 +225 /** +226 * Scans a given file or directory. If a directory is specified, it will be +227 * scanned recursively. Any dependencies identified are added to the +228 * dependency collection. +229 * +230 * @param path the path to a file or directory to be analyzed +231 * @return the list of dependencies scanned +232 */ +233 public List<Dependency> scan(String path) { +234 return scan(path, null); +235 } +236 +237 /** +238 * Scans a given file or directory. If a directory is specified, it will be +239 * scanned recursively. Any dependencies identified are added to the +240 * dependency collection. +241 * +242 * @param path the path to a file or directory to be analyzed +243 * @param projectReference the name of the project or scope in which the +244 * dependency was identified +245 * @return the list of dependencies scanned +246 * @since v1.4.4 +247 */ +248 public List<Dependency> scan(String path, String projectReference) { +249 final File file = new File(path); +250 return scan(file, projectReference); +251 } +252 +253 /** +254 * Scans an array of files or directories. If a directory is specified, it +255 * will be scanned recursively. Any dependencies identified are added to the +256 * dependency collection. +257 * +258 * @param files an array of paths to files or directories to be analyzed. +259 * @return the list of dependencies +260 * @since v0.3.2.5 +261 */ +262 public List<Dependency> scan(File[] files) { +263 return scan(files, null); +264 } +265 +266 /** +267 * Scans an array of files or directories. If a directory is specified, it +268 * will be scanned recursively. Any dependencies identified are added to the +269 * dependency collection. +270 * +271 * @param files an array of paths to files or directories to be analyzed. +272 * @param projectReference the name of the project or scope in which the +273 * dependency was identified +274 * @return the list of dependencies +275 * @since v1.4.4 +276 */ +277 public List<Dependency> scan(File[] files, String projectReference) { +278 final List<Dependency> deps = new ArrayList<Dependency>(); +279 for (File file : files) { +280 final List<Dependency> d = scan(file, projectReference); +281 if (d != null) { +282 deps.addAll(d); +283 } +284 } +285 return deps; +286 } +287 +288 /** +289 * Scans a collection of files or directories. If a directory is specified, +290 * it will be scanned recursively. Any dependencies identified are added to +291 * the dependency collection. +292 * +293 * @param files a set of paths to files or directories to be analyzed +294 * @return the list of dependencies scanned +295 * @since v0.3.2.5 +296 */ +297 public List<Dependency> scan(Collection<File> files) { +298 return scan(files, null); +299 } +300 +301 /** +302 * Scans a collection of files or directories. If a directory is specified, +303 * it will be scanned recursively. Any dependencies identified are added to +304 * the dependency collection. +305 * +306 * @param files a set of paths to files or directories to be analyzed +307 * @param projectReference the name of the project or scope in which the +308 * dependency was identified +309 * @return the list of dependencies scanned +310 * @since v1.4.4 +311 */ +312 public List<Dependency> scan(Collection<File> files, String projectReference) { +313 final List<Dependency> deps = new ArrayList<Dependency>(); +314 for (File file : files) { +315 final List<Dependency> d = scan(file, projectReference); +316 if (d != null) { +317 deps.addAll(d); +318 } +319 } +320 return deps; +321 } +322 +323 /** +324 * Scans a given file or directory. If a directory is specified, it will be +325 * scanned recursively. Any dependencies identified are added to the +326 * dependency collection. +327 * +328 * @param file the path to a file or directory to be analyzed +329 * @return the list of dependencies scanned +330 * @since v0.3.2.4 +331 */ +332 public List<Dependency> scan(File file) { +333 return scan(file, null); +334 } +335 +336 /** +337 * Scans a given file or directory. If a directory is specified, it will be +338 * scanned recursively. Any dependencies identified are added to the +339 * dependency collection. +340 * +341 * @param file the path to a file or directory to be analyzed +342 * @param projectReference the name of the project or scope in which the +343 * dependency was identified +344 * @return the list of dependencies scanned +345 * @since v1.4.4 +346 */ +347 public List<Dependency> scan(File file, String projectReference) { +348 if (file.exists()) { +349 if (file.isDirectory()) { +350 return scanDirectory(file, projectReference); +351 } else { +352 final Dependency d = scanFile(file, projectReference); +353 if (d != null) { +354 final List<Dependency> deps = new ArrayList<Dependency>(); +355 deps.add(d); +356 return deps; +357 } +358 } +359 } +360 return null; +361 } +362 +363 /** +364 * Recursively scans files and directories. Any dependencies identified are +365 * added to the dependency collection. +366 * +367 * @param dir the directory to scan +368 * @return the list of Dependency objects scanned +369 */ +370 protected List<Dependency> scanDirectory(File dir) { +371 return scanDirectory(dir, null); +372 } 373 -374 // analysis phases -375 for (AnalysisPhase phase : AnalysisPhase.values()) { -376 final List<Analyzer> analyzerList = analyzers.get(phase); -377 -378 for (Analyzer a : analyzerList) { -379 try { -380 a = initializeAnalyzer(a); -381 } catch (InitializationException ex) { -382 exceptions.add(ex); -383 continue; -384 } -385 -386 /* need to create a copy of the collection because some of the -387 * analyzers may modify it. This prevents ConcurrentModificationExceptions. -388 * This is okay for adds/deletes because it happens per analyzer. -389 */ -390 LOGGER.debug("Begin Analyzer '{}'", a.getName()); -391 final Set<Dependency> dependencySet = new HashSet<Dependency>(dependencies); -392 for (Dependency d : dependencySet) { -393 boolean shouldAnalyze = true; -394 if (a instanceof FileTypeAnalyzer) { -395 final FileTypeAnalyzer fAnalyzer = (FileTypeAnalyzer) a; -396 shouldAnalyze = fAnalyzer.accept(d.getActualFile()); -397 } -398 if (shouldAnalyze) { -399 LOGGER.debug("Begin Analysis of '{}'", d.getActualFilePath()); -400 try { -401 a.analyze(d, this); -402 } catch (AnalysisException ex) { -403 LOGGER.warn("An error occurred while analyzing '{}'.", d.getActualFilePath()); -404 LOGGER.debug("", ex); -405 exceptions.add(ex); -406 } catch (Throwable ex) { -407 //final AnalysisException ax = new AnalysisException(axMsg, ex); -408 LOGGER.warn("An unexpected error occurred during analysis of '{}'", d.getActualFilePath()); -409 LOGGER.debug("", ex); -410 exceptions.add(ex); -411 } -412 } -413 } -414 } -415 } -416 for (AnalysisPhase phase : AnalysisPhase.values()) { -417 final List<Analyzer> analyzerList = analyzers.get(phase); -418 -419 for (Analyzer a : analyzerList) { -420 closeAnalyzer(a); -421 } -422 } -423 -424 LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------"); -425 LOGGER.info("Analysis Complete ({} ms)", System.currentTimeMillis() - analysisStart); -426 if (exceptions.size() > 0) { -427 throw new ExceptionCollection("One or more exceptions occured during dependency-check analysis", exceptions); -428 } -429 } -430 -431 /** -432 * Initializes the given analyzer. -433 * -434 * @param analyzer the analyzer to initialize -435 * @return the initialized analyzer -436 * @throws InitializationException thrown when there is a problem -437 * initializing the analyzer -438 */ -439 protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException { -440 try { -441 LOGGER.debug("Initializing {}", analyzer.getName()); -442 analyzer.initialize(); -443 } catch (InitializationException ex) { -444 LOGGER.error("Exception occurred initializing {}.", analyzer.getName()); -445 LOGGER.debug("", ex); -446 try { -447 analyzer.close(); -448 } catch (Throwable ex1) { -449 LOGGER.trace("", ex1); -450 } -451 throw ex; -452 } catch (Throwable ex) { -453 LOGGER.error("Unexpected exception occurred initializing {}.", analyzer.getName()); -454 LOGGER.debug("", ex); -455 try { -456 analyzer.close(); -457 } catch (Throwable ex1) { -458 LOGGER.trace("", ex1); -459 } -460 throw new InitializationException("Unexpected Exception", ex); -461 } -462 return analyzer; -463 } -464 -465 /** -466 * Closes the given analyzer. -467 * -468 * @param analyzer the analyzer to close -469 */ -470 protected void closeAnalyzer(Analyzer analyzer) { -471 LOGGER.debug("Closing Analyzer '{}'", analyzer.getName()); -472 try { -473 analyzer.close(); -474 } catch (Throwable ex) { -475 LOGGER.trace("", ex); -476 } -477 } -478 -479 /** -480 * Cycles through the cached web data sources and calls update on all of -481 * them. -482 * -483 * @throws UpdateException thrown if the operation fails -484 */ -485 public void doUpdates() throws UpdateException { -486 LOGGER.info("Checking for updates"); -487 final long updateStart = System.currentTimeMillis(); -488 final UpdateService service = new UpdateService(serviceClassLoader); -489 final Iterator<CachedWebDataSource> iterator = service.getDataSources(); -490 while (iterator.hasNext()) { -491 final CachedWebDataSource source = iterator.next(); -492 source.update(); -493 } -494 LOGGER.info("Check for updates complete ({} ms)", System.currentTimeMillis() - updateStart); -495 } -496 -497 /** -498 * Returns a full list of all of the analyzers. This is useful for reporting -499 * which analyzers where used. -500 * -501 * @return a list of Analyzers -502 */ -503 public List<Analyzer> getAnalyzers() { -504 final List<Analyzer> ret = new ArrayList<Analyzer>(); -505 for (AnalysisPhase phase : AnalysisPhase.values()) { -506 final List<Analyzer> analyzerList = analyzers.get(phase); -507 ret.addAll(analyzerList); -508 } -509 return ret; -510 } -511 -512 /** -513 * Checks all analyzers to see if an extension is supported. -514 * -515 * @param file a file extension -516 * @return true or false depending on whether or not the file extension is -517 * supported -518 */ -519 @Override -520 public boolean accept(File file) { -521 if (file == null) { -522 return false; -523 } -524 boolean scan = false; -525 for (FileTypeAnalyzer a : this.fileTypeAnalyzers) { -526 /* note, we can't break early on this loop as the analyzers need to know if -527 they have files to work on prior to initialization */ -528 scan |= a.accept(file); -529 } -530 return scan; -531 } -532 -533 /** -534 * Returns the set of file type analyzers. -535 * -536 * @return the set of file type analyzers -537 */ -538 public Set<FileTypeAnalyzer> getFileTypeAnalyzers() { -539 return this.fileTypeAnalyzers; -540 } -541 -542 /** -543 * Checks the CPE Index to ensure documents exists. If none exist a -544 * NoDataException is thrown. -545 * -546 * @throws NoDataException thrown if no data exists in the CPE Index -547 * @throws DatabaseException thrown if there is an exception opening the -548 * database -549 */ -550 private void ensureDataExists() throws NoDataException, DatabaseException { -551 final CveDB cve = new CveDB(); -552 try { -553 cve.open(); -554 if (!cve.dataExists()) { -555 throw new NoDataException("No documents exist"); -556 } -557 } catch (DatabaseException ex) { -558 throw new NoDataException(ex.getMessage(), ex); -559 } finally { -560 cve.close(); -561 } -562 } -563 } +374 /** +375 * Recursively scans files and directories. Any dependencies identified are +376 * added to the dependency collection. +377 * +378 * @param dir the directory to scan +379 * @param projectReference the name of the project or scope in which the +380 * dependency was identified +381 * @return the list of Dependency objects scanned +382 * @since v1.4.4 +383 */ +384 protected List<Dependency> scanDirectory(File dir, String projectReference) { +385 final File[] files = dir.listFiles(); +386 final List<Dependency> deps = new ArrayList<Dependency>(); +387 if (files != null) { +388 for (File f : files) { +389 if (f.isDirectory()) { +390 final List<Dependency> d = scanDirectory(f, projectReference); +391 if (d != null) { +392 deps.addAll(d); +393 } +394 } else { +395 final Dependency d = scanFile(f, projectReference); +396 deps.add(d); +397 } +398 } +399 } +400 return deps; +401 } +402 +403 /** +404 * Scans a specified file. If a dependency is identified it is added to the +405 * dependency collection. +406 * +407 * @param file The file to scan +408 * @return the scanned dependency +409 */ +410 protected Dependency scanFile(File file) { +411 return scanFile(file, null); +412 } +413 +414 /** +415 * Scans a specified file. If a dependency is identified it is added to the +416 * dependency collection. +417 * +418 * @param file The file to scan +419 * @param projectReference the name of the project or scope in which the +420 * dependency was identified +421 * @return the scanned dependency +422 * @since v1.4.4 +423 */ +424 protected Dependency scanFile(File file, String projectReference) { +425 Dependency dependency = null; +426 if (file.isFile()) { +427 if (accept(file)) { +428 dependency = new Dependency(file); +429 if (projectReference != null) { +430 dependency.addProjectReference(projectReference); +431 } +432 final String sha1 = dependency.getSha1sum(); +433 boolean found = false; +434 synchronized (dependencies) { +435 if (sha1 != null) { +436 for (Dependency existing : dependencies) { +437 if (sha1.equals(existing.getSha1sum())) { +438 found = true; +439 if (projectReference != null) { +440 existing.addProjectReference(projectReference); +441 } +442 if (existing.getActualFilePath() != null && dependency.getActualFilePath() != null +443 && !existing.getActualFilePath().equals(dependency.getActualFilePath())) { +444 existing.addRelatedDependency(dependency); +445 } else { +446 dependency = existing; +447 } +448 break; +449 } +450 } +451 } +452 if (!found) { +453 dependencies.add(dependency); +454 } +455 } +456 } else { +457 LOGGER.debug("Path passed to scanFile(File) is not a file: {}. Skipping the file.", file); +458 } +459 } +460 return dependency; +461 } +462 +463 /** +464 * Runs the analyzers against all of the dependencies. Since the mutable +465 * dependencies list is exposed via {@link #getDependencies()}, this method +466 * iterates over a copy of the dependencies list. Thus, the potential for +467 * {@link java.util.ConcurrentModificationException}s is avoided, and +468 * analyzers may safely add or remove entries from the dependencies list. +469 * <p> +470 * Every effort is made to complete analysis on the dependencies. In some +471 * cases an exception will occur with part of the analysis being performed +472 * which may not affect the entire analysis. If an exception occurs it will +473 * be included in the thrown exception collection. +474 * +475 * @throws ExceptionCollection a collections of any exceptions that occurred +476 * during analysis +477 */ +478 public void analyzeDependencies() throws ExceptionCollection { +479 final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>()); +480 boolean autoUpdate = true; +481 try { +482 autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); +483 } catch (InvalidSettingException ex) { +484 LOGGER.debug("Invalid setting for auto-update; using true."); +485 exceptions.add(ex); +486 } +487 if (autoUpdate) { +488 try { +489 doUpdates(); +490 } catch (UpdateException ex) { +491 exceptions.add(ex); +492 LOGGER.warn("Unable to update Cached Web DataSource, using local " +493 + "data instead. Results may not include recent vulnerabilities."); +494 LOGGER.debug("Update Error", ex); +495 } +496 } +497 +498 //need to ensure that data exists +499 try { +500 ensureDataExists(); +501 } catch (NoDataException ex) { +502 throwFatalExceptionCollection("Unable to continue dependency-check analysis.", ex, exceptions); +503 } catch (DatabaseException ex) { +504 throwFatalExceptionCollection("Unable to connect to the dependency-check database.", ex, exceptions); +505 } +506 +507 LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------"); +508 LOGGER.info("Analysis Started"); +509 final long analysisStart = System.currentTimeMillis(); +510 +511 // analysis phases +512 for (AnalysisPhase phase : AnalysisPhase.values()) { +513 final List<Analyzer> analyzerList = analyzers.get(phase); +514 +515 for (final Analyzer analyzer : analyzerList) { +516 final long analyzerStart = System.currentTimeMillis(); +517 try { +518 initializeAnalyzer(analyzer); +519 } catch (InitializationException ex) { +520 exceptions.add(ex); +521 continue; +522 } +523 +524 executeAnalysisTasks(analyzer, exceptions); +525 +526 final long analyzerDurationMillis = System.currentTimeMillis() - analyzerStart; +527 final long analyzerDurationSeconds = TimeUnit.MILLISECONDS.toSeconds(analyzerDurationMillis); +528 LOGGER.info("Finished {} ({} seconds)", analyzer.getName(), analyzerDurationSeconds); +529 } +530 } +531 for (AnalysisPhase phase : AnalysisPhase.values()) { +532 final List<Analyzer> analyzerList = analyzers.get(phase); +533 +534 for (Analyzer a : analyzerList) { +535 closeAnalyzer(a); +536 } +537 } +538 +539 LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------"); +540 final long analysisDurationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - analysisStart); +541 LOGGER.info("Analysis Complete ({} seconds)", analysisDurationSeconds); +542 if (exceptions.size() > 0) { +543 throw new ExceptionCollection("One or more exceptions occurred during dependency-check analysis", exceptions); +544 } +545 } +546 +547 /** +548 * Executes executes the analyzer using multiple threads. +549 * +550 * @param exceptions a collection of exceptions that occurred during +551 * analysis +552 * @param analyzer the analyzer to execute +553 * @throws ExceptionCollection thrown if exceptions occurred during analysis +554 */ +555 void executeAnalysisTasks(Analyzer analyzer, List<Throwable> exceptions) throws ExceptionCollection { +556 LOGGER.debug("Starting {}", analyzer.getName()); +557 final List<AnalysisTask> analysisTasks = getAnalysisTasks(analyzer, exceptions); +558 final ExecutorService executorService = getExecutorService(analyzer); +559 +560 try { +561 final List<Future<Void>> results = executorService.invokeAll(analysisTasks, 10, TimeUnit.MINUTES); +562 +563 // ensure there was no exception during execution +564 for (Future<Void> result : results) { +565 try { +566 result.get(); +567 } catch (ExecutionException e) { +568 throwFatalExceptionCollection("Analysis task failed with a fatal exception.", e, exceptions); +569 } catch (CancellationException e) { +570 throwFatalExceptionCollection("Analysis task timed out.", e, exceptions); +571 } +572 } +573 } catch (InterruptedException e) { +574 throwFatalExceptionCollection("Analysis has been interrupted.", e, exceptions); +575 } finally { +576 executorService.shutdown(); +577 } +578 } +579 +580 /** +581 * Returns the analysis tasks for the dependencies. +582 * +583 * @param analyzer the analyzer to create tasks for +584 * @param exceptions the collection of exceptions to collect +585 * @return a collection of analysis tasks +586 */ +587 List<AnalysisTask> getAnalysisTasks(Analyzer analyzer, List<Throwable> exceptions) { +588 final List<AnalysisTask> result = new ArrayList<AnalysisTask>(); +589 synchronized (dependencies) { +590 for (final Dependency dependency : dependencies) { +591 final AnalysisTask task = new AnalysisTask(analyzer, dependency, this, exceptions); +592 result.add(task); +593 } +594 } +595 return result; +596 } +597 +598 /** +599 * Returns the executor service for a given analyzer. +600 * +601 * @param analyzer the analyzer to obtain an executor +602 * @return the executor service +603 */ +604 ExecutorService getExecutorService(Analyzer analyzer) { +605 if (analyzer.supportsParallelProcessing()) { +606 // just a fair trade-off that should be reasonable for all analyzer types +607 final int maximumNumberOfThreads = 4 * Runtime.getRuntime().availableProcessors(); +608 +609 LOGGER.debug("Parallel processing with up to {} threads: {}.", maximumNumberOfThreads, analyzer.getName()); +610 return Executors.newFixedThreadPool(maximumNumberOfThreads); +611 } else { +612 LOGGER.debug("Parallel processing is not supported: {}.", analyzer.getName()); +613 return Executors.newSingleThreadExecutor(); +614 } +615 } +616 +617 /** +618 * Initializes the given analyzer. +619 * +620 * @param analyzer the analyzer to initialize +621 * @return the initialized analyzer +622 * @throws InitializationException thrown when there is a problem +623 * initializing the analyzer +624 */ +625 protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException { +626 try { +627 LOGGER.debug("Initializing {}", analyzer.getName()); +628 analyzer.initialize(); +629 } catch (InitializationException ex) { +630 LOGGER.error("Exception occurred initializing {}.", analyzer.getName()); +631 LOGGER.debug("", ex); +632 try { +633 analyzer.close(); +634 } catch (Throwable ex1) { +635 LOGGER.trace("", ex1); +636 } +637 throw ex; +638 } catch (Throwable ex) { +639 LOGGER.error("Unexpected exception occurred initializing {}.", analyzer.getName()); +640 LOGGER.debug("", ex); +641 try { +642 analyzer.close(); +643 } catch (Throwable ex1) { +644 LOGGER.trace("", ex1); +645 } +646 throw new InitializationException("Unexpected Exception", ex); +647 } +648 return analyzer; +649 } +650 +651 /** +652 * Closes the given analyzer. +653 * +654 * @param analyzer the analyzer to close +655 */ +656 protected void closeAnalyzer(Analyzer analyzer) { +657 LOGGER.debug("Closing Analyzer '{}'", analyzer.getName()); +658 try { +659 analyzer.close(); +660 } catch (Throwable ex) { +661 LOGGER.trace("", ex); +662 } +663 } +664 +665 /** +666 * Cycles through the cached web data sources and calls update on all of +667 * them. +668 * +669 * @throws UpdateException thrown if the operation fails +670 */ +671 public void doUpdates() throws UpdateException { +672 LOGGER.info("Checking for updates"); +673 final long updateStart = System.currentTimeMillis(); +674 final UpdateService service = new UpdateService(serviceClassLoader); +675 final Iterator<CachedWebDataSource> iterator = service.getDataSources(); +676 while (iterator.hasNext()) { +677 final CachedWebDataSource source = iterator.next(); +678 source.update(); +679 } +680 LOGGER.info("Check for updates complete ({} ms)", System.currentTimeMillis() - updateStart); +681 } +682 +683 /** +684 * Returns a full list of all of the analyzers. This is useful for reporting +685 * which analyzers where used. +686 * +687 * @return a list of Analyzers +688 */ +689 public List<Analyzer> getAnalyzers() { +690 final List<Analyzer> ret = new ArrayList<Analyzer>(); +691 for (AnalysisPhase phase : AnalysisPhase.values()) { +692 final List<Analyzer> analyzerList = analyzers.get(phase); +693 ret.addAll(analyzerList); +694 } +695 return ret; +696 } +697 +698 /** +699 * Checks all analyzers to see if an extension is supported. +700 * +701 * @param file a file extension +702 * @return true or false depending on whether or not the file extension is +703 * supported +704 */ +705 @Override +706 public boolean accept(File file) { +707 if (file == null) { +708 return false; +709 } +710 boolean scan = false; +711 for (FileTypeAnalyzer a : this.fileTypeAnalyzers) { +712 /* note, we can't break early on this loop as the analyzers need to know if +713 they have files to work on prior to initialization */ +714 scan |= a.accept(file); +715 } +716 return scan; +717 } +718 +719 /** +720 * Returns the set of file type analyzers. +721 * +722 * @return the set of file type analyzers +723 */ +724 public Set<FileTypeAnalyzer> getFileTypeAnalyzers() { +725 return this.fileTypeAnalyzers; +726 } +727 +728 /** +729 * Adds a file type analyzer. This has been added solely to assist in unit +730 * testing the Engine. +731 * +732 * @param fta the file type analyzer to add +733 */ +734 protected void addFileTypeAnalyzer(FileTypeAnalyzer fta) { +735 this.fileTypeAnalyzers.add(fta); +736 } +737 +738 /** +739 * Checks the CPE Index to ensure documents exists. If none exist a +740 * NoDataException is thrown. +741 * +742 * @throws NoDataException thrown if no data exists in the CPE Index +743 * @throws DatabaseException thrown if there is an exception opening the +744 * database +745 */ +746 private void ensureDataExists() throws NoDataException, DatabaseException { +747 final CveDB cve = new CveDB(); +748 try { +749 cve.open(); +750 if (!cve.dataExists()) { +751 throw new NoDataException("No documents exist"); +752 } +753 } catch (DatabaseException ex) { +754 throw new NoDataException(ex.getMessage(), ex); +755 } finally { +756 cve.close(); +757 } +758 } +759 +760 /** +761 * Constructs and throws a fatal exception collection. +762 * +763 * @param message the exception message +764 * @param throwable the cause +765 * @param exceptions a collection of exception to include +766 * @throws ExceptionCollection a collection of exceptions that occurred +767 * during analysis +768 */ +769 private void throwFatalExceptionCollection(String message, Throwable throwable, List<Throwable> exceptions) throws ExceptionCollection { +770 LOGGER.error("{}\n\n{}", throwable.getMessage(), message); +771 LOGGER.debug("", throwable); +772 exceptions.add(throwable); +773 throw new ExceptionCollection(message, exceptions, true); +774 } +775 }
      diff --git a/xref/org/owasp/dependencycheck/agent/package-frame.html b/xref/org/owasp/dependencycheck/agent/package-frame.html index ad331cb6d..626826f1a 100644 --- a/xref/org/owasp/dependencycheck/agent/package-frame.html +++ b/xref/org/owasp/dependencycheck/agent/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.agent + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.agent diff --git a/xref/org/owasp/dependencycheck/agent/package-summary.html b/xref/org/owasp/dependencycheck/agent/package-summary.html index 8d42657b6..5b6bd67ab 100644 --- a/xref/org/owasp/dependencycheck/agent/package-summary.html +++ b/xref/org/owasp/dependencycheck/agent/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.agent + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.agent diff --git a/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html index a7a1237ad..aa8cbe6b5 100644 --- a/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.html @@ -54,7 +54,15 @@ 46 public void close() throws Exception { 47 //do nothing 48 } -49 } +49 +50 /** +51 * The default is to support parallel processing. +52 */ +53 @Override +54 public boolean supportsParallelProcessing() { +55 return true; +56 } +57 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html index 46135995f..2c1fc9a99 100644 --- a/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.html @@ -91,7 +91,7 @@ 83 /** 84 * A flag indicating whether or not the analyzer is enabled. 85 */ -86 private boolean enabled = true; +86 private volatile boolean enabled = true; 87 88 /** 89 * Get the value of enabled. diff --git a/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html index dff6d6872..f30874653 100644 --- a/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.html @@ -163,42 +163,49 @@ 155 } 156 } 157 if (file != null) { -158 try { -159 rules.addAll(parser.parseSuppressionRules(file)); -160 LOGGER.debug("{} suppression rules were loaded.", rules.size()); -161 } catch (SuppressionParseException ex) { -162 LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath()); -163 LOGGER.warn(ex.getMessage()); -164 throw ex; -165 } -166 } -167 } catch (DownloadFailedException ex) { -168 throwSuppressionParseException("Unable to fetch the configured suppression file", ex); -169 } catch (MalformedURLException ex) { -170 throwSuppressionParseException("Configured suppression file has an invalid URL", ex); -171 } catch (IOException ex) { -172 throwSuppressionParseException("Unable to create temp file for suppressions", ex); -173 } finally { -174 if (deleteTempFile && file != null) { -175 FileUtils.delete(file); -176 } -177 } -178 } -179 -180 /** -181 * Utility method to throw parse exceptions. -182 * -183 * @param message the exception message -184 * @param exception the cause of the exception -185 * @throws SuppressionParseException throws the generated -186 * SuppressionParseException -187 */ -188 private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException { -189 LOGGER.warn(message); -190 LOGGER.debug("", exception); -191 throw new SuppressionParseException(message, exception); -192 } -193 } +158 if (!file.exists()) { +159 final String msg = String.format("Suppression file '%s' does not exists", file.getPath()); +160 LOGGER.warn(msg); +161 throw new SuppressionParseException(msg); +162 } +163 try { +164 rules.addAll(parser.parseSuppressionRules(file)); +165 LOGGER.debug("{} suppression rules were loaded.", rules.size()); +166 } catch (SuppressionParseException ex) { +167 LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath()); +168 LOGGER.warn(ex.getMessage()); +169 throw ex; +170 } +171 } +172 } catch (DownloadFailedException ex) { +173 throwSuppressionParseException("Unable to fetch the configured suppression file", ex); +174 } catch (MalformedURLException ex) { +175 throwSuppressionParseException("Configured suppression file has an invalid URL", ex); +176 } catch (SuppressionParseException ex) { +177 throw ex; +178 } catch (IOException ex) { +179 throwSuppressionParseException("Unable to create temp file for suppressions", ex); +180 } finally { +181 if (deleteTempFile && file != null) { +182 FileUtils.delete(file); +183 } +184 } +185 } +186 +187 /** +188 * Utility method to throw parse exceptions. +189 * +190 * @param message the exception message +191 * @param exception the cause of the exception +192 * @throws SuppressionParseException throws the generated +193 * SuppressionParseException +194 */ +195 private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException { +196 LOGGER.warn(message); +197 LOGGER.debug("", exception); +198 throw new SuppressionParseException(message, exception); +199 } +200 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/Analyzer.html b/xref/org/owasp/dependencycheck/analyzer/Analyzer.html index b363ffba7..b894e05b0 100644 --- a/xref/org/owasp/dependencycheck/analyzer/Analyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/Analyzer.html @@ -83,7 +83,15 @@ 75 * @throws Exception is thrown if an exception occurs closing the analyzer. 76 */ 77 void close() throws Exception; -78 } +78 +79 /** +80 * Returns whether multiple instances of the same type of analyzer can run in parallel. +81 * Note that running analyzers of different types in parallel is not supported at all. +82 * +83 * @return {@code true} if the analyzer supports parallel processing, {@code false} else +84 */ +85 boolean supportsParallelProcessing(); +86 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html index 101341061..020d22f3d 100644 --- a/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.html @@ -33,570 +33,612 @@ 25 import java.io.FileNotFoundException; 26 import java.io.FileOutputStream; 27 import java.io.IOException; -28 import java.util.ArrayList; -29 import java.util.Collections; -30 import java.util.Enumeration; -31 import java.util.HashSet; -32 import java.util.List; -33 import java.util.Set; -34 -35 import org.apache.commons.compress.archivers.ArchiveEntry; -36 import org.apache.commons.compress.archivers.ArchiveInputStream; -37 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; -38 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -39 import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; -40 import org.apache.commons.compress.archivers.zip.ZipFile; -41 import org.apache.commons.compress.compressors.CompressorInputStream; -42 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; -43 import org.apache.commons.compress.compressors.bzip2.BZip2Utils; -44 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; -45 import org.apache.commons.compress.compressors.gzip.GzipUtils; -46 import org.apache.commons.compress.utils.IOUtils; -47 -48 import org.owasp.dependencycheck.Engine; -49 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -50 import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException; -51 import org.owasp.dependencycheck.dependency.Dependency; -52 import org.owasp.dependencycheck.exception.InitializationException; -53 import org.owasp.dependencycheck.utils.FileFilterBuilder; -54 import org.owasp.dependencycheck.utils.FileUtils; -55 import org.owasp.dependencycheck.utils.Settings; -56 -57 import org.slf4j.Logger; -58 import org.slf4j.LoggerFactory; -59 -60 /** -61 * <p> -62 * An analyzer that extracts files from archives and ensures any supported files -63 * contained within the archive are added to the dependency list.</p> -64 * -65 * @author Jeremy Long -66 */ -67 public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { -68 -69 /** -70 * The logger. -71 */ -72 private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveAnalyzer.class); -73 /** -74 * The count of directories created during analysis. This is used for -75 * creating temporary directories. -76 */ -77 private static int dirCount = 0; -78 /** -79 * The parent directory for the individual directories per archive. -80 */ -81 private File tempFileLocation = null; -82 /** -83 * The max scan depth that the analyzer will recursively extract nested -84 * archives. -85 */ -86 private static final int MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3); -87 /** -88 * Tracks the current scan/extraction depth for nested archives. -89 */ -90 private int scanDepth = 0; -91 -92 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> -93 /** -94 * The name of the analyzer. -95 */ -96 private static final String ANALYZER_NAME = "Archive Analyzer"; -97 /** -98 * The phase that this analyzer is intended to run in. -99 */ -100 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL; -101 /** -102 * The set of things we can handle with Zip methods -103 */ -104 private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg"); -105 /** -106 * The set of file extensions supported by this analyzer. Note for -107 * developers, any additions to this list will need to be explicitly handled -108 * in {@link #extractFiles(File, File, Engine)}. -109 */ -110 private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz", "bz2", "tbz2"); -111 -112 /** -113 * Detects files with extensions to remove from the engine's collection of -114 * dependencies. -115 */ -116 private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance().addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2") -117 .build(); -118 -119 static { -120 final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS); -121 if (additionalZipExt != null) { -122 final String[] ext = additionalZipExt.split("\\s*,\\s*"); -123 Collections.addAll(ZIPPABLES, ext); -124 } -125 EXTENSIONS.addAll(ZIPPABLES); -126 } -127 -128 /** -129 * The file filter used to filter supported files. -130 */ -131 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build(); -132 -133 @Override -134 protected FileFilter getFileFilter() { -135 return FILTER; -136 } -137 -138 /** -139 * Detects files with .zip extension. -140 */ -141 private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build(); -142 -143 /** -144 * Returns the name of the analyzer. -145 * -146 * @return the name of the analyzer. -147 */ -148 @Override -149 public String getName() { -150 return ANALYZER_NAME; -151 } -152 -153 /** -154 * Returns the phase that the analyzer is intended to run in. -155 * -156 * @return the phase that the analyzer is intended to run in. -157 */ -158 @Override -159 public AnalysisPhase getAnalysisPhase() { -160 return ANALYSIS_PHASE; -161 } -162 //</editor-fold> -163 -164 /** -165 * Returns the key used in the properties file to reference the analyzer's -166 * enabled property. -167 * -168 * @return the analyzer's enabled property setting key -169 */ -170 @Override -171 protected String getAnalyzerEnabledSettingKey() { -172 return Settings.KEYS.ANALYZER_ARCHIVE_ENABLED; -173 } -174 -175 /** -176 * The initialize method does nothing for this Analyzer. -177 * -178 * @throws InitializationException is thrown if there is an exception -179 * deleting or creating temporary files -180 */ -181 @Override -182 public void initializeFileTypeAnalyzer() throws InitializationException { -183 try { -184 final File baseDir = Settings.getTempDirectory(); -185 tempFileLocation = File.createTempFile("check", "tmp", baseDir); -186 if (!tempFileLocation.delete()) { -187 setEnabled(false); -188 final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath()); -189 throw new InitializationException(msg); -190 } -191 if (!tempFileLocation.mkdirs()) { -192 setEnabled(false); -193 final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath()); -194 throw new InitializationException(msg); -195 } -196 } catch (IOException ex) { -197 setEnabled(false); -198 throw new InitializationException("Unable to create a temporary file", ex); -199 } -200 } -201 -202 /** -203 * The close method deletes any temporary files and directories created -204 * during analysis. -205 * -206 * @throws Exception thrown if there is an exception deleting temporary -207 * files -208 */ -209 @Override -210 public void close() throws Exception { -211 if (tempFileLocation != null && tempFileLocation.exists()) { -212 LOGGER.debug("Attempting to delete temporary files"); -213 final boolean success = FileUtils.delete(tempFileLocation); -214 if (!success && tempFileLocation.exists()) { -215 final String[] l = tempFileLocation.list(); -216 if (l != null && l.length > 0) { -217 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); -218 } -219 } -220 } -221 } -222 -223 /** -224 * Analyzes a given dependency. If the dependency is an archive, such as a -225 * WAR or EAR, the contents are extracted, scanned, and added to the list of -226 * dependencies within the engine. -227 * -228 * @param dependency the dependency to analyze -229 * @param engine the engine scanning -230 * @throws AnalysisException thrown if there is an analysis exception -231 */ -232 @Override -233 public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { -234 final File f = new File(dependency.getActualFilePath()); -235 final File tmpDir = getNextTempDirectory(); -236 extractFiles(f, tmpDir, engine); -237 -238 //make a copy -239 final Set<Dependency> dependencySet = findMoreDependencies(engine, tmpDir); -240 if (!dependencySet.isEmpty()) { -241 for (Dependency d : dependencySet) { -242 //fix the dependency's display name and path -243 final String displayPath = String.format("%s%s", -244 dependency.getFilePath(), -245 d.getActualFilePath().substring(tmpDir.getAbsolutePath().length())); -246 final String displayName = String.format("%s: %s", -247 dependency.getFileName(), -248 d.getFileName()); -249 d.setFilePath(displayPath); -250 d.setFileName(displayName); -251 -252 //TODO - can we get more evidence from the parent? EAR contains module name, etc. -253 //analyze the dependency (i.e. extract files) if it is a supported type. -254 if (this.accept(d.getActualFile()) && scanDepth < MAX_SCAN_DEPTH) { -255 scanDepth += 1; -256 analyze(d, engine); -257 scanDepth -= 1; -258 } -259 } -260 } -261 if (REMOVE_FROM_ANALYSIS.accept(dependency.getActualFile())) { -262 addDisguisedJarsToDependencies(dependency, engine); -263 engine.getDependencies().remove(dependency); -264 } -265 Collections.sort(engine.getDependencies()); -266 } -267 -268 /** -269 * If a zip file was identified as a possible JAR, this method will add the -270 * zip to the list of dependencies. -271 * -272 * @param dependency the zip file -273 * @param engine the engine -274 * @throws AnalysisException thrown if there is an issue -275 */ -276 private void addDisguisedJarsToDependencies(Dependency dependency, Engine engine) throws AnalysisException { -277 if (ZIP_FILTER.accept(dependency.getActualFile()) && isZipFileActuallyJarFile(dependency)) { -278 final File tdir = getNextTempDirectory(); -279 final String fileName = dependency.getFileName(); -280 -281 LOGGER.info("The zip file '{}' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName); -282 -283 final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar"); -284 try { -285 org.apache.commons.io.FileUtils.copyFile(tdir, tmpLoc); -286 final Set<Dependency> dependencySet = findMoreDependencies(engine, tmpLoc); -287 if (!dependencySet.isEmpty()) { -288 if (dependencySet.size() != 1) { -289 LOGGER.info("Deep copy of ZIP to JAR file resulted in more than one dependency?"); -290 } -291 for (Dependency d : dependencySet) { -292 //fix the dependency's display name and path -293 d.setFilePath(dependency.getFilePath()); -294 d.setDisplayFileName(dependency.getFileName()); -295 } -296 } -297 } catch (IOException ex) { -298 LOGGER.debug("Unable to perform deep copy on '{}'", dependency.getActualFile().getPath(), ex); -299 } -300 } -301 } -302 /** -303 * An empty dependency set. -304 */ -305 private static final Set<Dependency> EMPTY_DEPENDENCY_SET = Collections.emptySet(); -306 -307 /** -308 * Scan the given file/folder, and return any new dependencies found. -309 * -310 * @param engine used to scan -311 * @param file target of scanning -312 * @return any dependencies that weren't known to the engine before -313 */ -314 private static Set<Dependency> findMoreDependencies(Engine engine, File file) { -315 final List<Dependency> before = new ArrayList<Dependency>(engine.getDependencies()); -316 engine.scan(file); -317 final List<Dependency> after = engine.getDependencies(); -318 final boolean sizeChanged = before.size() != after.size(); -319 final Set<Dependency> newDependencies; -320 if (sizeChanged) { -321 //get the new dependencies -322 newDependencies = new HashSet<Dependency>(after); -323 newDependencies.removeAll(before); -324 } else { -325 newDependencies = EMPTY_DEPENDENCY_SET; -326 } -327 return newDependencies; -328 } -329 -330 /** -331 * Retrieves the next temporary directory to extract an archive too. -332 * -333 * @return a directory -334 * @throws AnalysisException thrown if unable to create temporary directory -335 */ -336 private File getNextTempDirectory() throws AnalysisException { -337 dirCount += 1; -338 final File directory = new File(tempFileLocation, String.valueOf(dirCount)); -339 //getting an exception for some directories not being able to be created; might be because the directory already exists? -340 if (directory.exists()) { -341 return getNextTempDirectory(); -342 } -343 if (!directory.mkdirs()) { -344 final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath()); -345 throw new AnalysisException(msg); -346 } -347 return directory; -348 } -349 -350 /** -351 * Extracts the contents of an archive into the specified directory. -352 * -353 * @param archive an archive file such as a WAR or EAR -354 * @param destination a directory to extract the contents to -355 * @param engine the scanning engine -356 * @throws AnalysisException thrown if the archive is not found -357 */ -358 private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException { -359 if (archive != null && destination != null) { -360 String archiveExt = FileUtils.getFileExtension(archive.getName()); -361 if (archiveExt == null) { -362 return; -363 } -364 archiveExt = archiveExt.toLowerCase(); -365 -366 FileInputStream fis; -367 try { -368 fis = new FileInputStream(archive); -369 } catch (FileNotFoundException ex) { -370 LOGGER.debug("", ex); -371 throw new AnalysisException("Archive file was not found.", ex); -372 } -373 try { -374 if (ZIPPABLES.contains(archiveExt)) { -375 final BufferedInputStream in = new BufferedInputStream(fis); -376 ensureReadableJar(archiveExt, in); -377 extractArchive(new ZipArchiveInputStream(in), destination, engine); -378 } else if ("tar".equals(archiveExt)) { -379 extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine); -380 } else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) { -381 final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName()); -382 final File f = new File(destination, uncompressedName); -383 if (engine.accept(f)) { -384 decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), f); -385 } -386 } else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) { -387 final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName()); -388 final File f = new File(destination, uncompressedName); -389 if (engine.accept(f)) { -390 decompressFile(new BZip2CompressorInputStream(new BufferedInputStream(fis)), f); -391 } -392 } -393 } catch (ArchiveExtractionException ex) { -394 LOGGER.warn("Exception extracting archive '{}'.", archive.getName()); -395 LOGGER.debug("", ex); -396 } catch (IOException ex) { -397 LOGGER.warn("Exception reading archive '{}'.", archive.getName()); -398 LOGGER.debug("", ex); -399 } finally { -400 close(fis); -401 } -402 } -403 } -404 -405 /** -406 * Checks if the file being scanned is a JAR that begins with '#!/bin' which -407 * indicates it is a fully executable jar. If a fully executable JAR is -408 * identified the input stream will be advanced to the start of the actual -409 * JAR file ( skipping the script). -410 * -411 * @see -412 * <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing -413 * Spring Boot Applications</a> -414 * @param archiveExt the file extension -415 * @param in the input stream -416 * @throws IOException thrown if there is an error reading the stream -417 */ -418 private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException { -419 if ("jar".equals(archiveExt) && in.markSupported()) { -420 in.mark(7); -421 final byte[] b = new byte[7]; -422 final int read = in.read(b); -423 if (read == 7 -424 && b[0] == '#' -425 && b[1] == '!' -426 && b[2] == '/' -427 && b[3] == 'b' -428 && b[4] == 'i' -429 && b[5] == 'n' -430 && b[6] == '/') { -431 boolean stillLooking = true; -432 int chr, nxtChr; -433 while (stillLooking && (chr = in.read()) != -1) { -434 if (chr == '\n' || chr == '\r') { -435 in.mark(4); -436 if ((chr = in.read()) != -1) { -437 if (chr == 'P' && (chr = in.read()) != -1) { -438 if (chr == 'K' && (chr = in.read()) != -1) { -439 if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) { -440 if (nxtChr == chr + 1) { -441 stillLooking = false; -442 in.reset(); -443 } -444 } -445 } -446 } -447 } -448 } -449 } -450 } else { -451 in.reset(); -452 } -453 } -454 } -455 -456 /** -457 * Extracts files from an archive. -458 * -459 * @param input the archive to extract files from -460 * @param destination the location to write the files too -461 * @param engine the dependency-check engine -462 * @throws ArchiveExtractionException thrown if there is an exception -463 * extracting files from the archive -464 */ -465 private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException { -466 ArchiveEntry entry; -467 try { -468 while ((entry = input.getNextEntry()) != null) { -469 final File file = new File(destination, entry.getName()); -470 if (entry.isDirectory()) { -471 if (!file.exists() && !file.mkdirs()) { -472 final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath()); -473 throw new AnalysisException(msg); -474 } -475 } else if (engine.accept(file)) { -476 extractAcceptedFile(input, file); -477 } -478 } -479 } catch (Throwable ex) { -480 throw new ArchiveExtractionException(ex); -481 } finally { -482 close(input); -483 } -484 } -485 -486 /** -487 * Extracts a file from an archive. -488 * -489 * @param input the archives input stream -490 * @param file the file to extract -491 * @throws AnalysisException thrown if there is an error -492 */ -493 private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException { -494 LOGGER.debug("Extracting '{}'", file.getPath()); -495 FileOutputStream fos = null; -496 try { -497 final File parent = file.getParentFile(); -498 if (!parent.isDirectory() && !parent.mkdirs()) { -499 final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath()); -500 throw new AnalysisException(msg); -501 } -502 fos = new FileOutputStream(file); -503 IOUtils.copy(input, fos); -504 } catch (FileNotFoundException ex) { -505 LOGGER.debug("", ex); -506 final String msg = String.format("Unable to find file '%s'.", file.getName()); -507 throw new AnalysisException(msg, ex); -508 } catch (IOException ex) { -509 LOGGER.debug("", ex); -510 final String msg = String.format("IO Exception while parsing file '%s'.", file.getName()); -511 throw new AnalysisException(msg, ex); -512 } finally { -513 close(fos); -514 } -515 } -516 -517 /** -518 * Decompresses a file. -519 * -520 * @param inputStream the compressed file -521 * @param outputFile the location to write the decompressed file -522 * @throws ArchiveExtractionException thrown if there is an exception -523 * decompressing the file -524 */ -525 private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException { -526 LOGGER.debug("Decompressing '{}'", outputFile.getPath()); -527 FileOutputStream out = null; -528 try { -529 out = new FileOutputStream(outputFile); -530 IOUtils.copy(inputStream, out); -531 } catch (FileNotFoundException ex) { -532 LOGGER.debug("", ex); -533 throw new ArchiveExtractionException(ex); -534 } catch (IOException ex) { -535 LOGGER.debug("", ex); -536 throw new ArchiveExtractionException(ex); -537 } finally { -538 close(out); -539 } -540 } -541 -542 /** -543 * Close the given {@link Closeable} instance, ignoring nulls, and logging -544 * any thrown {@link IOException}. -545 * -546 * @param closeable to be closed -547 */ -548 private static void close(Closeable closeable) { -549 if (null != closeable) { -550 try { -551 closeable.close(); -552 } catch (IOException ex) { -553 LOGGER.trace("", ex); -554 } -555 } -556 } -557 -558 /** -559 * Attempts to determine if a zip file is actually a JAR file. -560 * -561 * @param dependency the dependency to check -562 * @return true if the dependency appears to be a JAR file; otherwise false -563 */ -564 private boolean isZipFileActuallyJarFile(Dependency dependency) { -565 boolean isJar = false; -566 ZipFile zip = null; -567 try { -568 zip = new ZipFile(dependency.getActualFilePath()); -569 if (zip.getEntry("META-INF/MANIFEST.MF") != null -570 || zip.getEntry("META-INF/maven") != null) { -571 final Enumeration<ZipArchiveEntry> entries = zip.getEntries(); -572 while (entries.hasMoreElements()) { -573 final ZipArchiveEntry entry = entries.nextElement(); -574 if (!entry.isDirectory()) { -575 final String name = entry.getName().toLowerCase(); -576 if (name.endsWith(".class")) { -577 isJar = true; -578 break; -579 } -580 } -581 } -582 } -583 } catch (IOException ex) { -584 LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex); -585 } finally { -586 ZipFile.closeQuietly(zip); -587 } -588 -589 return isJar; -590 } -591 } +28 import java.util.Collections; +29 import java.util.Enumeration; +30 import java.util.List; +31 import java.util.Set; +32 +33 import org.apache.commons.compress.archivers.ArchiveEntry; +34 import org.apache.commons.compress.archivers.ArchiveInputStream; +35 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +36 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +37 import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +38 import org.apache.commons.compress.archivers.zip.ZipFile; +39 import org.apache.commons.compress.compressors.CompressorInputStream; +40 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; +41 import org.apache.commons.compress.compressors.bzip2.BZip2Utils; +42 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; +43 import org.apache.commons.compress.compressors.gzip.GzipUtils; +44 import org.apache.commons.compress.utils.IOUtils; +45 +46 import org.owasp.dependencycheck.Engine; +47 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +48 import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException; +49 import org.owasp.dependencycheck.dependency.Dependency; +50 import org.owasp.dependencycheck.exception.InitializationException; +51 import org.owasp.dependencycheck.utils.FileFilterBuilder; +52 import org.owasp.dependencycheck.utils.FileUtils; +53 import org.owasp.dependencycheck.utils.Settings; +54 +55 import org.slf4j.Logger; +56 import org.slf4j.LoggerFactory; +57 +58 /** +59 * <p> +60 * An analyzer that extracts files from archives and ensures any supported files +61 * contained within the archive are added to the dependency list.</p> +62 * +63 * @author Jeremy Long +64 */ +65 public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { +66 +67 /** +68 * The logger. +69 */ +70 private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveAnalyzer.class); +71 /** +72 * The count of directories created during analysis. This is used for +73 * creating temporary directories. +74 */ +75 private static int dirCount = 0; +76 /** +77 * The parent directory for the individual directories per archive. +78 */ +79 private File tempFileLocation = null; +80 /** +81 * The max scan depth that the analyzer will recursively extract nested +82 * archives. +83 */ +84 private static final int MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3); +85 /** +86 * Tracks the current scan/extraction depth for nested archives. +87 */ +88 private int scanDepth = 0; +89 +90 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> +91 /** +92 * The name of the analyzer. +93 */ +94 private static final String ANALYZER_NAME = "Archive Analyzer"; +95 /** +96 * The phase that this analyzer is intended to run in. +97 */ +98 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL; +99 /** +100 * The set of things we can handle with Zip methods +101 */ +102 private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg"); +103 /** +104 * The set of file extensions supported by this analyzer. Note for +105 * developers, any additions to this list will need to be explicitly handled +106 * in {@link #extractFiles(File, File, Engine)}. +107 */ +108 private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz", "bz2", "tbz2"); +109 +110 /** +111 * Detects files with extensions to remove from the engine's collection of +112 * dependencies. +113 */ +114 private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance().addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2") +115 .build(); +116 +117 static { +118 final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS); +119 if (additionalZipExt != null) { +120 final String[] ext = additionalZipExt.split("\\s*,\\s*"); +121 Collections.addAll(ZIPPABLES, ext); +122 } +123 EXTENSIONS.addAll(ZIPPABLES); +124 } +125 +126 /** +127 * The file filter used to filter supported files. +128 */ +129 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build(); +130 +131 @Override +132 protected FileFilter getFileFilter() { +133 return FILTER; +134 } +135 +136 /** +137 * Detects files with .zip extension. +138 */ +139 private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build(); +140 +141 /** +142 * Returns the name of the analyzer. +143 * +144 * @return the name of the analyzer. +145 */ +146 @Override +147 public String getName() { +148 return ANALYZER_NAME; +149 } +150 +151 /** +152 * Returns the phase that the analyzer is intended to run in. +153 * +154 * @return the phase that the analyzer is intended to run in. +155 */ +156 @Override +157 public AnalysisPhase getAnalysisPhase() { +158 return ANALYSIS_PHASE; +159 } +160 //</editor-fold> +161 +162 /** +163 * Returns the key used in the properties file to reference the analyzer's +164 * enabled property. +165 * +166 * @return the analyzer's enabled property setting key +167 */ +168 @Override +169 protected String getAnalyzerEnabledSettingKey() { +170 return Settings.KEYS.ANALYZER_ARCHIVE_ENABLED; +171 } +172 +173 /** +174 * The initialize method does nothing for this Analyzer. +175 * +176 * @throws InitializationException is thrown if there is an exception +177 * deleting or creating temporary files +178 */ +179 @Override +180 public void initializeFileTypeAnalyzer() throws InitializationException { +181 try { +182 final File baseDir = Settings.getTempDirectory(); +183 tempFileLocation = File.createTempFile("check", "tmp", baseDir); +184 if (!tempFileLocation.delete()) { +185 setEnabled(false); +186 final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath()); +187 throw new InitializationException(msg); +188 } +189 if (!tempFileLocation.mkdirs()) { +190 setEnabled(false); +191 final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath()); +192 throw new InitializationException(msg); +193 } +194 } catch (IOException ex) { +195 setEnabled(false); +196 throw new InitializationException("Unable to create a temporary file", ex); +197 } +198 } +199 +200 /** +201 * The close method deletes any temporary files and directories created +202 * during analysis. +203 * +204 * @throws Exception thrown if there is an exception deleting temporary +205 * files +206 */ +207 @Override +208 public void close() throws Exception { +209 if (tempFileLocation != null && tempFileLocation.exists()) { +210 LOGGER.debug("Attempting to delete temporary files"); +211 final boolean success = FileUtils.delete(tempFileLocation); +212 if (!success && tempFileLocation.exists()) { +213 final String[] l = tempFileLocation.list(); +214 if (l != null && l.length > 0) { +215 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); +216 } +217 } +218 } +219 } +220 +221 /** +222 * Does not support parallel processing as it both modifies and iterates +223 * over the engine's list of dependencies. +224 * +225 * @see #analyzeFileType(Dependency, Engine) +226 * @see #findMoreDependencies(Engine, File) +227 */ +228 @Override +229 public boolean supportsParallelProcessing() { +230 return false; +231 } +232 +233 /** +234 * Analyzes a given dependency. If the dependency is an archive, such as a +235 * WAR or EAR, the contents are extracted, scanned, and added to the list of +236 * dependencies within the engine. +237 * +238 * @param dependency the dependency to analyze +239 * @param engine the engine scanning +240 * @throws AnalysisException thrown if there is an analysis exception +241 */ +242 @Override +243 public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { +244 final File f = new File(dependency.getActualFilePath()); +245 final File tmpDir = getNextTempDirectory(); +246 extractFiles(f, tmpDir, engine); +247 +248 //make a copy +249 final List<Dependency> dependencySet = findMoreDependencies(engine, tmpDir); +250 +251 if (!dependencySet.isEmpty()) { +252 for (Dependency d : dependencySet) { +253 if (d.getFilePath().startsWith(tmpDir.getAbsolutePath())) { +254 //fix the dependency's display name and path +255 final String displayPath = String.format("%s%s", +256 dependency.getFilePath(), +257 d.getActualFilePath().substring(tmpDir.getAbsolutePath().length())); +258 final String displayName = String.format("%s: %s", +259 dependency.getFileName(), +260 d.getFileName()); +261 d.setFilePath(displayPath); +262 d.setFileName(displayName); +263 d.setProjectReferences(dependency.getProjectReferences()); +264 +265 //TODO - can we get more evidence from the parent? EAR contains module name, etc. +266 //analyze the dependency (i.e. extract files) if it is a supported type. +267 if (this.accept(d.getActualFile()) && scanDepth < MAX_SCAN_DEPTH) { +268 scanDepth += 1; +269 analyze(d, engine); +270 scanDepth -= 1; +271 } +272 } else { +273 for (Dependency sub : dependencySet) { +274 if (sub.getFilePath().startsWith(tmpDir.getAbsolutePath())) { +275 final String displayPath = String.format("%s%s", +276 dependency.getFilePath(), +277 sub.getActualFilePath().substring(tmpDir.getAbsolutePath().length())); +278 final String displayName = String.format("%s: %s", +279 dependency.getFileName(), +280 sub.getFileName()); +281 sub.setFilePath(displayPath); +282 sub.setFileName(displayName); +283 } +284 } +285 } +286 } +287 } +288 if (REMOVE_FROM_ANALYSIS.accept(dependency.getActualFile())) { +289 addDisguisedJarsToDependencies(dependency, engine); +290 engine.getDependencies().remove(dependency); +291 } +292 Collections.sort(engine.getDependencies()); +293 } +294 +295 /** +296 * If a zip file was identified as a possible JAR, this method will add the +297 * zip to the list of dependencies. +298 * +299 * @param dependency the zip file +300 * @param engine the engine +301 * @throws AnalysisException thrown if there is an issue +302 */ +303 private void addDisguisedJarsToDependencies(Dependency dependency, Engine engine) throws AnalysisException { +304 if (ZIP_FILTER.accept(dependency.getActualFile()) && isZipFileActuallyJarFile(dependency)) { +305 final File tdir = getNextTempDirectory(); +306 final String fileName = dependency.getFileName(); +307 +308 LOGGER.info("The zip file '{}' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName); +309 final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar"); +310 //store the archives sha1 and change it so that the engine doesn't think the zip and jar file are the same +311 // and add it is a related dependency. +312 final String archiveSha1 = dependency.getSha1sum(); +313 try { +314 dependency.setSha1sum(""); +315 org.apache.commons.io.FileUtils.copyFile(dependency.getActualFile(), tmpLoc); +316 final List<Dependency> dependencySet = findMoreDependencies(engine, tmpLoc); +317 if (!dependencySet.isEmpty()) { +318 for (Dependency d : dependencySet) { +319 //fix the dependency's display name and path +320 if (d.getActualFile().equals(tmpLoc)) { +321 d.setFilePath(dependency.getFilePath()); +322 d.setDisplayFileName(dependency.getFileName()); +323 } else { +324 for (Dependency sub : d.getRelatedDependencies()) { +325 if (sub.getActualFile().equals(tmpLoc)) { +326 sub.setFilePath(dependency.getFilePath()); +327 sub.setDisplayFileName(dependency.getFileName()); +328 } +329 } +330 } +331 } +332 } +333 } catch (IOException ex) { +334 LOGGER.debug("Unable to perform deep copy on '{}'", dependency.getActualFile().getPath(), ex); +335 } finally { +336 dependency.setSha1sum(archiveSha1); +337 } +338 } +339 } +340 +341 /** +342 * Scan the given file/folder, and return any new dependencies found. +343 * +344 * @param engine used to scan +345 * @param file target of scanning +346 * @return any dependencies that weren't known to the engine before +347 */ +348 private static List<Dependency> findMoreDependencies(Engine engine, File file) { +349 final List<Dependency> added = engine.scan(file); +350 return added; +351 } +352 +353 /** +354 * Retrieves the next temporary directory to extract an archive too. +355 * +356 * @return a directory +357 * @throws AnalysisException thrown if unable to create temporary directory +358 */ +359 private File getNextTempDirectory() throws AnalysisException { +360 dirCount += 1; +361 final File directory = new File(tempFileLocation, String.valueOf(dirCount)); +362 //getting an exception for some directories not being able to be created; might be because the directory already exists? +363 if (directory.exists()) { +364 return getNextTempDirectory(); +365 } +366 if (!directory.mkdirs()) { +367 final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath()); +368 throw new AnalysisException(msg); +369 } +370 return directory; +371 } +372 +373 /** +374 * Extracts the contents of an archive into the specified directory. +375 * +376 * @param archive an archive file such as a WAR or EAR +377 * @param destination a directory to extract the contents to +378 * @param engine the scanning engine +379 * @throws AnalysisException thrown if the archive is not found +380 */ +381 private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException { +382 if (archive != null && destination != null) { +383 String archiveExt = FileUtils.getFileExtension(archive.getName()); +384 if (archiveExt == null) { +385 return; +386 } +387 archiveExt = archiveExt.toLowerCase(); +388 +389 final FileInputStream fis; +390 try { +391 fis = new FileInputStream(archive); +392 } catch (FileNotFoundException ex) { +393 LOGGER.debug("", ex); +394 throw new AnalysisException("Archive file was not found.", ex); +395 } +396 BufferedInputStream in = null; +397 ZipArchiveInputStream zin = null; +398 TarArchiveInputStream tin = null; +399 GzipCompressorInputStream gin = null; +400 BZip2CompressorInputStream bzin = null; +401 try { +402 if (ZIPPABLES.contains(archiveExt)) { +403 in = new BufferedInputStream(fis); +404 ensureReadableJar(archiveExt, in); +405 zin = new ZipArchiveInputStream(in); +406 extractArchive(zin, destination, engine); +407 } else if ("tar".equals(archiveExt)) { +408 in = new BufferedInputStream(fis); +409 tin = new TarArchiveInputStream(in); +410 extractArchive(tin, destination, engine); +411 } else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) { +412 final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName()); +413 final File f = new File(destination, uncompressedName); +414 if (engine.accept(f)) { +415 in = new BufferedInputStream(fis); +416 gin = new GzipCompressorInputStream(in); +417 decompressFile(gin, f); +418 } +419 } else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) { +420 final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName()); +421 final File f = new File(destination, uncompressedName); +422 if (engine.accept(f)) { +423 in = new BufferedInputStream(fis); +424 bzin = new BZip2CompressorInputStream(in); +425 decompressFile(bzin, f); +426 } +427 } +428 } catch (ArchiveExtractionException ex) { +429 LOGGER.warn("Exception extracting archive '{}'.", archive.getName()); +430 LOGGER.debug("", ex); +431 } catch (IOException ex) { +432 LOGGER.warn("Exception reading archive '{}'.", archive.getName()); +433 LOGGER.debug("", ex); +434 } finally { +435 //overly verbose and not needed... but keeping it anyway due to +436 //having issue with file handles being left open +437 close(fis); +438 close(in); +439 close(zin); +440 close(tin); +441 close(gin); +442 close(bzin); +443 } +444 } +445 } +446 +447 /** +448 * Checks if the file being scanned is a JAR that begins with '#!/bin' which +449 * indicates it is a fully executable jar. If a fully executable JAR is +450 * identified the input stream will be advanced to the start of the actual +451 * JAR file ( skipping the script). +452 * +453 * @see +454 * <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing +455 * Spring Boot Applications</a> +456 * @param archiveExt the file extension +457 * @param in the input stream +458 * @throws IOException thrown if there is an error reading the stream +459 */ +460 private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException { +461 if ("jar".equals(archiveExt) && in.markSupported()) { +462 in.mark(7); +463 final byte[] b = new byte[7]; +464 final int read = in.read(b); +465 if (read == 7 +466 && b[0] == '#' +467 && b[1] == '!' +468 && b[2] == '/' +469 && b[3] == 'b' +470 && b[4] == 'i' +471 && b[5] == 'n' +472 && b[6] == '/') { +473 boolean stillLooking = true; +474 int chr, nxtChr; +475 while (stillLooking && (chr = in.read()) != -1) { +476 if (chr == '\n' || chr == '\r') { +477 in.mark(4); +478 if ((chr = in.read()) != -1) { +479 if (chr == 'P' && (chr = in.read()) != -1) { +480 if (chr == 'K' && (chr = in.read()) != -1) { +481 if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) { +482 if (nxtChr == chr + 1) { +483 stillLooking = false; +484 in.reset(); +485 } +486 } +487 } +488 } +489 } +490 } +491 } +492 } else { +493 in.reset(); +494 } +495 } +496 } +497 +498 /** +499 * Extracts files from an archive. +500 * +501 * @param input the archive to extract files from +502 * @param destination the location to write the files too +503 * @param engine the dependency-check engine +504 * @throws ArchiveExtractionException thrown if there is an exception +505 * extracting files from the archive +506 */ +507 private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException { +508 ArchiveEntry entry; +509 try { +510 while ((entry = input.getNextEntry()) != null) { +511 final File file = new File(destination, entry.getName()); +512 if (entry.isDirectory()) { +513 if (!file.exists() && !file.mkdirs()) { +514 final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath()); +515 throw new AnalysisException(msg); +516 } +517 } else if (engine.accept(file)) { +518 extractAcceptedFile(input, file); +519 } +520 } +521 } catch (Throwable ex) { +522 throw new ArchiveExtractionException(ex); +523 } finally { +524 close(input); +525 } +526 } +527 +528 /** +529 * Extracts a file from an archive. +530 * +531 * @param input the archives input stream +532 * @param file the file to extract +533 * @throws AnalysisException thrown if there is an error +534 */ +535 private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException { +536 LOGGER.debug("Extracting '{}'", file.getPath()); +537 FileOutputStream fos = null; +538 try { +539 final File parent = file.getParentFile(); +540 if (!parent.isDirectory() && !parent.mkdirs()) { +541 final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath()); +542 throw new AnalysisException(msg); +543 } +544 fos = new FileOutputStream(file); +545 IOUtils.copy(input, fos); +546 } catch (FileNotFoundException ex) { +547 LOGGER.debug("", ex); +548 final String msg = String.format("Unable to find file '%s'.", file.getName()); +549 throw new AnalysisException(msg, ex); +550 } catch (IOException ex) { +551 LOGGER.debug("", ex); +552 final String msg = String.format("IO Exception while parsing file '%s'.", file.getName()); +553 throw new AnalysisException(msg, ex); +554 } finally { +555 close(fos); +556 } +557 } +558 +559 /** +560 * Decompresses a file. +561 * +562 * @param inputStream the compressed file +563 * @param outputFile the location to write the decompressed file +564 * @throws ArchiveExtractionException thrown if there is an exception +565 * decompressing the file +566 */ +567 private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException { +568 LOGGER.debug("Decompressing '{}'", outputFile.getPath()); +569 FileOutputStream out = null; +570 try { +571 out = new FileOutputStream(outputFile); +572 IOUtils.copy(inputStream, out); +573 } catch (FileNotFoundException ex) { +574 LOGGER.debug("", ex); +575 throw new ArchiveExtractionException(ex); +576 } catch (IOException ex) { +577 LOGGER.debug("", ex); +578 throw new ArchiveExtractionException(ex); +579 } finally { +580 close(out); +581 } +582 } +583 +584 /** +585 * Close the given {@link Closeable} instance, ignoring nulls, and logging +586 * any thrown {@link IOException}. +587 * +588 * @param closeable to be closed +589 */ +590 private static void close(Closeable closeable) { +591 if (null != closeable) { +592 try { +593 closeable.close(); +594 } catch (IOException ex) { +595 LOGGER.trace("", ex); +596 } +597 } +598 } +599 +600 /** +601 * Attempts to determine if a zip file is actually a JAR file. +602 * +603 * @param dependency the dependency to check +604 * @return true if the dependency appears to be a JAR file; otherwise false +605 */ +606 private boolean isZipFileActuallyJarFile(Dependency dependency) { +607 boolean isJar = false; +608 ZipFile zip = null; +609 try { +610 zip = new ZipFile(dependency.getActualFilePath()); +611 if (zip.getEntry("META-INF/MANIFEST.MF") != null +612 || zip.getEntry("META-INF/maven") != null) { +613 final Enumeration<ZipArchiveEntry> entries = zip.getEntries(); +614 while (entries.hasMoreElements()) { +615 final ZipArchiveEntry entry = entries.nextElement(); +616 if (!entry.isDirectory()) { +617 final String name = entry.getName().toLowerCase(); +618 if (name.endsWith(".class")) { +619 isJar = true; +620 break; +621 } +622 } +623 } +624 } +625 } catch (IOException ex) { +626 LOGGER.debug("Unable to unzip zip file '{}'", dependency.getFilePath(), ex); +627 } finally { +628 ZipFile.closeQuietly(zip); +629 } +630 +631 return isJar; +632 } +633 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html index 34acd7d46..1be2f72b4 100644 --- a/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.html @@ -81,302 +81,298 @@ 73 */ 74 private File grokAssemblyExe = null; 75 /** -76 * The DocumentBuilder for parsing the XML +76 * Logger 77 */ -78 private DocumentBuilder builder; -79 /** -80 * Logger -81 */ -82 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class); -83 -84 /** -85 * Builds the beginnings of a List for ProcessBuilder -86 * -87 * @return the list of arguments to begin populating the ProcessBuilder -88 */ -89 protected List<String> buildArgumentList() { -90 // Use file.separator as a wild guess as to whether this is Windows -91 final List<String> args = new ArrayList<String>(); -92 if (!SystemUtils.IS_OS_WINDOWS) { -93 if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) { -94 args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH)); -95 } else if (isInPath("mono")) { -96 args.add("mono"); -97 } else { -98 return null; -99 } -100 } -101 args.add(grokAssemblyExe.getPath()); -102 return args; -103 } -104 -105 /** -106 * Performs the analysis on a single Dependency. -107 * -108 * @param dependency the dependency to analyze -109 * @param engine the engine to perform the analysis under -110 * @throws AnalysisException if anything goes sideways -111 */ -112 @Override -113 public void analyzeFileType(Dependency dependency, Engine engine) -114 throws AnalysisException { -115 if (grokAssemblyExe == null) { -116 LOGGER.warn("GrokAssembly didn't get deployed"); -117 return; -118 } -119 -120 final List<String> args = buildArgumentList(); -121 if (args == null) { -122 LOGGER.warn("Assembly Analyzer was unable to execute"); -123 return; -124 } -125 args.add(dependency.getActualFilePath()); -126 final ProcessBuilder pb = new ProcessBuilder(args); -127 Document doc = null; -128 try { -129 final Process proc = pb.start(); -130 -131 doc = builder.parse(proc.getInputStream()); -132 -133 // Try evacuating the error stream -134 final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8"); -135 if (null != errorStream && !errorStream.isEmpty()) { -136 LOGGER.warn("Error from GrokAssembly: {}", errorStream); -137 } -138 -139 int rc = 0; -140 try { -141 rc = proc.waitFor(); -142 } catch (InterruptedException ie) { -143 return; -144 } -145 if (rc == 3) { -146 LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check", -147 dependency.getActualFilePath()); -148 return; -149 } else if (rc != 0) { -150 LOGGER.warn("Return code {} from GrokAssembly", rc); -151 } -152 -153 final XPath xpath = XPathFactory.newInstance().newXPath(); -154 -155 // First, see if there was an error -156 final String error = xpath.evaluate("/assembly/error", doc); -157 if (error != null && !error.isEmpty()) { -158 throw new AnalysisException(error); -159 } -160 -161 final String version = xpath.evaluate("/assembly/version", doc); -162 if (version != null) { -163 dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version", -164 version, Confidence.HIGHEST)); -165 } -166 -167 final String vendor = xpath.evaluate("/assembly/company", doc); -168 if (vendor != null) { -169 dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor", -170 vendor, Confidence.HIGH)); -171 } -172 -173 final String product = xpath.evaluate("/assembly/product", doc); -174 if (product != null) { -175 dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product", -176 product, Confidence.HIGH)); -177 } -178 -179 } catch (IOException ioe) { -180 throw new AnalysisException(ioe); -181 } catch (SAXException saxe) { -182 throw new AnalysisException("Couldn't parse GrokAssembly result", saxe); -183 } catch (XPathExpressionException xpe) { -184 // This shouldn't happen -185 throw new AnalysisException(xpe); -186 } -187 } -188 -189 /** -190 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a -191 * temporary location. -192 * -193 * @throws InitializationException thrown if anything goes wrong -194 */ -195 @Override -196 public void initializeFileTypeAnalyzer() throws InitializationException { -197 final File tempFile; -198 try { -199 tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory()); -200 } catch (IOException ex) { -201 setEnabled(false); -202 throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex); -203 } -204 FileOutputStream fos = null; -205 InputStream is = null; -206 try { -207 fos = new FileOutputStream(tempFile); -208 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe"); -209 IOUtils.copy(is, fos); -210 -211 grokAssemblyExe = tempFile; -212 LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath()); -213 } catch (IOException ioe) { -214 this.setEnabled(false); -215 LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage()); -216 throw new InitializationException("Could not extract GrokAssembly.exe", ioe); -217 } finally { -218 if (fos != null) { -219 try { -220 fos.close(); -221 } catch (Throwable e) { -222 LOGGER.debug("Error closing output stream"); -223 } -224 } -225 if (is != null) { -226 try { -227 is.close(); -228 } catch (Throwable e) { -229 LOGGER.debug("Error closing input stream"); -230 } -231 } -232 } -233 -234 // Now, need to see if GrokAssembly actually runs from this location. -235 final List<String> args = buildArgumentList(); -236 //TODO this creaes an "unreported" error - if someone doesn't look -237 // at the command output this could easily be missed (especially in an -238 // Ant or Mmaven build. -239 // -240 // We need to create a non-fatal warning error type that will -241 // get added to the report. -242 //TOOD this idea needs to get replicated to the bundle audit analyzer. -243 if (args == null) { -244 setEnabled(false); -245 LOGGER.error("----------------------------------------------------"); -246 LOGGER.error(".NET Assembly Analyzer could not be initialized and at least one " -247 + "'exe' or 'dll' was scanned. The 'mono' executale could not be found on " -248 + "the path; either disable the Assembly Analyzer or configure the path mono."); -249 LOGGER.error("----------------------------------------------------"); -250 return; -251 } -252 try { -253 final ProcessBuilder pb = new ProcessBuilder(args); -254 final Process p = pb.start(); -255 // Try evacuating the error stream -256 IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM); -257 -258 final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream()); -259 final XPath xpath = XPathFactory.newInstance().newXPath(); -260 final String error = xpath.evaluate("/assembly/error", doc); -261 if (p.waitFor() != 1 || error == null || error.isEmpty()) { -262 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details."); -263 LOGGER.debug("GrokAssembly.exe is not working properly"); -264 grokAssemblyExe = null; -265 setEnabled(false); -266 throw new InitializationException("Could not execute .NET AssemblyAnalyzer"); -267 } -268 } catch (InitializationException e) { -269 setEnabled(false); -270 throw e; -271 } catch (Throwable e) { -272 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n" -273 + "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details."); -274 LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage()); -275 setEnabled(false); -276 throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e); -277 } -278 try { -279 builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); -280 } catch (ParserConfigurationException ex) { -281 setEnabled(false); -282 throw new InitializationException("Error initializing the assembly analyzer", ex); -283 } -284 } -285 -286 /** -287 * Removes resources used from the local file system. -288 * -289 * @throws Exception thrown if there is a problem closing the analyzer -290 */ -291 @Override -292 public void close() throws Exception { -293 super.close(); -294 try { -295 if (grokAssemblyExe != null && !grokAssemblyExe.delete()) { -296 LOGGER.debug("Unable to delete temporary GrokAssembly.exe; attempting delete on exit"); -297 grokAssemblyExe.deleteOnExit(); -298 } -299 } catch (SecurityException se) { -300 LOGGER.debug("Can't delete temporary GrokAssembly.exe"); -301 grokAssemblyExe.deleteOnExit(); -302 } -303 } -304 -305 /** -306 * The File Filter used to filter supported extensions. -307 */ -308 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions( -309 SUPPORTED_EXTENSIONS).build(); -310 -311 @Override -312 protected FileFilter getFileFilter() { -313 return FILTER; -314 } -315 -316 /** -317 * Gets this analyzer's name. -318 * -319 * @return the analyzer name -320 */ -321 @Override -322 public String getName() { -323 return ANALYZER_NAME; -324 } -325 -326 /** -327 * Returns the phase this analyzer runs under. -328 * -329 * @return the phase this runs under -330 */ -331 @Override -332 public AnalysisPhase getAnalysisPhase() { -333 return ANALYSIS_PHASE; -334 } -335 -336 /** -337 * Returns the key used in the properties file to reference the analyzer's -338 * enabled property. -339 * -340 * @return the analyzer's enabled property setting key -341 */ -342 @Override -343 protected String getAnalyzerEnabledSettingKey() { -344 return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED; -345 } -346 -347 /** -348 * Tests to see if a file is in the system path. <b>Note</b> - the current -349 * implementation only works on non-windows platforms. For purposes of the -350 * AssemblyAnalyzer this is okay as this is only needed on Mac/*nix. -351 * -352 * @param file the executable to look for -353 * @return <code>true</code> if the file exists; otherwise -354 * <code>false</code> -355 */ -356 private boolean isInPath(String file) { -357 final ProcessBuilder pb = new ProcessBuilder("which", file); -358 try { -359 final Process proc = pb.start(); -360 final int retCode = proc.waitFor(); -361 if (retCode == 0) { -362 return true; -363 } -364 } catch (IOException ex) { -365 LOGGER.debug("Path seach failed for " + file); -366 } catch (InterruptedException ex) { -367 LOGGER.debug("Path seach failed for " + file); -368 } -369 return false; -370 } -371 } +78 private static final Logger LOGGER = LoggerFactory.getLogger(AssemblyAnalyzer.class); +79 +80 /** +81 * Builds the beginnings of a List for ProcessBuilder +82 * +83 * @return the list of arguments to begin populating the ProcessBuilder +84 */ +85 protected List<String> buildArgumentList() { +86 // Use file.separator as a wild guess as to whether this is Windows +87 final List<String> args = new ArrayList<String>(); +88 if (!SystemUtils.IS_OS_WINDOWS) { +89 if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) { +90 args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH)); +91 } else if (isInPath("mono")) { +92 args.add("mono"); +93 } else { +94 return null; +95 } +96 } +97 args.add(grokAssemblyExe.getPath()); +98 return args; +99 } +100 +101 /** +102 * Performs the analysis on a single Dependency. +103 * +104 * @param dependency the dependency to analyze +105 * @param engine the engine to perform the analysis under +106 * @throws AnalysisException if anything goes sideways +107 */ +108 @Override +109 public void analyzeFileType(Dependency dependency, Engine engine) +110 throws AnalysisException { +111 if (grokAssemblyExe == null) { +112 LOGGER.warn("GrokAssembly didn't get deployed"); +113 return; +114 } +115 +116 final List<String> args = buildArgumentList(); +117 if (args == null) { +118 LOGGER.warn("Assembly Analyzer was unable to execute"); +119 return; +120 } +121 args.add(dependency.getActualFilePath()); +122 final ProcessBuilder pb = new ProcessBuilder(args); +123 Document doc = null; +124 try { +125 final Process proc = pb.start(); +126 +127 final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); +128 doc = builder.parse(proc.getInputStream()); +129 +130 // Try evacuating the error stream +131 final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8"); +132 if (null != errorStream && !errorStream.isEmpty()) { +133 LOGGER.warn("Error from GrokAssembly: {}", errorStream); +134 } +135 +136 int rc = 0; +137 try { +138 rc = proc.waitFor(); +139 } catch (InterruptedException ie) { +140 return; +141 } +142 if (rc == 3) { +143 LOGGER.debug("{} is not a .NET assembly or executable and as such cannot be analyzed by dependency-check", +144 dependency.getActualFilePath()); +145 return; +146 } else if (rc != 0) { +147 LOGGER.warn("Return code {} from GrokAssembly", rc); +148 } +149 +150 final XPath xpath = XPathFactory.newInstance().newXPath(); +151 +152 // First, see if there was an error +153 final String error = xpath.evaluate("/assembly/error", doc); +154 if (error != null && !error.isEmpty()) { +155 throw new AnalysisException(error); +156 } +157 +158 final String version = xpath.evaluate("/assembly/version", doc); +159 if (version != null) { +160 dependency.getVersionEvidence().addEvidence(new Evidence("grokassembly", "version", +161 version, Confidence.HIGHEST)); +162 } +163 +164 final String vendor = xpath.evaluate("/assembly/company", doc); +165 if (vendor != null) { +166 dependency.getVendorEvidence().addEvidence(new Evidence("grokassembly", "vendor", +167 vendor, Confidence.HIGH)); +168 } +169 +170 final String product = xpath.evaluate("/assembly/product", doc); +171 if (product != null) { +172 dependency.getProductEvidence().addEvidence(new Evidence("grokassembly", "product", +173 product, Confidence.HIGH)); +174 } +175 +176 } catch (ParserConfigurationException pce) { +177 throw new AnalysisException("Error initializing the assembly analyzer", pce); +178 } catch (IOException ioe) { +179 throw new AnalysisException(ioe); +180 } catch (SAXException saxe) { +181 throw new AnalysisException("Couldn't parse GrokAssembly result", saxe); +182 } catch (XPathExpressionException xpe) { +183 // This shouldn't happen +184 throw new AnalysisException(xpe); +185 } +186 } +187 +188 /** +189 * Initialize the analyzer. In this case, extract GrokAssembly.exe to a +190 * temporary location. +191 * +192 * @throws InitializationException thrown if anything goes wrong +193 */ +194 @Override +195 public void initializeFileTypeAnalyzer() throws InitializationException { +196 final File tempFile; +197 try { +198 tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory()); +199 } catch (IOException ex) { +200 setEnabled(false); +201 throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex); +202 } +203 FileOutputStream fos = null; +204 InputStream is = null; +205 try { +206 fos = new FileOutputStream(tempFile); +207 is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe"); +208 IOUtils.copy(is, fos); +209 +210 grokAssemblyExe = tempFile; +211 LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath()); +212 } catch (IOException ioe) { +213 this.setEnabled(false); +214 LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage()); +215 throw new InitializationException("Could not extract GrokAssembly.exe", ioe); +216 } finally { +217 if (fos != null) { +218 try { +219 fos.close(); +220 } catch (Throwable e) { +221 LOGGER.debug("Error closing output stream"); +222 } +223 } +224 if (is != null) { +225 try { +226 is.close(); +227 } catch (Throwable e) { +228 LOGGER.debug("Error closing input stream"); +229 } +230 } +231 } +232 +233 // Now, need to see if GrokAssembly actually runs from this location. +234 final List<String> args = buildArgumentList(); +235 //TODO this creates an "unreported" error - if someone doesn't look +236 // at the command output this could easily be missed (especially in an +237 // Ant or Maven build. +238 // +239 // We need to create a non-fatal warning error type that will +240 // get added to the report. +241 //TOOD this idea needs to get replicated to the bundle audit analyzer. +242 if (args == null) { +243 setEnabled(false); +244 LOGGER.error("----------------------------------------------------"); +245 LOGGER.error(".NET Assembly Analyzer could not be initialized and at least one " +246 + "'exe' or 'dll' was scanned. The 'mono' executable could not be found on " +247 + "the path; either disable the Assembly Analyzer or configure the path mono."); +248 LOGGER.error("----------------------------------------------------"); +249 return; +250 } +251 try { +252 final ProcessBuilder pb = new ProcessBuilder(args); +253 final Process p = pb.start(); +254 // Try evacuating the error stream +255 IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM); +256 +257 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +258 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +259 final DocumentBuilder builder = factory.newDocumentBuilder(); +260 final Document doc = builder.parse(p.getInputStream()); +261 final XPath xpath = XPathFactory.newInstance().newXPath(); +262 final String error = xpath.evaluate("/assembly/error", doc); +263 if (p.waitFor() != 1 || error == null || error.isEmpty()) { +264 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details."); +265 LOGGER.debug("GrokAssembly.exe is not working properly"); +266 grokAssemblyExe = null; +267 setEnabled(false); +268 throw new InitializationException("Could not execute .NET AssemblyAnalyzer"); +269 } +270 } catch (InitializationException e) { +271 setEnabled(false); +272 throw e; +273 } catch (Throwable e) { +274 LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n" +275 + "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details."); +276 LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage()); +277 setEnabled(false); +278 throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e); +279 } +280 } +281 +282 /** +283 * Removes resources used from the local file system. +284 * +285 * @throws Exception thrown if there is a problem closing the analyzer +286 */ +287 @Override +288 public void close() throws Exception { +289 super.close(); +290 try { +291 if (grokAssemblyExe != null && !grokAssemblyExe.delete()) { +292 LOGGER.debug("Unable to delete temporary GrokAssembly.exe; attempting delete on exit"); +293 grokAssemblyExe.deleteOnExit(); +294 } +295 } catch (SecurityException se) { +296 LOGGER.debug("Can't delete temporary GrokAssembly.exe"); +297 grokAssemblyExe.deleteOnExit(); +298 } +299 } +300 +301 /** +302 * The File Filter used to filter supported extensions. +303 */ +304 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions( +305 SUPPORTED_EXTENSIONS).build(); +306 +307 @Override +308 protected FileFilter getFileFilter() { +309 return FILTER; +310 } +311 +312 /** +313 * Gets this analyzer's name. +314 * +315 * @return the analyzer name +316 */ +317 @Override +318 public String getName() { +319 return ANALYZER_NAME; +320 } +321 +322 /** +323 * Returns the phase this analyzer runs under. +324 * +325 * @return the phase this runs under +326 */ +327 @Override +328 public AnalysisPhase getAnalysisPhase() { +329 return ANALYSIS_PHASE; +330 } +331 +332 /** +333 * Returns the key used in the properties file to reference the analyzer's +334 * enabled property. +335 * +336 * @return the analyzer's enabled property setting key +337 */ +338 @Override +339 protected String getAnalyzerEnabledSettingKey() { +340 return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED; +341 } +342 +343 /** +344 * Tests to see if a file is in the system path. <b>Note</b> - the current +345 * implementation only works on non-windows platforms. For purposes of the +346 * AssemblyAnalyzer this is okay as this is only needed on Mac/*nix. +347 * +348 * @param file the executable to look for +349 * @return <code>true</code> if the file exists; otherwise +350 * <code>false</code> +351 */ +352 private boolean isInPath(String file) { +353 final ProcessBuilder pb = new ProcessBuilder("which", file); +354 try { +355 final Process proc = pb.start(); +356 final int retCode = proc.waitFor(); +357 if (retCode == 0) { +358 return true; +359 } +360 } catch (IOException ex) { +361 LOGGER.debug("Path seach failed for " + file); +362 } catch (InterruptedException ex) { +363 LOGGER.debug("Path seach failed for " + file); +364 } +365 return false; +366 } +367 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.html index 3ca94822e..91d72c650 100644 --- a/xref/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.html @@ -39,257 +39,251 @@ 31 import java.io.FileFilter; 32 import java.io.IOException; 33 import java.nio.charset.Charset; -34 import java.util.ArrayList; -35 import java.util.List; -36 import java.util.regex.Matcher; -37 import java.util.regex.Pattern; -38 import org.owasp.dependencycheck.exception.InitializationException; -39 -40 /** -41 * Used to analyze Autoconf input files named configure.ac or configure.in. -42 * Files simply named "configure" are also analyzed, assuming they are generated -43 * by Autoconf, and contain certain special package descriptor variables. -44 * -45 * @author Dale Visser -46 * @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project -47 * - Free Software Foundation (FSF)</a> -48 */ -49 @Experimental -50 public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer { -51 -52 /** -53 * Autoconf output filename. -54 */ -55 private static final String CONFIGURE = "configure"; -56 -57 /** -58 * Autoconf input filename. -59 */ -60 private static final String CONFIGURE_IN = "configure.in"; -61 -62 /** -63 * Autoconf input filename. -64 */ -65 private static final String CONFIGURE_AC = "configure.ac"; -66 -67 /** -68 * The name of the analyzer. -69 */ -70 private static final String ANALYZER_NAME = "Autoconf Analyzer"; -71 -72 /** -73 * The phase that this analyzer is intended to run in. -74 */ -75 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; -76 -77 /** -78 * The set of file extensions supported by this analyzer. -79 */ -80 private static final String[] EXTENSIONS = {"ac", "in"}; -81 -82 /** -83 * Matches AC_INIT variables in the output configure script. -84 */ -85 private static final Pattern PACKAGE_VAR = Pattern.compile( -86 "PACKAGE_(.+?)='(.*?)'", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); -87 -88 /** -89 * Matches AC_INIT statement in configure.ac file. -90 */ -91 private static final Pattern AC_INIT_PATTERN; -92 -93 static { -94 // each instance of param or sep_param has a capture group -95 final String param = "\\[{0,2}(.+?)\\]{0,2}"; -96 final String sepParam = "\\s*,\\s*" + param; -97 // Group 1: Package -98 // Group 2: Version -99 // Group 3: optional -100 // Group 4: Bug report address (if it exists) -101 // Group 5: optional -102 // Group 6: Tarname (if it exists) -103 // Group 7: optional -104 // Group 8: URL (if it exists) -105 AC_INIT_PATTERN = Pattern.compile(String.format( -106 "AC_INIT\\(%s%s(%s)?(%s)?(%s)?\\s*\\)", param, sepParam, -107 sepParam, sepParam, sepParam), Pattern.DOTALL -108 | Pattern.CASE_INSENSITIVE); -109 } -110 -111 /** -112 * The file filter used to determine which files this analyzer supports. -113 */ -114 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(CONFIGURE).addExtensions( -115 EXTENSIONS).build(); -116 -117 /** -118 * Returns the FileFilter -119 * -120 * @return the FileFilter -121 */ -122 @Override -123 protected FileFilter getFileFilter() { -124 return FILTER; -125 } -126 -127 /** -128 * Returns the name of the analyzer. -129 * -130 * @return the name of the analyzer. -131 */ -132 @Override -133 public String getName() { -134 return ANALYZER_NAME; -135 } -136 -137 /** -138 * Returns the phase that the analyzer is intended to run in. -139 * -140 * @return the phase that the analyzer is intended to run in. -141 */ -142 @Override -143 public AnalysisPhase getAnalysisPhase() { -144 return ANALYSIS_PHASE; -145 } -146 -147 /** -148 * Returns the key used in the properties file to reference the analyzer's -149 * enabled property. -150 * -151 * @return the analyzer's enabled property setting key -152 */ -153 @Override -154 protected String getAnalyzerEnabledSettingKey() { -155 return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED; -156 } -157 -158 @Override -159 protected void analyzeFileType(Dependency dependency, Engine engine) -160 throws AnalysisException { -161 final File actualFile = dependency.getActualFile(); -162 final String name = actualFile.getName(); -163 if (name.startsWith(CONFIGURE)) { -164 final File parent = actualFile.getParentFile(); -165 final String parentName = parent.getName(); -166 dependency.setDisplayFileName(parentName + "/" + name); -167 final boolean isOutputScript = CONFIGURE.equals(name); -168 if (isOutputScript || CONFIGURE_AC.equals(name) -169 || CONFIGURE_IN.equals(name)) { -170 final String contents = getFileContents(actualFile); -171 if (!contents.isEmpty()) { -172 if (isOutputScript) { -173 extractConfigureScriptEvidence(dependency, name, -174 contents); -175 } else { -176 gatherEvidence(dependency, name, contents); -177 } -178 } -179 } -180 } else { -181 // copy, alter and set in case some other thread is iterating over -182 final List<Dependency> dependencies = new ArrayList<Dependency>( -183 engine.getDependencies()); -184 dependencies.remove(dependency); -185 engine.setDependencies(dependencies); -186 } -187 } -188 -189 /** -190 * Extracts evidence from the configuration. -191 * -192 * @param dependency the dependency being analyzed -193 * @param name the name of the source of evidence -194 * @param contents the contents to analyze for evidence -195 */ -196 private void extractConfigureScriptEvidence(Dependency dependency, -197 final String name, final String contents) { -198 final Matcher matcher = PACKAGE_VAR.matcher(contents); -199 while (matcher.find()) { -200 final String variable = matcher.group(1); -201 final String value = matcher.group(2); -202 if (!value.isEmpty()) { -203 if (variable.endsWith("NAME")) { -204 dependency.getProductEvidence().addEvidence(name, variable, -205 value, Confidence.HIGHEST); -206 } else if ("VERSION".equals(variable)) { -207 dependency.getVersionEvidence().addEvidence(name, variable, -208 value, Confidence.HIGHEST); -209 } else if ("BUGREPORT".equals(variable)) { -210 dependency.getVendorEvidence().addEvidence(name, variable, -211 value, Confidence.HIGH); -212 } else if ("URL".equals(variable)) { -213 dependency.getVendorEvidence().addEvidence(name, variable, -214 value, Confidence.HIGH); -215 } -216 } -217 } -218 } -219 -220 /** -221 * Retrieves the contents of a given file. -222 * -223 * @param actualFile the file to read -224 * @return the contents of the file -225 * @throws AnalysisException thrown if there is an IO Exception -226 */ -227 private String getFileContents(final File actualFile) -228 throws AnalysisException { -229 try { -230 return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim(); -231 } catch (IOException e) { -232 throw new AnalysisException( -233 "Problem occurred while reading dependency file.", e); -234 } -235 } -236 -237 /** -238 * Gathers evidence from a given file -239 * -240 * @param dependency the dependency to add evidence to -241 * @param name the source of the evidence -242 * @param contents the evidence to analyze -243 */ -244 private void gatherEvidence(Dependency dependency, final String name, -245 String contents) { -246 final Matcher matcher = AC_INIT_PATTERN.matcher(contents); -247 if (matcher.find()) { -248 final EvidenceCollection productEvidence = dependency -249 .getProductEvidence(); -250 productEvidence.addEvidence(name, "Package", matcher.group(1), -251 Confidence.HIGHEST); -252 dependency.getVersionEvidence().addEvidence(name, -253 "Package Version", matcher.group(2), Confidence.HIGHEST); -254 final EvidenceCollection vendorEvidence = dependency -255 .getVendorEvidence(); -256 if (null != matcher.group(3)) { -257 vendorEvidence.addEvidence(name, "Bug report address", -258 matcher.group(4), Confidence.HIGH); -259 } -260 if (null != matcher.group(5)) { -261 productEvidence.addEvidence(name, "Tarname", matcher.group(6), -262 Confidence.HIGH); -263 } -264 if (null != matcher.group(7)) { -265 final String url = matcher.group(8); -266 if (UrlStringUtils.isUrl(url)) { -267 vendorEvidence.addEvidence(name, "URL", url, -268 Confidence.HIGH); -269 } -270 } -271 } -272 } -273 -274 /** -275 * Initializes the file type analyzer. -276 * -277 * @throws InitializationException thrown if there is an exception during -278 * initialization -279 */ -280 @Override -281 protected void initializeFileTypeAnalyzer() throws InitializationException { -282 // No initialization needed. -283 } -284 } +34 import java.util.regex.Matcher; +35 import java.util.regex.Pattern; +36 import org.owasp.dependencycheck.exception.InitializationException; +37 +38 /** +39 * Used to analyze Autoconf input files named configure.ac or configure.in. +40 * Files simply named "configure" are also analyzed, assuming they are generated +41 * by Autoconf, and contain certain special package descriptor variables. +42 * +43 * @author Dale Visser +44 * @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project +45 * - Free Software Foundation (FSF)</a> +46 */ +47 @Experimental +48 public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer { +49 +50 /** +51 * Autoconf output filename. +52 */ +53 private static final String CONFIGURE = "configure"; +54 +55 /** +56 * Autoconf input filename. +57 */ +58 private static final String CONFIGURE_IN = "configure.in"; +59 +60 /** +61 * Autoconf input filename. +62 */ +63 private static final String CONFIGURE_AC = "configure.ac"; +64 +65 /** +66 * The name of the analyzer. +67 */ +68 private static final String ANALYZER_NAME = "Autoconf Analyzer"; +69 +70 /** +71 * The phase that this analyzer is intended to run in. +72 */ +73 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; +74 +75 /** +76 * The set of file extensions supported by this analyzer. +77 */ +78 private static final String[] EXTENSIONS = {"ac", "in"}; +79 +80 /** +81 * Matches AC_INIT variables in the output configure script. +82 */ +83 private static final Pattern PACKAGE_VAR = Pattern.compile( +84 "PACKAGE_(.+?)='(.*?)'", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); +85 +86 /** +87 * Matches AC_INIT statement in configure.ac file. +88 */ +89 private static final Pattern AC_INIT_PATTERN; +90 +91 static { +92 // each instance of param or sep_param has a capture group +93 final String param = "\\[{0,2}(.+?)\\]{0,2}"; +94 final String sepParam = "\\s*,\\s*" + param; +95 // Group 1: Package +96 // Group 2: Version +97 // Group 3: optional +98 // Group 4: Bug report address (if it exists) +99 // Group 5: optional +100 // Group 6: Tarname (if it exists) +101 // Group 7: optional +102 // Group 8: URL (if it exists) +103 AC_INIT_PATTERN = Pattern.compile(String.format( +104 "AC_INIT\\(%s%s(%s)?(%s)?(%s)?\\s*\\)", param, sepParam, +105 sepParam, sepParam, sepParam), Pattern.DOTALL +106 | Pattern.CASE_INSENSITIVE); +107 } +108 +109 /** +110 * The file filter used to determine which files this analyzer supports. +111 */ +112 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(CONFIGURE).addExtensions( +113 EXTENSIONS).build(); +114 +115 /** +116 * Returns the FileFilter +117 * +118 * @return the FileFilter +119 */ +120 @Override +121 protected FileFilter getFileFilter() { +122 return FILTER; +123 } +124 +125 /** +126 * Returns the name of the analyzer. +127 * +128 * @return the name of the analyzer. +129 */ +130 @Override +131 public String getName() { +132 return ANALYZER_NAME; +133 } +134 +135 /** +136 * Returns the phase that the analyzer is intended to run in. +137 * +138 * @return the phase that the analyzer is intended to run in. +139 */ +140 @Override +141 public AnalysisPhase getAnalysisPhase() { +142 return ANALYSIS_PHASE; +143 } +144 +145 /** +146 * Returns the key used in the properties file to reference the analyzer's +147 * enabled property. +148 * +149 * @return the analyzer's enabled property setting key +150 */ +151 @Override +152 protected String getAnalyzerEnabledSettingKey() { +153 return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED; +154 } +155 +156 @Override +157 protected void analyzeFileType(Dependency dependency, Engine engine) +158 throws AnalysisException { +159 final File actualFile = dependency.getActualFile(); +160 final String name = actualFile.getName(); +161 if (name.startsWith(CONFIGURE)) { +162 final File parent = actualFile.getParentFile(); +163 final String parentName = parent.getName(); +164 dependency.setDisplayFileName(parentName + "/" + name); +165 final boolean isOutputScript = CONFIGURE.equals(name); +166 if (isOutputScript || CONFIGURE_AC.equals(name) +167 || CONFIGURE_IN.equals(name)) { +168 final String contents = getFileContents(actualFile); +169 if (!contents.isEmpty()) { +170 if (isOutputScript) { +171 extractConfigureScriptEvidence(dependency, name, +172 contents); +173 } else { +174 gatherEvidence(dependency, name, contents); +175 } +176 } +177 } +178 } else { +179 engine.getDependencies().remove(dependency); +180 } +181 } +182 +183 /** +184 * Extracts evidence from the configuration. +185 * +186 * @param dependency the dependency being analyzed +187 * @param name the name of the source of evidence +188 * @param contents the contents to analyze for evidence +189 */ +190 private void extractConfigureScriptEvidence(Dependency dependency, +191 final String name, final String contents) { +192 final Matcher matcher = PACKAGE_VAR.matcher(contents); +193 while (matcher.find()) { +194 final String variable = matcher.group(1); +195 final String value = matcher.group(2); +196 if (!value.isEmpty()) { +197 if (variable.endsWith("NAME")) { +198 dependency.getProductEvidence().addEvidence(name, variable, +199 value, Confidence.HIGHEST); +200 } else if ("VERSION".equals(variable)) { +201 dependency.getVersionEvidence().addEvidence(name, variable, +202 value, Confidence.HIGHEST); +203 } else if ("BUGREPORT".equals(variable)) { +204 dependency.getVendorEvidence().addEvidence(name, variable, +205 value, Confidence.HIGH); +206 } else if ("URL".equals(variable)) { +207 dependency.getVendorEvidence().addEvidence(name, variable, +208 value, Confidence.HIGH); +209 } +210 } +211 } +212 } +213 +214 /** +215 * Retrieves the contents of a given file. +216 * +217 * @param actualFile the file to read +218 * @return the contents of the file +219 * @throws AnalysisException thrown if there is an IO Exception +220 */ +221 private String getFileContents(final File actualFile) +222 throws AnalysisException { +223 try { +224 return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim(); +225 } catch (IOException e) { +226 throw new AnalysisException( +227 "Problem occurred while reading dependency file.", e); +228 } +229 } +230 +231 /** +232 * Gathers evidence from a given file +233 * +234 * @param dependency the dependency to add evidence to +235 * @param name the source of the evidence +236 * @param contents the evidence to analyze +237 */ +238 private void gatherEvidence(Dependency dependency, final String name, +239 String contents) { +240 final Matcher matcher = AC_INIT_PATTERN.matcher(contents); +241 if (matcher.find()) { +242 final EvidenceCollection productEvidence = dependency +243 .getProductEvidence(); +244 productEvidence.addEvidence(name, "Package", matcher.group(1), +245 Confidence.HIGHEST); +246 dependency.getVersionEvidence().addEvidence(name, +247 "Package Version", matcher.group(2), Confidence.HIGHEST); +248 final EvidenceCollection vendorEvidence = dependency +249 .getVendorEvidence(); +250 if (null != matcher.group(3)) { +251 vendorEvidence.addEvidence(name, "Bug report address", +252 matcher.group(4), Confidence.HIGH); +253 } +254 if (null != matcher.group(5)) { +255 productEvidence.addEvidence(name, "Tarname", matcher.group(6), +256 Confidence.HIGH); +257 } +258 if (null != matcher.group(7)) { +259 final String url = matcher.group(8); +260 if (UrlStringUtils.isUrl(url)) { +261 vendorEvidence.addEvidence(name, "URL", url, +262 Confidence.HIGH); +263 } +264 } +265 } +266 } +267 +268 /** +269 * Initializes the file type analyzer. +270 * +271 * @throws InitializationException thrown if there is an exception during +272 * initialization +273 */ +274 @Override +275 protected void initializeFileTypeAnalyzer() throws InitializationException { +276 // No initialization needed. +277 } +278 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html index d9f5e97dd..008432ef0 100644 --- a/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.html @@ -101,159 +101,166 @@ 93 .addFilenames("CMakeLists.txt").build(); 94 95 /** -96 * A reference to SHA1 message digest. -97 */ -98 private static MessageDigest sha1 = null; -99 -100 static { -101 try { -102 sha1 = MessageDigest.getInstance("SHA1"); -103 } catch (NoSuchAlgorithmException e) { -104 LOGGER.error(e.getMessage()); -105 } -106 } -107 -108 /** -109 * Returns the name of the CMake analyzer. -110 * -111 * @return the name of the analyzer -112 * -113 */ -114 @Override -115 public String getName() { -116 return "CMake Analyzer"; -117 } -118 -119 /** -120 * Tell that we are used for information collection. -121 * -122 * @return INFORMATION_COLLECTION -123 */ -124 @Override -125 public AnalysisPhase getAnalysisPhase() { -126 return AnalysisPhase.INFORMATION_COLLECTION; -127 } -128 -129 /** -130 * Returns the set of supported file extensions. -131 * -132 * @return the set of supported file extensions -133 */ -134 @Override -135 protected FileFilter getFileFilter() { -136 return FILTER; -137 } -138 -139 /** -140 * No-op initializer implementation. -141 * -142 * @throws InitializationException never thrown -143 */ -144 @Override -145 protected void initializeFileTypeAnalyzer() throws InitializationException { -146 // Nothing to do here. -147 } -148 -149 /** -150 * Analyzes python packages and adds evidence to the dependency. -151 * -152 * @param dependency the dependency being analyzed -153 * @param engine the engine being used to perform the scan -154 * @throws AnalysisException thrown if there is an unrecoverable error -155 * analyzing the dependency -156 */ -157 @Override -158 protected void analyzeFileType(Dependency dependency, Engine engine) -159 throws AnalysisException { -160 final File file = dependency.getActualFile(); -161 final String parentName = file.getParentFile().getName(); -162 final String name = file.getName(); -163 dependency.setDisplayFileName(String.format("%s%c%s", parentName, File.separatorChar, name)); -164 String contents; -165 try { -166 contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); -167 } catch (IOException e) { -168 throw new AnalysisException( -169 "Problem occurred while reading dependency file.", e); -170 } -171 -172 if (StringUtils.isNotBlank(contents)) { -173 final Matcher m = PROJECT.matcher(contents); -174 int count = 0; -175 while (m.find()) { -176 count++; -177 LOGGER.debug(String.format( -178 "Found project command match with %d groups: %s", -179 m.groupCount(), m.group(0))); -180 final String group = m.group(1); -181 LOGGER.debug("Group 1: " + group); -182 dependency.getProductEvidence().addEvidence(name, "Project", -183 group, Confidence.HIGH); -184 } -185 LOGGER.debug("Found {} matches.", count); -186 analyzeSetVersionCommand(dependency, engine, contents); -187 } -188 } -189 -190 /** -191 * Extracts the version information from the contents. If more then one -192 * version is found additional dependencies are added to the dependency -193 * list. -194 * -195 * @param dependency the dependency being analyzed -196 * @param engine the dependency-check engine -197 * @param contents the version information -198 */ -199 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( -200 value = "DM_DEFAULT_ENCODING", -201 justification = "Default encoding is only used if UTF-8 is not available") -202 private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) { -203 Dependency currentDep = dependency; -204 -205 final Matcher m = SET_VERSION.matcher(contents); -206 int count = 0; -207 while (m.find()) { -208 count++; -209 LOGGER.debug("Found project command match with {} groups: {}", -210 m.groupCount(), m.group(0)); -211 String product = m.group(1); -212 final String version = m.group(2); -213 LOGGER.debug("Group 1: " + product); -214 LOGGER.debug("Group 2: " + version); -215 final String aliasPrefix = "ALIASOF_"; -216 if (product.startsWith(aliasPrefix)) { -217 product = product.replaceFirst(aliasPrefix, ""); -218 } -219 if (count > 1) { -220 //TODO - refactor so we do not assign to the parameter (checkstyle) -221 currentDep = new Dependency(dependency.getActualFile()); -222 currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product)); -223 final String filePath = String.format("%s:%s", dependency.getFilePath(), product); -224 currentDep.setFilePath(filePath); -225 -226 byte[] path; -227 try { -228 path = filePath.getBytes("UTF-8"); -229 } catch (UnsupportedEncodingException ex) { -230 path = filePath.getBytes(); -231 } -232 currentDep.setSha1sum(Checksum.getHex(sha1.digest(path))); -233 engine.getDependencies().add(currentDep); -234 } -235 final String source = currentDep.getDisplayFileName(); -236 currentDep.getProductEvidence().addEvidence(source, "Product", -237 product, Confidence.MEDIUM); -238 currentDep.getVersionEvidence().addEvidence(source, "Version", -239 version, Confidence.MEDIUM); -240 } -241 LOGGER.debug(String.format("Found %d matches.", count)); -242 } -243 -244 @Override -245 protected String getAnalyzerEnabledSettingKey() { -246 return Settings.KEYS.ANALYZER_CMAKE_ENABLED; -247 } -248 } +96 * Returns the name of the CMake analyzer. +97 * +98 * @return the name of the analyzer +99 */ +100 @Override +101 public String getName() { +102 return "CMake Analyzer"; +103 } +104 +105 /** +106 * Tell that we are used for information collection. +107 * +108 * @return INFORMATION_COLLECTION +109 */ +110 @Override +111 public AnalysisPhase getAnalysisPhase() { +112 return AnalysisPhase.INFORMATION_COLLECTION; +113 } +114 +115 /** +116 * Returns the set of supported file extensions. +117 * +118 * @return the set of supported file extensions +119 */ +120 @Override +121 protected FileFilter getFileFilter() { +122 return FILTER; +123 } +124 +125 /** +126 * Initializes the analyzer. +127 * +128 * @throws InitializationException thrown if an exception occurs getting an +129 * instance of SHA1 +130 */ +131 @Override +132 protected void initializeFileTypeAnalyzer() throws InitializationException { +133 try { +134 getSha1MessageDigest(); +135 } catch (IllegalStateException ex) { +136 setEnabled(false); +137 throw new InitializationException("Unable to create SHA1 MessageDigest", ex); +138 } +139 } +140 +141 /** +142 * Analyzes python packages and adds evidence to the dependency. +143 * +144 * @param dependency the dependency being analyzed +145 * @param engine the engine being used to perform the scan +146 * @throws AnalysisException thrown if there is an unrecoverable error +147 * analyzing the dependency +148 */ +149 @Override +150 protected void analyzeFileType(Dependency dependency, Engine engine) +151 throws AnalysisException { +152 final File file = dependency.getActualFile(); +153 final String parentName = file.getParentFile().getName(); +154 final String name = file.getName(); +155 dependency.setDisplayFileName(String.format("%s%c%s", parentName, File.separatorChar, name)); +156 String contents; +157 try { +158 contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); +159 } catch (IOException e) { +160 throw new AnalysisException( +161 "Problem occurred while reading dependency file.", e); +162 } +163 +164 if (StringUtils.isNotBlank(contents)) { +165 final Matcher m = PROJECT.matcher(contents); +166 int count = 0; +167 while (m.find()) { +168 count++; +169 LOGGER.debug(String.format( +170 "Found project command match with %d groups: %s", +171 m.groupCount(), m.group(0))); +172 final String group = m.group(1); +173 LOGGER.debug("Group 1: " + group); +174 dependency.getProductEvidence().addEvidence(name, "Project", +175 group, Confidence.HIGH); +176 } +177 LOGGER.debug("Found {} matches.", count); +178 analyzeSetVersionCommand(dependency, engine, contents); +179 } +180 } +181 +182 /** +183 * Extracts the version information from the contents. If more then one +184 * version is found additional dependencies are added to the dependency +185 * list. +186 * +187 * @param dependency the dependency being analyzed +188 * @param engine the dependency-check engine +189 * @param contents the version information +190 */ +191 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( +192 value = "DM_DEFAULT_ENCODING", +193 justification = "Default encoding is only used if UTF-8 is not available") +194 private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) { +195 Dependency currentDep = dependency; +196 +197 final Matcher m = SET_VERSION.matcher(contents); +198 int count = 0; +199 while (m.find()) { +200 count++; +201 LOGGER.debug("Found project command match with {} groups: {}", +202 m.groupCount(), m.group(0)); +203 String product = m.group(1); +204 final String version = m.group(2); +205 LOGGER.debug("Group 1: " + product); +206 LOGGER.debug("Group 2: " + version); +207 final String aliasPrefix = "ALIASOF_"; +208 if (product.startsWith(aliasPrefix)) { +209 product = product.replaceFirst(aliasPrefix, ""); +210 } +211 if (count > 1) { +212 //TODO - refactor so we do not assign to the parameter (checkstyle) +213 currentDep = new Dependency(dependency.getActualFile()); +214 currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product)); +215 final String filePath = String.format("%s:%s", dependency.getFilePath(), product); +216 currentDep.setFilePath(filePath); +217 +218 byte[] path; +219 try { +220 path = filePath.getBytes("UTF-8"); +221 } catch (UnsupportedEncodingException ex) { +222 path = filePath.getBytes(); +223 } +224 final MessageDigest sha1 = getSha1MessageDigest(); +225 currentDep.setSha1sum(Checksum.getHex(sha1.digest(path))); +226 engine.getDependencies().add(currentDep); +227 } +228 final String source = currentDep.getDisplayFileName(); +229 currentDep.getProductEvidence().addEvidence(source, "Product", +230 product, Confidence.MEDIUM); +231 currentDep.getVersionEvidence().addEvidence(source, "Version", +232 version, Confidence.MEDIUM); +233 } +234 LOGGER.debug(String.format("Found %d matches.", count)); +235 } +236 +237 @Override +238 protected String getAnalyzerEnabledSettingKey() { +239 return Settings.KEYS.ANALYZER_CMAKE_ENABLED; +240 } +241 +242 /** +243 * Returns the sha1 message digest. +244 * +245 * @return the sha1 message digest +246 */ +247 private MessageDigest getSha1MessageDigest() { +248 try { +249 return MessageDigest.getInstance("SHA1"); +250 } catch (NoSuchAlgorithmException e) { +251 LOGGER.error(e.getMessage()); +252 throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e); +253 } +254 } +255 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html index 1cd289873..96a8dd3f8 100644 --- a/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/CPEAnalyzer.html @@ -33,801 +33,802 @@ 25 import java.util.List; 26 import java.util.Set; 27 import java.util.StringTokenizer; -28 import org.apache.commons.lang3.builder.CompareToBuilder; -29 import org.apache.lucene.document.Document; -30 import org.apache.lucene.index.CorruptIndexException; -31 import org.apache.lucene.queryparser.classic.ParseException; -32 import org.apache.lucene.search.ScoreDoc; -33 import org.apache.lucene.search.TopDocs; -34 import org.owasp.dependencycheck.Engine; -35 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -36 import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex; -37 import org.owasp.dependencycheck.data.cpe.Fields; -38 import org.owasp.dependencycheck.data.cpe.IndexEntry; -39 import org.owasp.dependencycheck.data.cpe.IndexException; -40 import org.owasp.dependencycheck.data.lucene.LuceneUtils; -41 import org.owasp.dependencycheck.data.nvdcve.CveDB; -42 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -43 import org.owasp.dependencycheck.dependency.Confidence; -44 import org.owasp.dependencycheck.dependency.Dependency; -45 import org.owasp.dependencycheck.dependency.Evidence; -46 import org.owasp.dependencycheck.dependency.EvidenceCollection; -47 import org.owasp.dependencycheck.dependency.Identifier; -48 import org.owasp.dependencycheck.dependency.VulnerableSoftware; -49 import org.owasp.dependencycheck.exception.InitializationException; -50 import org.owasp.dependencycheck.utils.DependencyVersion; -51 import org.owasp.dependencycheck.utils.DependencyVersionUtil; -52 import org.slf4j.Logger; -53 import org.slf4j.LoggerFactory; -54 -55 /** -56 * CPEAnalyzer is a utility class that takes a project dependency and attempts -57 * to discern if there is an associated CPE. It uses the evidence contained -58 * within the dependency to search the Lucene index. -59 * -60 * @author Jeremy Long -61 */ -62 public class CPEAnalyzer implements Analyzer { -63 -64 /** -65 * The Logger. -66 */ -67 private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class); -68 /** -69 * The maximum number of query results to return. -70 */ -71 static final int MAX_QUERY_RESULTS = 25; -72 /** -73 * The weighting boost to give terms when constructing the Lucene query. -74 */ -75 static final String WEIGHTING_BOOST = "^5"; -76 /** -77 * A string representation of a regular expression defining characters -78 * utilized within the CPE Names. -79 */ -80 static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]"; -81 /** -82 * A string representation of a regular expression used to remove all but -83 * alpha characters. -84 */ -85 static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*"; -86 /** -87 * The additional size to add to a new StringBuilder to account for extra -88 * data that will be written into the string. -89 */ -90 static final int STRING_BUILDER_BUFFER = 20; -91 /** -92 * The CPE in memory index. -93 */ -94 private CpeMemoryIndex cpe; -95 /** -96 * The CVE Database. -97 */ -98 private CveDB cve; -99 -100 /** -101 * The URL to perform a search of the NVD CVE data at NIST. -102 */ -103 public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s"; -104 -105 /** -106 * Returns the name of this analyzer. -107 * -108 * @return the name of this analyzer. -109 */ -110 @Override -111 public String getName() { -112 return "CPE Analyzer"; -113 } -114 -115 /** -116 * Returns the analysis phase that this analyzer should run in. -117 * -118 * @return the analysis phase that this analyzer should run in. -119 */ -120 @Override -121 public AnalysisPhase getAnalysisPhase() { -122 return AnalysisPhase.IDENTIFIER_ANALYSIS; -123 } -124 -125 /** -126 * Creates the CPE Lucene Index. -127 * -128 * @throws InitializationException is thrown if there is an issue opening -129 * the index. -130 */ -131 @Override -132 public void initialize() throws InitializationException { -133 try { -134 this.open(); -135 } catch (IOException ex) { -136 LOGGER.debug("Exception initializing the Lucene Index", ex); -137 throw new InitializationException("An exception occurred initializing the Lucene Index", ex); -138 } catch (DatabaseException ex) { -139 LOGGER.debug("Exception accessing the database", ex); -140 throw new InitializationException("An exception occurred accessing the database", ex); -141 } -142 } -143 -144 /** -145 * Opens the data source. -146 * -147 * @throws IOException when the Lucene directory to be queried does not -148 * exist or is corrupt. -149 * @throws DatabaseException when the database throws an exception. This -150 * usually occurs when the database is in use by another process. -151 */ -152 public void open() throws IOException, DatabaseException { -153 if (!isOpen()) { -154 cve = new CveDB(); -155 cve.open(); -156 cpe = CpeMemoryIndex.getInstance(); -157 try { -158 LOGGER.info("Creating the CPE Index"); +28 import java.util.concurrent.TimeUnit; +29 import org.apache.commons.lang3.builder.CompareToBuilder; +30 import org.apache.lucene.document.Document; +31 import org.apache.lucene.index.CorruptIndexException; +32 import org.apache.lucene.queryparser.classic.ParseException; +33 import org.apache.lucene.search.ScoreDoc; +34 import org.apache.lucene.search.TopDocs; +35 import org.owasp.dependencycheck.Engine; +36 import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +37 import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex; +38 import org.owasp.dependencycheck.data.cpe.Fields; +39 import org.owasp.dependencycheck.data.cpe.IndexEntry; +40 import org.owasp.dependencycheck.data.cpe.IndexException; +41 import org.owasp.dependencycheck.data.lucene.LuceneUtils; +42 import org.owasp.dependencycheck.data.nvdcve.CveDB; +43 import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +44 import org.owasp.dependencycheck.dependency.Confidence; +45 import org.owasp.dependencycheck.dependency.Dependency; +46 import org.owasp.dependencycheck.dependency.Evidence; +47 import org.owasp.dependencycheck.dependency.EvidenceCollection; +48 import org.owasp.dependencycheck.dependency.Identifier; +49 import org.owasp.dependencycheck.dependency.VulnerableSoftware; +50 import org.owasp.dependencycheck.exception.InitializationException; +51 import org.owasp.dependencycheck.utils.DependencyVersion; +52 import org.owasp.dependencycheck.utils.DependencyVersionUtil; +53 import org.slf4j.Logger; +54 import org.slf4j.LoggerFactory; +55 +56 /** +57 * CPEAnalyzer is a utility class that takes a project dependency and attempts +58 * to discern if there is an associated CPE. It uses the evidence contained +59 * within the dependency to search the Lucene index. +60 * +61 * @author Jeremy Long +62 */ +63 public class CPEAnalyzer extends AbstractAnalyzer { +64 +65 /** +66 * The Logger. +67 */ +68 private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class); +69 /** +70 * The maximum number of query results to return. +71 */ +72 static final int MAX_QUERY_RESULTS = 25; +73 /** +74 * The weighting boost to give terms when constructing the Lucene query. +75 */ +76 static final String WEIGHTING_BOOST = "^5"; +77 /** +78 * A string representation of a regular expression defining characters +79 * utilized within the CPE Names. +80 */ +81 static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]"; +82 /** +83 * A string representation of a regular expression used to remove all but +84 * alpha characters. +85 */ +86 static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*"; +87 /** +88 * The additional size to add to a new StringBuilder to account for extra +89 * data that will be written into the string. +90 */ +91 static final int STRING_BUILDER_BUFFER = 20; +92 /** +93 * The CPE in memory index. +94 */ +95 private CpeMemoryIndex cpe; +96 /** +97 * The CVE Database. +98 */ +99 private CveDB cve; +100 +101 /** +102 * The URL to perform a search of the NVD CVE data at NIST. +103 */ +104 public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s"; +105 +106 /** +107 * Returns the name of this analyzer. +108 * +109 * @return the name of this analyzer. +110 */ +111 @Override +112 public String getName() { +113 return "CPE Analyzer"; +114 } +115 +116 /** +117 * Returns the analysis phase that this analyzer should run in. +118 * +119 * @return the analysis phase that this analyzer should run in. +120 */ +121 @Override +122 public AnalysisPhase getAnalysisPhase() { +123 return AnalysisPhase.IDENTIFIER_ANALYSIS; +124 } +125 +126 /** +127 * Creates the CPE Lucene Index. +128 * +129 * @throws InitializationException is thrown if there is an issue opening +130 * the index. +131 */ +132 @Override +133 public void initialize() throws InitializationException { +134 try { +135 this.open(); +136 } catch (IOException ex) { +137 LOGGER.debug("Exception initializing the Lucene Index", ex); +138 throw new InitializationException("An exception occurred initializing the Lucene Index", ex); +139 } catch (DatabaseException ex) { +140 LOGGER.debug("Exception accessing the database", ex); +141 throw new InitializationException("An exception occurred accessing the database", ex); +142 } +143 } +144 +145 /** +146 * Opens the data source. +147 * +148 * @throws IOException when the Lucene directory to be queried does not +149 * exist or is corrupt. +150 * @throws DatabaseException when the database throws an exception. This +151 * usually occurs when the database is in use by another process. +152 */ +153 public void open() throws IOException, DatabaseException { +154 if (!isOpen()) { +155 cve = new CveDB(); +156 cve.open(); +157 cpe = CpeMemoryIndex.getInstance(); +158 try { 159 final long creationStart = System.currentTimeMillis(); 160 cpe.open(cve); -161 LOGGER.info("CPE Index Created ({} ms)", System.currentTimeMillis() - creationStart); -162 } catch (IndexException ex) { -163 LOGGER.debug("IndexException", ex); -164 throw new DatabaseException(ex); -165 } -166 } -167 } -168 -169 /** -170 * Closes the data sources. -171 */ -172 @Override -173 public void close() { -174 if (cpe != null) { -175 cpe.close(); -176 cpe = null; -177 } -178 if (cve != null) { -179 cve.close(); -180 cve = null; -181 } -182 } -183 -184 public boolean isOpen() { -185 return cpe != null && cpe.isOpen(); -186 } -187 -188 /** -189 * Searches the data store of CPE entries, trying to identify the CPE for -190 * the given dependency based on the evidence contained within. The -191 * dependency passed in is updated with any identified CPE values. -192 * -193 * @param dependency the dependency to search for CPE entries on. -194 * @throws CorruptIndexException is thrown when the Lucene index is corrupt. -195 * @throws IOException is thrown when an IOException occurs. -196 * @throws ParseException is thrown when the Lucene query cannot be parsed. -197 */ -198 protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException { -199 //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit -200 String vendors = ""; -201 String products = ""; -202 for (Confidence confidence : Confidence.values()) { -203 if (dependency.getVendorEvidence().contains(confidence)) { -204 vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence); -205 LOGGER.debug("vendor search: {}", vendors); -206 } -207 if (dependency.getProductEvidence().contains(confidence)) { -208 products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence); -209 LOGGER.debug("product search: {}", products); -210 } -211 if (!vendors.isEmpty() && !products.isEmpty()) { -212 final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(), -213 dependency.getProductEvidence().getWeighting()); -214 if (entries == null) { -215 continue; -216 } -217 boolean identifierAdded = false; -218 for (IndexEntry e : entries) { -219 LOGGER.debug("Verifying entry: {}", e); -220 if (verifyEntry(e, dependency)) { -221 final String vendor = e.getVendor(); -222 final String product = e.getProduct(); -223 LOGGER.debug("identified vendor/product: {}/{}", vendor, product); -224 identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence); -225 } -226 } -227 if (identifierAdded) { -228 break; -229 } -230 } -231 } -232 } -233 -234 /** -235 * Returns the text created by concatenating the text and the values from -236 * the EvidenceCollection (filtered for a specific confidence). This -237 * attempts to prevent duplicate terms from being added.<br/<br/> Note, if -238 * the evidence is longer then 200 characters it will be truncated. -239 * -240 * @param text the base text. -241 * @param ec an EvidenceCollection -242 * @param confidenceFilter a Confidence level to filter the evidence by. -243 * @return the new evidence text -244 */ -245 private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) { -246 final String txt = (text == null) ? "" : text; -247 final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size())); -248 sb.append(' ').append(txt).append(' '); -249 for (Evidence e : ec.iterator(confidenceFilter)) { -250 String value = e.getValue(); -251 -252 //hack to get around the fact that lucene does a really good job of recognizing domains and not -253 // splitting them. TODO - put together a better lucene analyzer specific to the domain. -254 if (value.startsWith("http://")) { -255 value = value.substring(7).replaceAll("\\.", " "); -256 } -257 if (value.startsWith("https://")) { -258 value = value.substring(8).replaceAll("\\.", " "); -259 } -260 if (sb.indexOf(" " + value + " ") < 0) { -261 sb.append(value).append(' '); -262 } -263 } -264 return sb.toString().trim(); -265 } -266 -267 /** -268 * <p> -269 * Searches the Lucene CPE index to identify possible CPE entries associated -270 * with the supplied vendor, product, and version.</p> -271 * -272 * <p> -273 * If either the vendorWeightings or productWeightings lists have been -274 * populated this data is used to add weighting factors to the search.</p> -275 * -276 * @param vendor the text used to search the vendor field -277 * @param product the text used to search the product field -278 * @param vendorWeightings a list of strings to use to add weighting factors -279 * to the vendor field -280 * @param productWeightings Adds a list of strings that will be used to add -281 * weighting factors to the product search -282 * @return a list of possible CPE values -283 */ -284 protected List<IndexEntry> searchCPE(String vendor, String product, -285 Set<String> vendorWeightings, Set<String> productWeightings) { -286 -287 final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS); -288 -289 final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings); -290 if (searchString == null) { -291 return ret; -292 } -293 try { -294 final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS); -295 for (ScoreDoc d : docs.scoreDocs) { -296 if (d.score >= 0.08) { -297 final Document doc = cpe.getDocument(d.doc); -298 final IndexEntry entry = new IndexEntry(); -299 entry.setVendor(doc.get(Fields.VENDOR)); -300 entry.setProduct(doc.get(Fields.PRODUCT)); -301 entry.setSearchScore(d.score); -302 if (!ret.contains(entry)) { -303 ret.add(entry); -304 } -305 } -306 } -307 return ret; -308 } catch (ParseException ex) { -309 LOGGER.warn("An error occurred querying the CPE data. See the log for more details."); -310 LOGGER.info("Unable to parse: {}", searchString, ex); -311 } catch (IOException ex) { -312 LOGGER.warn("An error occurred reading CPE data. See the log for more details."); -313 LOGGER.info("IO Error with search string: {}", searchString, ex); -314 } -315 return null; -316 } -317 -318 /** -319 * <p> -320 * Builds a Lucene search string by properly escaping data and constructing -321 * a valid search query.</p> -322 * -323 * <p> -324 * If either the possibleVendor or possibleProducts lists have been -325 * populated this data is used to add weighting factors to the search string -326 * generated.</p> -327 * -328 * @param vendor text to search the vendor field -329 * @param product text to search the product field -330 * @param vendorWeighting a list of strings to apply to the vendor to boost -331 * the terms weight -332 * @param productWeightings a list of strings to apply to the product to -333 * boost the terms weight -334 * @return the Lucene query -335 */ -336 protected String buildSearch(String vendor, String product, -337 Set<String> vendorWeighting, Set<String> productWeightings) { -338 final String v = vendor; //.replaceAll("[^\\w\\d]", " "); -339 final String p = product; //.replaceAll("[^\\w\\d]", " "); -340 final StringBuilder sb = new StringBuilder(v.length() + p.length() -341 + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER); -342 -343 if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) { -344 return null; -345 } -346 sb.append(" AND "); -347 if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) { -348 return null; -349 } -350 return sb.toString(); -351 } -352 -353 /** -354 * This method constructs a Lucene query for a given field. The searchText -355 * is split into separate words and if the word is within the list of -356 * weighted words then an additional weighting is applied to the term as it -357 * is appended into the query. -358 * -359 * @param sb a StringBuilder that the query text will be appended to. -360 * @param field the field within the Lucene index that the query is -361 * searching. -362 * @param searchText text used to construct the query. -363 * @param weightedText a list of terms that will be considered higher -364 * importance when searching. -365 * @return if the append was successful. -366 */ -367 private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) { -368 sb.append(' ').append(field).append(":( "); -369 -370 final String cleanText = cleanseText(searchText); -371 -372 if (cleanText.isEmpty()) { -373 return false; -374 } -375 -376 if (weightedText == null || weightedText.isEmpty()) { -377 LuceneUtils.appendEscapedLuceneQuery(sb, cleanText); -378 } else { -379 final StringTokenizer tokens = new StringTokenizer(cleanText); -380 while (tokens.hasMoreElements()) { -381 final String word = tokens.nextToken(); -382 StringBuilder temp = null; -383 for (String weighted : weightedText) { -384 final String weightedStr = cleanseText(weighted); -385 if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) { -386 temp = new StringBuilder(word.length() + 2); -387 LuceneUtils.appendEscapedLuceneQuery(temp, word); -388 temp.append(WEIGHTING_BOOST); -389 if (!word.equalsIgnoreCase(weightedStr)) { -390 temp.append(' '); -391 LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr); -392 temp.append(WEIGHTING_BOOST); -393 } -394 break; -395 } -396 } -397 sb.append(' '); -398 if (temp == null) { -399 LuceneUtils.appendEscapedLuceneQuery(sb, word); -400 } else { -401 sb.append(temp); -402 } -403 } -404 } -405 sb.append(" ) "); -406 return true; -407 } -408 -409 /** -410 * Removes characters from the input text that are not used within the CPE -411 * index. -412 * -413 * @param text is the text to remove the characters from. -414 * @return the text having removed some characters. -415 */ -416 private String cleanseText(String text) { -417 return text.replaceAll(CLEANSE_CHARACTER_RX, " "); -418 } -419 -420 /** -421 * Compares two strings after lower casing them and removing the non-alpha -422 * characters. -423 * -424 * @param l string one to compare. -425 * @param r string two to compare. -426 * @return whether or not the two strings are similar. -427 */ -428 private boolean equalsIgnoreCaseAndNonAlpha(String l, String r) { -429 if (l == null || r == null) { -430 return false; -431 } -432 -433 final String left = l.replaceAll(CLEANSE_NONALPHA_RX, ""); -434 final String right = r.replaceAll(CLEANSE_NONALPHA_RX, ""); -435 return left.equalsIgnoreCase(right); -436 } -437 -438 /** -439 * Ensures that the CPE Identified matches the dependency. This validates -440 * that the product, vendor, and version information for the CPE are -441 * contained within the dependencies evidence. -442 * -443 * @param entry a CPE entry. -444 * @param dependency the dependency that the CPE entries could be for. -445 * @return whether or not the entry is valid. -446 */ -447 private boolean verifyEntry(final IndexEntry entry, final Dependency dependency) { -448 boolean isValid = false; -449 -450 //TODO - does this nullify some of the fuzzy matching that happens in the lucene search? -451 // for instance CPE some-component and in the evidence we have SomeComponent. -452 if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct()) -453 && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) { -454 //&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion()) -455 isValid = true; -456 } -457 return isValid; -458 } -459 -460 /** -461 * Used to determine if the EvidenceCollection contains a specific string. -462 * -463 * @param ec an EvidenceCollection -464 * @param text the text to search for -465 * @return whether or not the EvidenceCollection contains the string -466 */ -467 private boolean collectionContainsString(EvidenceCollection ec, String text) { -468 //TODO - likely need to change the split... not sure if this will work for CPE with special chars -469 if (text == null) { -470 return false; -471 } -472 final String[] words = text.split("[\\s_-]"); -473 final List<String> list = new ArrayList<String>(); -474 String tempWord = null; -475 for (String word : words) { -476 /* -477 single letter words should be concatenated with the next word. -478 so { "m", "core", "sample" } -> { "mcore", "sample" } -479 */ -480 if (tempWord != null) { -481 list.add(tempWord + word); -482 tempWord = null; -483 } else if (word.length() <= 2) { -484 tempWord = word; -485 } else { -486 list.add(word); -487 } -488 } -489 if (tempWord != null) { -490 if (!list.isEmpty()) { -491 final String tmp = list.get(list.size() - 1) + tempWord; -492 list.add(tmp); -493 } else { -494 list.add(tempWord); -495 } -496 } -497 if (list.isEmpty()) { -498 return false; -499 } -500 boolean contains = true; -501 for (String word : list) { -502 contains &= ec.containsUsedString(word); -503 } -504 return contains; -505 } -506 -507 /** -508 * Analyzes a dependency and attempts to determine if there are any CPE -509 * identifiers for this dependency. -510 * -511 * @param dependency The Dependency to analyze. -512 * @param engine The analysis engine -513 * @throws AnalysisException is thrown if there is an issue analyzing the -514 * dependency. -515 */ -516 @Override -517 public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException { -518 try { -519 determineCPE(dependency); -520 } catch (CorruptIndexException ex) { -521 throw new AnalysisException("CPE Index is corrupt.", ex); -522 } catch (IOException ex) { -523 throw new AnalysisException("Failure opening the CPE Index.", ex); -524 } catch (ParseException ex) { -525 throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex); -526 } -527 } -528 -529 /** -530 * Retrieves a list of CPE values from the CveDB based on the vendor and -531 * product passed in. The list is then validated to find only CPEs that are -532 * valid for the given dependency. It is possible that the CPE identified is -533 * a best effort "guess" based on the vendor, product, and version -534 * information. -535 * -536 * @param dependency the Dependency being analyzed -537 * @param vendor the vendor for the CPE being analyzed -538 * @param product the product for the CPE being analyzed -539 * @param currentConfidence the current confidence being used during -540 * analysis -541 * @return <code>true</code> if an identifier was added to the dependency; -542 * otherwise <code>false</code> -543 * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported -544 */ -545 protected boolean determineIdentifiers(Dependency dependency, String vendor, String product, -546 Confidence currentConfidence) throws UnsupportedEncodingException { -547 final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product); -548 DependencyVersion bestGuess = new DependencyVersion("-"); -549 Confidence bestGuessConf = null; -550 boolean hasBroadMatch = false; -551 final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>(); -552 -553 //TODO the following algorithm incorrectly identifies things as a lower version -554 // if there lower confidence evidence when the current (highest) version number -555 // is newer then anything in the NVD. -556 for (Confidence conf : Confidence.values()) { -557 for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) { -558 final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue()); -559 if (evVer == null) { -560 continue; -561 } -562 for (VulnerableSoftware vs : cpes) { -563 DependencyVersion dbVer; -564 if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) { -565 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate()); -566 } else { -567 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion()); -568 } -569 if (dbVer == null) { //special case, no version specified - everything is vulnerable -570 hasBroadMatch = true; -571 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); -572 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf); -573 collected.add(match); -574 } else if (evVer.equals(dbVer)) { //yeah! exact match -575 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); -576 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf); -577 collected.add(match); -578 -579 //TODO the following isn't quite right is it? need to think about this guessing game a bit more. -580 } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() -581 && evVer.matchesAtLeastThreeLevels(dbVer)) { -582 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { -583 if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) { -584 bestGuess = dbVer; -585 bestGuessConf = conf; -586 } -587 } -588 } -589 } -590 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { -591 if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) { -592 bestGuess = evVer; -593 bestGuessConf = conf; -594 } -595 } -596 } -597 } -598 final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString()); -599 String url = null; -600 if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess. -601 final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product); -602 url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8")); -603 } -604 if (bestGuessConf == null) { -605 bestGuessConf = Confidence.LOW; -606 } -607 final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf); -608 collected.add(match); -609 -610 Collections.sort(collected); -611 final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence(); -612 final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence(); -613 boolean identifierAdded = false; -614 for (IdentifierMatch m : collected) { -615 if (bestIdentifierQuality.equals(m.getConfidence()) -616 && bestEvidenceQuality.equals(m.getEvidenceConfidence())) { -617 final Identifier i = m.getIdentifier(); -618 if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) { -619 i.setConfidence(Confidence.LOW); -620 } else { -621 i.setConfidence(bestEvidenceQuality); -622 } -623 dependency.addIdentifier(i); -624 identifierAdded = true; -625 } -626 } -627 return identifierAdded; -628 } -629 -630 /** -631 * The confidence whether the identifier is an exact match, or a best guess. -632 */ -633 private enum IdentifierConfidence { -634 -635 /** -636 * An exact match for the CPE. -637 */ -638 EXACT_MATCH, -639 /** -640 * A best guess for the CPE. -641 */ -642 BEST_GUESS, -643 /** -644 * The entire vendor/product group must be added (without a guess at -645 * version) because there is a CVE with a VS that only specifies -646 * vendor/product. -647 */ -648 BROAD_MATCH -649 } -650 -651 /** -652 * A simple object to hold an identifier and carry information about the -653 * confidence in the identifier. -654 */ -655 private static class IdentifierMatch implements Comparable<IdentifierMatch> { -656 -657 /** -658 * Constructs an IdentifierMatch. -659 * -660 * @param type the type of identifier (such as CPE) -661 * @param value the value of the identifier -662 * @param url the URL of the identifier -663 * @param identifierConfidence the confidence in the identifier: best -664 * guess or exact match -665 * @param evidenceConfidence the confidence of the evidence used to find -666 * the identifier -667 */ -668 IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) { -669 this.identifier = new Identifier(type, value, url); -670 this.confidence = identifierConfidence; -671 this.evidenceConfidence = evidenceConfidence; -672 } -673 //<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier"> -674 /** -675 * The confidence in the evidence used to identify this match. -676 */ -677 private Confidence evidenceConfidence; -678 -679 /** -680 * Get the value of evidenceConfidence -681 * -682 * @return the value of evidenceConfidence -683 */ -684 public Confidence getEvidenceConfidence() { -685 return evidenceConfidence; -686 } -687 -688 /** -689 * Set the value of evidenceConfidence -690 * -691 * @param evidenceConfidence new value of evidenceConfidence -692 */ -693 public void setEvidenceConfidence(Confidence evidenceConfidence) { -694 this.evidenceConfidence = evidenceConfidence; -695 } -696 /** -697 * The confidence whether this is an exact match, or a best guess. -698 */ -699 private IdentifierConfidence confidence; -700 -701 /** -702 * Get the value of confidence. -703 * -704 * @return the value of confidence -705 */ -706 public IdentifierConfidence getConfidence() { -707 return confidence; -708 } -709 -710 /** -711 * Set the value of confidence. -712 * -713 * @param confidence new value of confidence -714 */ -715 public void setConfidence(IdentifierConfidence confidence) { -716 this.confidence = confidence; -717 } -718 /** -719 * The CPE identifier. -720 */ -721 private Identifier identifier; -722 -723 /** -724 * Get the value of identifier. -725 * -726 * @return the value of identifier -727 */ -728 public Identifier getIdentifier() { -729 return identifier; -730 } -731 -732 /** -733 * Set the value of identifier. -734 * -735 * @param identifier new value of identifier -736 */ -737 public void setIdentifier(Identifier identifier) { -738 this.identifier = identifier; -739 } -740 //</editor-fold> -741 //<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals"> -742 -743 /** -744 * Standard toString() implementation. -745 * -746 * @return the string representation of the object -747 */ -748 @Override -749 public String toString() { -750 return "IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence -751 + ", confidence=" + confidence + ", identifier=" + identifier + '}'; -752 } -753 -754 /** -755 * Standard hashCode() implementation. -756 * -757 * @return the hashCode -758 */ -759 @Override -760 public int hashCode() { -761 int hash = 5; -762 hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0); -763 hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0); -764 hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0); -765 return hash; -766 } -767 -768 /** -769 * Standard equals implementation. -770 * -771 * @param obj the object to compare -772 * @return true if the objects are equal, otherwise false -773 */ -774 @Override -775 public boolean equals(Object obj) { -776 if (obj == null) { -777 return false; -778 } -779 if (getClass() != obj.getClass()) { -780 return false; -781 } -782 final IdentifierMatch other = (IdentifierMatch) obj; -783 if (this.evidenceConfidence != other.evidenceConfidence) { -784 return false; -785 } -786 if (this.confidence != other.confidence) { -787 return false; -788 } -789 if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) { -790 return false; -791 } -792 return true; -793 } -794 //</editor-fold> -795 -796 /** -797 * Standard implementation of compareTo that compares identifier -798 * confidence, evidence confidence, and then the identifier. -799 * -800 * @param o the IdentifierMatch to compare to -801 * @return the natural ordering of IdentifierMatch -802 */ -803 @Override -804 public int compareTo(IdentifierMatch o) { -805 return new CompareToBuilder() -806 .append(confidence, o.confidence) -807 .append(evidenceConfidence, o.evidenceConfidence) -808 .append(identifier, o.identifier) -809 .toComparison(); -810 /* -811 int conf = this.confidence.compareTo(o.confidence); -812 if (conf == 0) { -813 conf = this.evidenceConfidence.compareTo(o.evidenceConfidence); -814 if (conf == 0) { -815 conf = identifier.compareTo(o.identifier); -816 } -817 } -818 return conf; -819 */ -820 } -821 } -822 } +161 final long creationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - creationStart); +162 LOGGER.info("Created CPE Index ({} seconds)", creationSeconds); +163 } catch (IndexException ex) { +164 LOGGER.debug("IndexException", ex); +165 throw new DatabaseException(ex); +166 } +167 } +168 } +169 +170 /** +171 * Closes the data sources. +172 */ +173 @Override +174 public void close() { +175 if (cpe != null) { +176 cpe.close(); +177 cpe = null; +178 } +179 if (cve != null) { +180 cve.close(); +181 cve = null; +182 } +183 } +184 +185 public boolean isOpen() { +186 return cpe != null && cpe.isOpen(); +187 } +188 +189 /** +190 * Searches the data store of CPE entries, trying to identify the CPE for +191 * the given dependency based on the evidence contained within. The +192 * dependency passed in is updated with any identified CPE values. +193 * +194 * @param dependency the dependency to search for CPE entries on. +195 * @throws CorruptIndexException is thrown when the Lucene index is corrupt. +196 * @throws IOException is thrown when an IOException occurs. +197 * @throws ParseException is thrown when the Lucene query cannot be parsed. +198 */ +199 protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException { +200 //TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit +201 String vendors = ""; +202 String products = ""; +203 for (Confidence confidence : Confidence.values()) { +204 if (dependency.getVendorEvidence().contains(confidence)) { +205 vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), confidence); +206 LOGGER.debug("vendor search: {}", vendors); +207 } +208 if (dependency.getProductEvidence().contains(confidence)) { +209 products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), confidence); +210 LOGGER.debug("product search: {}", products); +211 } +212 if (!vendors.isEmpty() && !products.isEmpty()) { +213 final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(), +214 dependency.getProductEvidence().getWeighting()); +215 if (entries == null) { +216 continue; +217 } +218 boolean identifierAdded = false; +219 for (IndexEntry e : entries) { +220 LOGGER.debug("Verifying entry: {}", e); +221 if (verifyEntry(e, dependency)) { +222 final String vendor = e.getVendor(); +223 final String product = e.getProduct(); +224 LOGGER.debug("identified vendor/product: {}/{}", vendor, product); +225 identifierAdded |= determineIdentifiers(dependency, vendor, product, confidence); +226 } +227 } +228 if (identifierAdded) { +229 break; +230 } +231 } +232 } +233 } +234 +235 /** +236 * Returns the text created by concatenating the text and the values from +237 * the EvidenceCollection (filtered for a specific confidence). This +238 * attempts to prevent duplicate terms from being added.<br/<br/> Note, if +239 * the evidence is longer then 200 characters it will be truncated. +240 * +241 * @param text the base text. +242 * @param ec an EvidenceCollection +243 * @param confidenceFilter a Confidence level to filter the evidence by. +244 * @return the new evidence text +245 */ +246 private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) { +247 final String txt = (text == null) ? "" : text; +248 final StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size())); +249 sb.append(' ').append(txt).append(' '); +250 for (Evidence e : ec.iterator(confidenceFilter)) { +251 String value = e.getValue(); +252 +253 //hack to get around the fact that lucene does a really good job of recognizing domains and not +254 // splitting them. TODO - put together a better lucene analyzer specific to the domain. +255 if (value.startsWith("http://")) { +256 value = value.substring(7).replaceAll("\\.", " "); +257 } +258 if (value.startsWith("https://")) { +259 value = value.substring(8).replaceAll("\\.", " "); +260 } +261 if (sb.indexOf(" " + value + " ") < 0) { +262 sb.append(value).append(' '); +263 } +264 } +265 return sb.toString().trim(); +266 } +267 +268 /** +269 * <p> +270 * Searches the Lucene CPE index to identify possible CPE entries associated +271 * with the supplied vendor, product, and version.</p> +272 * +273 * <p> +274 * If either the vendorWeightings or productWeightings lists have been +275 * populated this data is used to add weighting factors to the search.</p> +276 * +277 * @param vendor the text used to search the vendor field +278 * @param product the text used to search the product field +279 * @param vendorWeightings a list of strings to use to add weighting factors +280 * to the vendor field +281 * @param productWeightings Adds a list of strings that will be used to add +282 * weighting factors to the product search +283 * @return a list of possible CPE values +284 */ +285 protected List<IndexEntry> searchCPE(String vendor, String product, +286 Set<String> vendorWeightings, Set<String> productWeightings) { +287 +288 final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS); +289 +290 final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings); +291 if (searchString == null) { +292 return ret; +293 } +294 try { +295 final TopDocs docs = cpe.search(searchString, MAX_QUERY_RESULTS); +296 for (ScoreDoc d : docs.scoreDocs) { +297 if (d.score >= 0.08) { +298 final Document doc = cpe.getDocument(d.doc); +299 final IndexEntry entry = new IndexEntry(); +300 entry.setVendor(doc.get(Fields.VENDOR)); +301 entry.setProduct(doc.get(Fields.PRODUCT)); +302 entry.setSearchScore(d.score); +303 if (!ret.contains(entry)) { +304 ret.add(entry); +305 } +306 } +307 } +308 return ret; +309 } catch (ParseException ex) { +310 LOGGER.warn("An error occurred querying the CPE data. See the log for more details."); +311 LOGGER.info("Unable to parse: {}", searchString, ex); +312 } catch (IOException ex) { +313 LOGGER.warn("An error occurred reading CPE data. See the log for more details."); +314 LOGGER.info("IO Error with search string: {}", searchString, ex); +315 } +316 return null; +317 } +318 +319 /** +320 * <p> +321 * Builds a Lucene search string by properly escaping data and constructing +322 * a valid search query.</p> +323 * +324 * <p> +325 * If either the possibleVendor or possibleProducts lists have been +326 * populated this data is used to add weighting factors to the search string +327 * generated.</p> +328 * +329 * @param vendor text to search the vendor field +330 * @param product text to search the product field +331 * @param vendorWeighting a list of strings to apply to the vendor to boost +332 * the terms weight +333 * @param productWeightings a list of strings to apply to the product to +334 * boost the terms weight +335 * @return the Lucene query +336 */ +337 protected String buildSearch(String vendor, String product, +338 Set<String> vendorWeighting, Set<String> productWeightings) { +339 final String v = vendor; //.replaceAll("[^\\w\\d]", " "); +340 final String p = product; //.replaceAll("[^\\w\\d]", " "); +341 final StringBuilder sb = new StringBuilder(v.length() + p.length() +342 + Fields.PRODUCT.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER); +343 +344 if (!appendWeightedSearch(sb, Fields.PRODUCT, p, productWeightings)) { +345 return null; +346 } +347 sb.append(" AND "); +348 if (!appendWeightedSearch(sb, Fields.VENDOR, v, vendorWeighting)) { +349 return null; +350 } +351 return sb.toString(); +352 } +353 +354 /** +355 * This method constructs a Lucene query for a given field. The searchText +356 * is split into separate words and if the word is within the list of +357 * weighted words then an additional weighting is applied to the term as it +358 * is appended into the query. +359 * +360 * @param sb a StringBuilder that the query text will be appended to. +361 * @param field the field within the Lucene index that the query is +362 * searching. +363 * @param searchText text used to construct the query. +364 * @param weightedText a list of terms that will be considered higher +365 * importance when searching. +366 * @return if the append was successful. +367 */ +368 private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) { +369 sb.append(' ').append(field).append(":( "); +370 +371 final String cleanText = cleanseText(searchText); +372 +373 if (cleanText.isEmpty()) { +374 return false; +375 } +376 +377 if (weightedText == null || weightedText.isEmpty()) { +378 LuceneUtils.appendEscapedLuceneQuery(sb, cleanText); +379 } else { +380 final StringTokenizer tokens = new StringTokenizer(cleanText); +381 while (tokens.hasMoreElements()) { +382 final String word = tokens.nextToken(); +383 StringBuilder temp = null; +384 for (String weighted : weightedText) { +385 final String weightedStr = cleanseText(weighted); +386 if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) { +387 temp = new StringBuilder(word.length() + 2); +388 LuceneUtils.appendEscapedLuceneQuery(temp, word); +389 temp.append(WEIGHTING_BOOST); +390 if (!word.equalsIgnoreCase(weightedStr)) { +391 temp.append(' '); +392 LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr); +393 temp.append(WEIGHTING_BOOST); +394 } +395 break; +396 } +397 } +398 sb.append(' '); +399 if (temp == null) { +400 LuceneUtils.appendEscapedLuceneQuery(sb, word); +401 } else { +402 sb.append(temp); +403 } +404 } +405 } +406 sb.append(" ) "); +407 return true; +408 } +409 +410 /** +411 * Removes characters from the input text that are not used within the CPE +412 * index. +413 * +414 * @param text is the text to remove the characters from. +415 * @return the text having removed some characters. +416 */ +417 private String cleanseText(String text) { +418 return text.replaceAll(CLEANSE_CHARACTER_RX, " "); +419 } +420 +421 /** +422 * Compares two strings after lower casing them and removing the non-alpha +423 * characters. +424 * +425 * @param l string one to compare. +426 * @param r string two to compare. +427 * @return whether or not the two strings are similar. +428 */ +429 private boolean equalsIgnoreCaseAndNonAlpha(String l, String r) { +430 if (l == null || r == null) { +431 return false; +432 } +433 +434 final String left = l.replaceAll(CLEANSE_NONALPHA_RX, ""); +435 final String right = r.replaceAll(CLEANSE_NONALPHA_RX, ""); +436 return left.equalsIgnoreCase(right); +437 } +438 +439 /** +440 * Ensures that the CPE Identified matches the dependency. This validates +441 * that the product, vendor, and version information for the CPE are +442 * contained within the dependencies evidence. +443 * +444 * @param entry a CPE entry. +445 * @param dependency the dependency that the CPE entries could be for. +446 * @return whether or not the entry is valid. +447 */ +448 private boolean verifyEntry(final IndexEntry entry, final Dependency dependency) { +449 boolean isValid = false; +450 +451 //TODO - does this nullify some of the fuzzy matching that happens in the lucene search? +452 // for instance CPE some-component and in the evidence we have SomeComponent. +453 if (collectionContainsString(dependency.getProductEvidence(), entry.getProduct()) +454 && collectionContainsString(dependency.getVendorEvidence(), entry.getVendor())) { +455 //&& collectionContainsVersion(dependency.getVersionEvidence(), entry.getVersion()) +456 isValid = true; +457 } +458 return isValid; +459 } +460 +461 /** +462 * Used to determine if the EvidenceCollection contains a specific string. +463 * +464 * @param ec an EvidenceCollection +465 * @param text the text to search for +466 * @return whether or not the EvidenceCollection contains the string +467 */ +468 private boolean collectionContainsString(EvidenceCollection ec, String text) { +469 //TODO - likely need to change the split... not sure if this will work for CPE with special chars +470 if (text == null) { +471 return false; +472 } +473 final String[] words = text.split("[\\s_-]"); +474 final List<String> list = new ArrayList<String>(); +475 String tempWord = null; +476 for (String word : words) { +477 /* +478 single letter words should be concatenated with the next word. +479 so { "m", "core", "sample" } -> { "mcore", "sample" } +480 */ +481 if (tempWord != null) { +482 list.add(tempWord + word); +483 tempWord = null; +484 } else if (word.length() <= 2) { +485 tempWord = word; +486 } else { +487 list.add(word); +488 } +489 } +490 if (tempWord != null) { +491 if (!list.isEmpty()) { +492 final String tmp = list.get(list.size() - 1) + tempWord; +493 list.add(tmp); +494 } else { +495 list.add(tempWord); +496 } +497 } +498 if (list.isEmpty()) { +499 return false; +500 } +501 boolean contains = true; +502 for (String word : list) { +503 contains &= ec.containsUsedString(word); +504 } +505 return contains; +506 } +507 +508 /** +509 * Analyzes a dependency and attempts to determine if there are any CPE +510 * identifiers for this dependency. +511 * +512 * @param dependency The Dependency to analyze. +513 * @param engine The analysis engine +514 * @throws AnalysisException is thrown if there is an issue analyzing the +515 * dependency. +516 */ +517 @Override +518 public synchronized void analyze(Dependency dependency, Engine engine) throws AnalysisException { +519 try { +520 determineCPE(dependency); +521 } catch (CorruptIndexException ex) { +522 throw new AnalysisException("CPE Index is corrupt.", ex); +523 } catch (IOException ex) { +524 throw new AnalysisException("Failure opening the CPE Index.", ex); +525 } catch (ParseException ex) { +526 throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex); +527 } +528 } +529 +530 /** +531 * Retrieves a list of CPE values from the CveDB based on the vendor and +532 * product passed in. The list is then validated to find only CPEs that are +533 * valid for the given dependency. It is possible that the CPE identified is +534 * a best effort "guess" based on the vendor, product, and version +535 * information. +536 * +537 * @param dependency the Dependency being analyzed +538 * @param vendor the vendor for the CPE being analyzed +539 * @param product the product for the CPE being analyzed +540 * @param currentConfidence the current confidence being used during +541 * analysis +542 * @return <code>true</code> if an identifier was added to the dependency; +543 * otherwise <code>false</code> +544 * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported +545 */ +546 protected boolean determineIdentifiers(Dependency dependency, String vendor, String product, +547 Confidence currentConfidence) throws UnsupportedEncodingException { +548 final Set<VulnerableSoftware> cpes = cve.getCPEs(vendor, product); +549 DependencyVersion bestGuess = new DependencyVersion("-"); +550 Confidence bestGuessConf = null; +551 boolean hasBroadMatch = false; +552 final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>(); +553 +554 //TODO the following algorithm incorrectly identifies things as a lower version +555 // if there lower confidence evidence when the current (highest) version number +556 // is newer then anything in the NVD. +557 for (Confidence conf : Confidence.values()) { +558 for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) { +559 final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue()); +560 if (evVer == null) { +561 continue; +562 } +563 for (VulnerableSoftware vs : cpes) { +564 DependencyVersion dbVer; +565 if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) { +566 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate()); +567 } else { +568 dbVer = DependencyVersionUtil.parseVersion(vs.getVersion()); +569 } +570 if (dbVer == null) { //special case, no version specified - everything is vulnerable +571 hasBroadMatch = true; +572 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); +573 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.BROAD_MATCH, conf); +574 collected.add(match); +575 } else if (evVer.equals(dbVer)) { //yeah! exact match +576 final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8")); +577 final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf); +578 collected.add(match); +579 +580 //TODO the following isn't quite right is it? need to think about this guessing game a bit more. +581 } else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size() +582 && evVer.matchesAtLeastThreeLevels(dbVer)) { +583 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { +584 if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) { +585 bestGuess = dbVer; +586 bestGuessConf = conf; +587 } +588 } +589 } +590 } +591 if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) { +592 if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) { +593 bestGuess = evVer; +594 bestGuessConf = conf; +595 } +596 } +597 } +598 } +599 final String cpeName = String.format("cpe:/a:%s:%s:%s", vendor, product, bestGuess.toString()); +600 String url = null; +601 if (hasBroadMatch) { //if we have a broad match we can add the URL to the best guess. +602 final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product); +603 url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8")); +604 } +605 if (bestGuessConf == null) { +606 bestGuessConf = Confidence.LOW; +607 } +608 final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf); +609 collected.add(match); +610 +611 Collections.sort(collected); +612 final IdentifierConfidence bestIdentifierQuality = collected.get(0).getConfidence(); +613 final Confidence bestEvidenceQuality = collected.get(0).getEvidenceConfidence(); +614 boolean identifierAdded = false; +615 for (IdentifierMatch m : collected) { +616 if (bestIdentifierQuality.equals(m.getConfidence()) +617 && bestEvidenceQuality.equals(m.getEvidenceConfidence())) { +618 final Identifier i = m.getIdentifier(); +619 if (bestIdentifierQuality == IdentifierConfidence.BEST_GUESS) { +620 i.setConfidence(Confidence.LOW); +621 } else { +622 i.setConfidence(bestEvidenceQuality); +623 } +624 dependency.addIdentifier(i); +625 identifierAdded = true; +626 } +627 } +628 return identifierAdded; +629 } +630 +631 /** +632 * The confidence whether the identifier is an exact match, or a best guess. +633 */ +634 private enum IdentifierConfidence { +635 +636 /** +637 * An exact match for the CPE. +638 */ +639 EXACT_MATCH, +640 /** +641 * A best guess for the CPE. +642 */ +643 BEST_GUESS, +644 /** +645 * The entire vendor/product group must be added (without a guess at +646 * version) because there is a CVE with a VS that only specifies +647 * vendor/product. +648 */ +649 BROAD_MATCH +650 } +651 +652 /** +653 * A simple object to hold an identifier and carry information about the +654 * confidence in the identifier. +655 */ +656 private static class IdentifierMatch implements Comparable<IdentifierMatch> { +657 +658 /** +659 * Constructs an IdentifierMatch. +660 * +661 * @param type the type of identifier (such as CPE) +662 * @param value the value of the identifier +663 * @param url the URL of the identifier +664 * @param identifierConfidence the confidence in the identifier: best +665 * guess or exact match +666 * @param evidenceConfidence the confidence of the evidence used to find +667 * the identifier +668 */ +669 IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) { +670 this.identifier = new Identifier(type, value, url); +671 this.confidence = identifierConfidence; +672 this.evidenceConfidence = evidenceConfidence; +673 } +674 //<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier"> +675 /** +676 * The confidence in the evidence used to identify this match. +677 */ +678 private Confidence evidenceConfidence; +679 +680 /** +681 * Get the value of evidenceConfidence +682 * +683 * @return the value of evidenceConfidence +684 */ +685 public Confidence getEvidenceConfidence() { +686 return evidenceConfidence; +687 } +688 +689 /** +690 * Set the value of evidenceConfidence +691 * +692 * @param evidenceConfidence new value of evidenceConfidence +693 */ +694 public void setEvidenceConfidence(Confidence evidenceConfidence) { +695 this.evidenceConfidence = evidenceConfidence; +696 } +697 /** +698 * The confidence whether this is an exact match, or a best guess. +699 */ +700 private IdentifierConfidence confidence; +701 +702 /** +703 * Get the value of confidence. +704 * +705 * @return the value of confidence +706 */ +707 public IdentifierConfidence getConfidence() { +708 return confidence; +709 } +710 +711 /** +712 * Set the value of confidence. +713 * +714 * @param confidence new value of confidence +715 */ +716 public void setConfidence(IdentifierConfidence confidence) { +717 this.confidence = confidence; +718 } +719 /** +720 * The CPE identifier. +721 */ +722 private Identifier identifier; +723 +724 /** +725 * Get the value of identifier. +726 * +727 * @return the value of identifier +728 */ +729 public Identifier getIdentifier() { +730 return identifier; +731 } +732 +733 /** +734 * Set the value of identifier. +735 * +736 * @param identifier new value of identifier +737 */ +738 public void setIdentifier(Identifier identifier) { +739 this.identifier = identifier; +740 } +741 //</editor-fold> +742 //<editor-fold defaultstate="collapsed" desc="Standard implementations of toString, hashCode, and equals"> +743 +744 /** +745 * Standard toString() implementation. +746 * +747 * @return the string representation of the object +748 */ +749 @Override +750 public String toString() { +751 return "IdentifierMatch{" + "evidenceConfidence=" + evidenceConfidence +752 + ", confidence=" + confidence + ", identifier=" + identifier + '}'; +753 } +754 +755 /** +756 * Standard hashCode() implementation. +757 * +758 * @return the hashCode +759 */ +760 @Override +761 public int hashCode() { +762 int hash = 5; +763 hash = 97 * hash + (this.evidenceConfidence != null ? this.evidenceConfidence.hashCode() : 0); +764 hash = 97 * hash + (this.confidence != null ? this.confidence.hashCode() : 0); +765 hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0); +766 return hash; +767 } +768 +769 /** +770 * Standard equals implementation. +771 * +772 * @param obj the object to compare +773 * @return true if the objects are equal, otherwise false +774 */ +775 @Override +776 public boolean equals(Object obj) { +777 if (obj == null) { +778 return false; +779 } +780 if (getClass() != obj.getClass()) { +781 return false; +782 } +783 final IdentifierMatch other = (IdentifierMatch) obj; +784 if (this.evidenceConfidence != other.evidenceConfidence) { +785 return false; +786 } +787 if (this.confidence != other.confidence) { +788 return false; +789 } +790 if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) { +791 return false; +792 } +793 return true; +794 } +795 //</editor-fold> +796 +797 /** +798 * Standard implementation of compareTo that compares identifier +799 * confidence, evidence confidence, and then the identifier. +800 * +801 * @param o the IdentifierMatch to compare to +802 * @return the natural ordering of IdentifierMatch +803 */ +804 @Override +805 public int compareTo(IdentifierMatch o) { +806 return new CompareToBuilder() +807 .append(confidence, o.confidence) +808 .append(evidenceConfidence, o.evidenceConfidence) +809 .append(identifier, o.identifier) +810 .toComparison(); +811 /* +812 int conf = this.confidence.compareTo(o.confidence); +813 if (conf == 0) { +814 conf = this.evidenceConfidence.compareTo(o.evidenceConfidence); +815 if (conf == 0) { +816 conf = identifier.compareTo(o.identifier); +817 } +818 } +819 return conf; +820 */ +821 } +822 } +823 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html index 886f0d5d1..03f83c6ff 100644 --- a/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/CentralAnalyzer.html @@ -83,7 +83,7 @@ 75 * The analyzer should be disabled if there are errors, so this is a flag to 76 * determine if such an error has occurred. 77 */ -78 private boolean errorFlag = false; +78 private volatile boolean errorFlag = false; 79 80 /** 81 * The searcher itself. diff --git a/xref/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html index 4fd93c80a..6c4cc84dd 100644 --- a/xref/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.html @@ -32,19 +32,19 @@ 24 import org.owasp.dependencycheck.data.composer.ComposerLockParser; 25 import org.owasp.dependencycheck.dependency.Confidence; 26 import org.owasp.dependencycheck.dependency.Dependency; -27 import org.owasp.dependencycheck.utils.Checksum; -28 import org.owasp.dependencycheck.utils.FileFilterBuilder; -29 import org.owasp.dependencycheck.utils.Settings; -30 import org.slf4j.Logger; -31 import org.slf4j.LoggerFactory; -32 -33 import java.io.FileFilter; -34 import java.io.FileInputStream; -35 import java.io.FileNotFoundException; -36 import java.nio.charset.Charset; -37 import java.security.MessageDigest; -38 import java.security.NoSuchAlgorithmException; -39 import org.owasp.dependencycheck.exception.InitializationException; +27 import org.owasp.dependencycheck.exception.InitializationException; +28 import org.owasp.dependencycheck.utils.Checksum; +29 import org.owasp.dependencycheck.utils.FileFilterBuilder; +30 import org.owasp.dependencycheck.utils.Settings; +31 import org.slf4j.Logger; +32 import org.slf4j.LoggerFactory; +33 +34 import java.io.FileFilter; +35 import java.io.FileInputStream; +36 import java.io.FileNotFoundException; +37 import java.nio.charset.Charset; +38 import java.security.MessageDigest; +39 import java.security.NoSuchAlgorithmException; 40 41 /** 42 * Used to analyze a composer.lock file for a composer PHP app. @@ -93,91 +93,100 @@ 85 @Override 86 protected void initializeFileTypeAnalyzer() throws InitializationException { 87 try { -88 sha1 = MessageDigest.getInstance("SHA1"); -89 } catch (NoSuchAlgorithmException ex) { +88 getSha1MessageDigest(); +89 } catch (IllegalStateException ex) { 90 setEnabled(false); -91 throw new InitializationException("Unable to create SHA1 MmessageDigest", ex); +91 throw new InitializationException("Unable to create SHA1 MessageDigest", ex); 92 } 93 } 94 95 /** -96 * The MessageDigest for calculating a new digest for the new dependencies -97 * added. -98 */ -99 private MessageDigest sha1 = null; -100 -101 /** -102 * Entry point for the analyzer. -103 * -104 * @param dependency the dependency to analyze -105 * @param engine the engine scanning -106 * @throws AnalysisException if there's a failure during analysis -107 */ -108 @Override -109 protected void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { -110 FileInputStream fis = null; -111 try { -112 fis = new FileInputStream(dependency.getActualFile()); -113 final ComposerLockParser clp = new ComposerLockParser(fis); -114 LOGGER.info("Checking composer.lock file {}", dependency.getActualFilePath()); -115 clp.process(); -116 for (ComposerDependency dep : clp.getDependencies()) { -117 final Dependency d = new Dependency(dependency.getActualFile()); -118 d.setDisplayFileName(String.format("%s:%s/%s", dependency.getDisplayFileName(), dep.getGroup(), dep.getProject())); -119 final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject()); -120 d.setFilePath(filePath); -121 d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset())))); -122 d.getVendorEvidence().addEvidence(COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST); -123 d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST); -124 d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST); -125 LOGGER.info("Adding dependency {}", d); -126 engine.getDependencies().add(d); -127 } -128 } catch (FileNotFoundException fnfe) { -129 LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath()); -130 } catch (ComposerException ce) { -131 LOGGER.warn("Error parsing composer.json {}", dependency.getActualFilePath(), ce); -132 } finally { -133 if (fis != null) { -134 try { -135 fis.close(); -136 } catch (Exception e) { -137 LOGGER.debug("Unable to close file", e); -138 } -139 } -140 } -141 } -142 -143 /** -144 * Gets the key to determine whether the analyzer is enabled. -145 * -146 * @return the key specifying whether the analyzer is enabled -147 */ -148 @Override -149 protected String getAnalyzerEnabledSettingKey() { -150 return Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED; -151 } -152 -153 /** -154 * Returns the analyzer's name. -155 * -156 * @return the analyzer's name -157 */ -158 @Override -159 public String getName() { -160 return ANALYZER_NAME; -161 } -162 -163 /** -164 * Returns the phase this analyzer should run under. -165 * -166 * @return the analysis phase -167 */ -168 @Override -169 public AnalysisPhase getAnalysisPhase() { -170 return AnalysisPhase.INFORMATION_COLLECTION; -171 } -172 } +96 * Entry point for the analyzer. +97 * +98 * @param dependency the dependency to analyze +99 * @param engine the engine scanning +100 * @throws AnalysisException if there's a failure during analysis +101 */ +102 @Override +103 protected void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { +104 FileInputStream fis = null; +105 try { +106 fis = new FileInputStream(dependency.getActualFile()); +107 final ComposerLockParser clp = new ComposerLockParser(fis); +108 LOGGER.info("Checking composer.lock file {}", dependency.getActualFilePath()); +109 clp.process(); +110 for (ComposerDependency dep : clp.getDependencies()) { +111 final Dependency d = new Dependency(dependency.getActualFile()); +112 d.setDisplayFileName(String.format("%s:%s/%s", dependency.getDisplayFileName(), dep.getGroup(), dep.getProject())); +113 final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject()); +114 final MessageDigest sha1 = getSha1MessageDigest(); +115 d.setFilePath(filePath); +116 d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset())))); +117 d.getVendorEvidence().addEvidence(COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST); +118 d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST); +119 d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST); +120 LOGGER.info("Adding dependency {}", d); +121 engine.getDependencies().add(d); +122 } +123 } catch (FileNotFoundException fnfe) { +124 LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath()); +125 } catch (ComposerException ce) { +126 LOGGER.warn("Error parsing composer.json {}", dependency.getActualFilePath(), ce); +127 } finally { +128 if (fis != null) { +129 try { +130 fis.close(); +131 } catch (Exception e) { +132 LOGGER.debug("Unable to close file", e); +133 } +134 } +135 } +136 } +137 +138 /** +139 * Gets the key to determine whether the analyzer is enabled. +140 * +141 * @return the key specifying whether the analyzer is enabled +142 */ +143 @Override +144 protected String getAnalyzerEnabledSettingKey() { +145 return Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED; +146 } +147 +148 /** +149 * Returns the analyzer's name. +150 * +151 * @return the analyzer's name +152 */ +153 @Override +154 public String getName() { +155 return ANALYZER_NAME; +156 } +157 +158 /** +159 * Returns the phase this analyzer should run under. +160 * +161 * @return the analysis phase +162 */ +163 @Override +164 public AnalysisPhase getAnalysisPhase() { +165 return AnalysisPhase.INFORMATION_COLLECTION; +166 } +167 +168 /** +169 * Returns the sha1 message digest. +170 * +171 * @return the sha1 message digest +172 */ +173 private MessageDigest getSha1MessageDigest() { +174 try { +175 return MessageDigest.getInstance("SHA1"); +176 } catch (NoSuchAlgorithmException e) { +177 LOGGER.error(e.getMessage()); +178 throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e); +179 } +180 } +181 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html index 0ab088c9a..a319654cc 100644 --- a/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.html @@ -54,7 +54,7 @@ 46 * 47 * @author Jeremy Long 48 */ -49 public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Analyzer { +49 public class DependencyBundlingAnalyzer extends AbstractAnalyzer { 50 51 /** 52 * The Logger. @@ -66,505 +66,526 @@ 58 * A pattern for obtaining the first part of a filename. 59 */ 60 private static final Pattern STARTING_TEXT_PATTERN = Pattern.compile("^[a-zA-Z0-9]*"); -61 /** -62 * a flag indicating if this analyzer has run. This analyzer only runs once. -63 */ -64 private boolean analyzed = false; -65 //</editor-fold> -66 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> +61 +62 /** +63 * a flag indicating if this analyzer has run. This analyzer only runs once. +64 */ +65 private boolean analyzed = false; +66 67 /** -68 * The name of the analyzer. -69 */ -70 private static final String ANALYZER_NAME = "Dependency Bundling Analyzer"; -71 /** -72 * The phase that this analyzer is intended to run in. +68 * Returns a flag indicating if this analyzer has run. This analyzer only +69 * runs once. Note this is currently only used in the unit tests. +70 * +71 * @return a flag indicating if this analyzer has run. This analyzer only +72 * runs once 73 */ -74 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS; -75 -76 /** -77 * Returns the name of the analyzer. -78 * -79 * @return the name of the analyzer. -80 */ -81 @Override -82 public String getName() { -83 return ANALYZER_NAME; -84 } -85 -86 /** -87 * Returns the phase that the analyzer is intended to run in. -88 * -89 * @return the phase that the analyzer is intended to run in. -90 */ -91 @Override -92 public AnalysisPhase getAnalysisPhase() { -93 return ANALYSIS_PHASE; -94 } -95 //</editor-fold> -96 -97 /** -98 * Analyzes a set of dependencies. If they have been found to have the same -99 * base path and the same set of identifiers they are likely related. The -100 * related dependencies are bundled into a single reportable item. +74 protected boolean getAnalyzed() { +75 return analyzed; +76 } +77 +78 //</editor-fold> +79 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> +80 /** +81 * The name of the analyzer. +82 */ +83 private static final String ANALYZER_NAME = "Dependency Bundling Analyzer"; +84 /** +85 * The phase that this analyzer is intended to run in. +86 */ +87 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS; +88 +89 /** +90 * Returns the name of the analyzer. +91 * +92 * @return the name of the analyzer. +93 */ +94 @Override +95 public String getName() { +96 return ANALYZER_NAME; +97 } +98 +99 /** +100 * Returns the phase that the analyzer is intended to run in. 101 * -102 * @param ignore this analyzer ignores the dependency being analyzed -103 * @param engine the engine that is scanning the dependencies -104 * @throws AnalysisException is thrown if there is an error reading the JAR -105 * file. -106 */ -107 @Override -108 public void analyze(Dependency ignore, Engine engine) throws AnalysisException { -109 if (!analyzed) { -110 analyzed = true; -111 final Set<Dependency> dependenciesToRemove = new HashSet<Dependency>(); -112 final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator(); -113 //for (Dependency nextDependency : engine.getDependencies()) { -114 while (mainIterator.hasNext()) { -115 final Dependency dependency = mainIterator.next(); -116 if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) { -117 final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex()); -118 while (subIterator.hasNext()) { -119 final Dependency nextDependency = subIterator.next(); -120 Dependency main = null; -121 if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath()) -122 && !containedInWar(nextDependency.getFilePath())) { -123 if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) { -124 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -125 } else { -126 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -127 break; //since we merged into the next dependency - skip forward to the next in mainIterator -128 } -129 } else if (isShadedJar(dependency, nextDependency)) { -130 if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) { -131 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -132 nextDependency.getRelatedDependencies().remove(dependency); -133 break; -134 } else { -135 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -136 dependency.getRelatedDependencies().remove(nextDependency); -137 } -138 } else if (cpeIdentifiersMatch(dependency, nextDependency) -139 && hasSameBasePath(dependency, nextDependency) -140 && fileNameMatch(dependency, nextDependency)) { -141 if (isCore(dependency, nextDependency)) { -142 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -143 } else { -144 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -145 break; //since we merged into the next dependency - skip forward to the next in mainIterator -146 } -147 } else if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) { -148 if (main == dependency) { +102 * @return the phase that the analyzer is intended to run in. +103 */ +104 @Override +105 public AnalysisPhase getAnalysisPhase() { +106 return ANALYSIS_PHASE; +107 } +108 //</editor-fold> +109 +110 /** +111 * Does not support parallel processing as it only runs once and then +112 * operates on <em>all</em> dependencies. +113 * +114 * @return whether or not parallel processing is enabled +115 * @see #analyze(Dependency, Engine) +116 */ +117 @Override +118 public boolean supportsParallelProcessing() { +119 return false; +120 } +121 +122 /** +123 * Analyzes a set of dependencies. If they have been found to have the same +124 * base path and the same set of identifiers they are likely related. The +125 * related dependencies are bundled into a single reportable item. +126 * +127 * @param ignore this analyzer ignores the dependency being analyzed +128 * @param engine the engine that is scanning the dependencies +129 * @throws AnalysisException is thrown if there is an error reading the JAR +130 * file. +131 */ +132 @Override +133 public void analyze(Dependency ignore, Engine engine) throws AnalysisException { +134 if (!analyzed) { +135 analyzed = true; +136 final Set<Dependency> dependenciesToRemove = new HashSet<Dependency>(); +137 final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator(); +138 //for (Dependency nextDependency : engine.getDependencies()) { +139 while (mainIterator.hasNext()) { +140 final Dependency dependency = mainIterator.next(); +141 if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) { +142 final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex()); +143 while (subIterator.hasNext()) { +144 final Dependency nextDependency = subIterator.next(); +145 Dependency main = null; +146 if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath()) +147 && !containedInWar(nextDependency.getFilePath())) { +148 if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) { 149 mergeDependencies(dependency, nextDependency, dependenciesToRemove); 150 } else { 151 mergeDependencies(nextDependency, dependency, dependenciesToRemove); 152 break; //since we merged into the next dependency - skip forward to the next in mainIterator 153 } -154 } else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) { -155 if (main == dependency) { -156 mergeDependencies(dependency, nextDependency, dependenciesToRemove); -157 } else { -158 mergeDependencies(nextDependency, dependency, dependenciesToRemove); -159 break; //since we merged into the next dependency - skip forward to the next in mainIterator -160 } -161 } -162 } -163 } -164 } -165 //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions -166 // was difficult because of the inner iterator. -167 engine.getDependencies().removeAll(dependenciesToRemove); -168 } -169 } -170 -171 /** -172 * Adds the relatedDependency to the dependency's related dependencies. -173 * -174 * @param dependency the main dependency -175 * @param relatedDependency a collection of dependencies to be removed from -176 * the main analysis loop, this is the source of dependencies to remove -177 * @param dependenciesToRemove a collection of dependencies that will be -178 * removed from the main analysis loop, this function adds to this -179 * collection -180 */ -181 private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) { -182 dependency.addRelatedDependency(relatedDependency); -183 final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator(); -184 while (i.hasNext()) { -185 dependency.addRelatedDependency(i.next()); -186 i.remove(); -187 } -188 if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) { -189 dependency.addAllProjectReferences(relatedDependency.getProjectReferences()); -190 } -191 dependenciesToRemove.add(relatedDependency); -192 } -193 -194 /** -195 * Attempts to trim a maven repo to a common base path. This is typically -196 * [drive]\[repo_location]\repository\[path1]\[path2]. -197 * -198 * @param path the path to trim -199 * @return a string representing the base path. -200 */ -201 private String getBaseRepoPath(final String path) { -202 int pos = path.indexOf("repository" + File.separator) + 11; -203 if (pos < 0) { -204 return path; -205 } -206 int tmp = path.indexOf(File.separator, pos); -207 if (tmp <= 0) { -208 return path; -209 } -210 if (tmp > 0) { -211 pos = tmp + 1; +154 } else if (isShadedJar(dependency, nextDependency)) { +155 if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) { +156 mergeDependencies(nextDependency, dependency, dependenciesToRemove); +157 nextDependency.getRelatedDependencies().remove(dependency); +158 break; +159 } else { +160 mergeDependencies(dependency, nextDependency, dependenciesToRemove); +161 dependency.getRelatedDependencies().remove(nextDependency); +162 } +163 } else if (cpeIdentifiersMatch(dependency, nextDependency) +164 && hasSameBasePath(dependency, nextDependency) +165 && fileNameMatch(dependency, nextDependency)) { +166 if (isCore(dependency, nextDependency)) { +167 mergeDependencies(dependency, nextDependency, dependenciesToRemove); +168 } else { +169 mergeDependencies(nextDependency, dependency, dependenciesToRemove); +170 break; //since we merged into the next dependency - skip forward to the next in mainIterator +171 } +172 } else if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) { +173 if (main == dependency) { +174 mergeDependencies(dependency, nextDependency, dependenciesToRemove); +175 } else { +176 mergeDependencies(nextDependency, dependency, dependenciesToRemove); +177 break; //since we merged into the next dependency - skip forward to the next in mainIterator +178 } +179 } else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) { +180 if (main == dependency) { +181 mergeDependencies(dependency, nextDependency, dependenciesToRemove); +182 } else { +183 mergeDependencies(nextDependency, dependency, dependenciesToRemove); +184 break; //since we merged into the next dependency - skip forward to the next in mainIterator +185 } +186 } +187 } +188 } +189 } +190 //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions +191 // was difficult because of the inner iterator. +192 engine.getDependencies().removeAll(dependenciesToRemove); +193 } +194 } +195 +196 /** +197 * Adds the relatedDependency to the dependency's related dependencies. +198 * +199 * @param dependency the main dependency +200 * @param relatedDependency a collection of dependencies to be removed from +201 * the main analysis loop, this is the source of dependencies to remove +202 * @param dependenciesToRemove a collection of dependencies that will be +203 * removed from the main analysis loop, this function adds to this +204 * collection +205 */ +206 private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) { +207 dependency.addRelatedDependency(relatedDependency); +208 final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator(); +209 while (i.hasNext()) { +210 dependency.addRelatedDependency(i.next()); +211 i.remove(); 212 } -213 tmp = path.indexOf(File.separator, pos); -214 if (tmp > 0) { -215 pos = tmp + 1; -216 } -217 return path.substring(0, pos); -218 } -219 -220 /** -221 * Returns true if the file names (and version if it exists) of the two -222 * dependencies are sufficiently similar. -223 * -224 * @param dependency1 a dependency2 to compare -225 * @param dependency2 a dependency2 to compare -226 * @return true if the identifiers in the two supplied dependencies are -227 * equal -228 */ -229 private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) { -230 if (dependency1 == null || dependency1.getFileName() == null -231 || dependency2 == null || dependency2.getFileName() == null) { -232 return false; -233 } -234 final String fileName1 = dependency1.getActualFile().getName(); -235 final String fileName2 = dependency2.getActualFile().getName(); -236 -237 //version check -238 final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1); -239 final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2); -240 if (version1 != null && version2 != null && !version1.equals(version2)) { -241 return false; -242 } -243 -244 //filename check -245 final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1); -246 final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2); -247 if (match1.find() && match2.find()) { -248 return match1.group().equals(match2.group()); -249 } -250 -251 return false; -252 } -253 -254 /** -255 * Returns true if the CPE identifiers in the two supplied dependencies are -256 * equal. -257 * -258 * @param dependency1 a dependency2 to compare -259 * @param dependency2 a dependency2 to compare -260 * @return true if the identifiers in the two supplied dependencies are -261 * equal -262 */ -263 private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) { -264 if (dependency1 == null || dependency1.getIdentifiers() == null -265 || dependency2 == null || dependency2.getIdentifiers() == null) { +213 if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) { +214 dependency.addAllProjectReferences(relatedDependency.getProjectReferences()); +215 } +216 dependenciesToRemove.add(relatedDependency); +217 } +218 +219 /** +220 * Attempts to trim a maven repo to a common base path. This is typically +221 * [drive]\[repo_location]\repository\[path1]\[path2]. +222 * +223 * @param path the path to trim +224 * @return a string representing the base path. +225 */ +226 private String getBaseRepoPath(final String path) { +227 int pos = path.indexOf("repository" + File.separator) + 11; +228 if (pos < 0) { +229 return path; +230 } +231 int tmp = path.indexOf(File.separator, pos); +232 if (tmp <= 0) { +233 return path; +234 } +235 if (tmp > 0) { +236 pos = tmp + 1; +237 } +238 tmp = path.indexOf(File.separator, pos); +239 if (tmp > 0) { +240 pos = tmp + 1; +241 } +242 return path.substring(0, pos); +243 } +244 +245 /** +246 * Returns true if the file names (and version if it exists) of the two +247 * dependencies are sufficiently similar. +248 * +249 * @param dependency1 a dependency2 to compare +250 * @param dependency2 a dependency2 to compare +251 * @return true if the identifiers in the two supplied dependencies are +252 * equal +253 */ +254 private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) { +255 if (dependency1 == null || dependency1.getFileName() == null +256 || dependency2 == null || dependency2.getFileName() == null) { +257 return false; +258 } +259 final String fileName1 = dependency1.getActualFile().getName(); +260 final String fileName2 = dependency2.getActualFile().getName(); +261 +262 //version check +263 final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1); +264 final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2); +265 if (version1 != null && version2 != null && !version1.equals(version2)) { 266 return false; 267 } -268 boolean matches = false; -269 int cpeCount1 = 0; -270 int cpeCount2 = 0; -271 for (Identifier i : dependency1.getIdentifiers()) { -272 if ("cpe".equals(i.getType())) { -273 cpeCount1 += 1; -274 } -275 } -276 for (Identifier i : dependency2.getIdentifiers()) { -277 if ("cpe".equals(i.getType())) { -278 cpeCount2 += 1; -279 } -280 } -281 if (cpeCount1 > 0 && cpeCount1 == cpeCount2) { -282 for (Identifier i : dependency1.getIdentifiers()) { -283 if ("cpe".equals(i.getType())) { -284 matches |= dependency2.getIdentifiers().contains(i); -285 if (!matches) { -286 break; -287 } -288 } -289 } -290 } -291 LOGGER.debug("IdentifiersMatch={} ({}, {})", matches, dependency1.getFileName(), dependency2.getFileName()); -292 return matches; -293 } -294 -295 /** -296 * Determines if the two dependencies have the same base path. -297 * -298 * @param dependency1 a Dependency object -299 * @param dependency2 a Dependency object -300 * @return true if the base paths of the dependencies are identical -301 */ -302 private boolean hasSameBasePath(Dependency dependency1, Dependency dependency2) { -303 if (dependency1 == null || dependency2 == null) { -304 return false; +268 +269 //filename check +270 final Matcher match1 = STARTING_TEXT_PATTERN.matcher(fileName1); +271 final Matcher match2 = STARTING_TEXT_PATTERN.matcher(fileName2); +272 if (match1.find() && match2.find()) { +273 return match1.group().equals(match2.group()); +274 } +275 +276 return false; +277 } +278 +279 /** +280 * Returns true if the CPE identifiers in the two supplied dependencies are +281 * equal. +282 * +283 * @param dependency1 a dependency2 to compare +284 * @param dependency2 a dependency2 to compare +285 * @return true if the identifiers in the two supplied dependencies are +286 * equal +287 */ +288 private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) { +289 if (dependency1 == null || dependency1.getIdentifiers() == null +290 || dependency2 == null || dependency2.getIdentifiers() == null) { +291 return false; +292 } +293 boolean matches = false; +294 int cpeCount1 = 0; +295 int cpeCount2 = 0; +296 for (Identifier i : dependency1.getIdentifiers()) { +297 if ("cpe".equals(i.getType())) { +298 cpeCount1 += 1; +299 } +300 } +301 for (Identifier i : dependency2.getIdentifiers()) { +302 if ("cpe".equals(i.getType())) { +303 cpeCount2 += 1; +304 } 305 } -306 final File lFile = new File(dependency1.getFilePath()); -307 String left = lFile.getParent(); -308 final File rFile = new File(dependency2.getFilePath()); -309 String right = rFile.getParent(); -310 if (left == null) { -311 return right == null; -312 } else if (right == null) { -313 return false; -314 } -315 if (left.equalsIgnoreCase(right)) { -316 return true; -317 } -318 -319 if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) { -320 left = getBaseRepoPath(left); -321 right = getBaseRepoPath(right); -322 } -323 if (left.equalsIgnoreCase(right)) { -324 return true; -325 } -326 //new code -327 for (Dependency child : dependency2.getRelatedDependencies()) { -328 if (hasSameBasePath(dependency1, child)) { -329 return true; -330 } -331 } -332 return false; -333 } -334 -335 /** -336 * Bundling Ruby gems that are identified from different .gemspec files but -337 * denote the same package path. This happens when Ruby bundler installs an -338 * application's dependencies by running "bundle install". -339 * -340 * @param dependency1 dependency to compare -341 * @param dependency2 dependency to compare -342 * @return true if the the dependencies being analyzed appear to be the -343 * same; otherwise false -344 */ -345 private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) { -346 if (dependency1 == null || dependency2 == null -347 || !dependency1.getFileName().endsWith(".gemspec") -348 || !dependency2.getFileName().endsWith(".gemspec") -349 || dependency1.getPackagePath() == null -350 || dependency2.getPackagePath() == null) { -351 return false; -352 } -353 if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) { -354 return true; -355 } -356 +306 if (cpeCount1 > 0 && cpeCount1 == cpeCount2) { +307 for (Identifier i : dependency1.getIdentifiers()) { +308 if ("cpe".equals(i.getType())) { +309 matches |= dependency2.getIdentifiers().contains(i); +310 if (!matches) { +311 break; +312 } +313 } +314 } +315 } +316 LOGGER.debug("IdentifiersMatch={} ({}, {})", matches, dependency1.getFileName(), dependency2.getFileName()); +317 return matches; +318 } +319 +320 /** +321 * Determines if the two dependencies have the same base path. +322 * +323 * @param dependency1 a Dependency object +324 * @param dependency2 a Dependency object +325 * @return true if the base paths of the dependencies are identical +326 */ +327 private boolean hasSameBasePath(Dependency dependency1, Dependency dependency2) { +328 if (dependency1 == null || dependency2 == null) { +329 return false; +330 } +331 final File lFile = new File(dependency1.getFilePath()); +332 String left = lFile.getParent(); +333 final File rFile = new File(dependency2.getFilePath()); +334 String right = rFile.getParent(); +335 if (left == null) { +336 return right == null; +337 } else if (right == null) { +338 return false; +339 } +340 if (left.equalsIgnoreCase(right)) { +341 return true; +342 } +343 +344 if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) { +345 left = getBaseRepoPath(left); +346 right = getBaseRepoPath(right); +347 } +348 if (left.equalsIgnoreCase(right)) { +349 return true; +350 } +351 //new code +352 for (Dependency child : dependency2.getRelatedDependencies()) { +353 if (hasSameBasePath(dependency1, child)) { +354 return true; +355 } +356 } 357 return false; 358 } 359 360 /** -361 * Ruby gems installed by "bundle install" can have zero or more *.gemspec -362 * files, all of which have the same packagePath and should be grouped. If -363 * one of these gemspec is from <parent>/specifications/*.gemspec, because -364 * it is a stub with fully resolved gem meta-data created by Ruby bundler, -365 * this dependency should be the main one. Otherwise, use dependency2 as -366 * main. -367 * -368 * This method returns null if any dependency is not from *.gemspec, or the -369 * two do not have the same packagePath. In this case, they should not be -370 * grouped. -371 * -372 * @param dependency1 dependency to compare -373 * @param dependency2 dependency to compare -374 * @return the main dependency; or null if a gemspec is not included in the -375 * analysis -376 */ -377 private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) { -378 if (isSameRubyGem(dependency1, dependency2)) { -379 final File lFile = dependency1.getActualFile(); -380 final File left = lFile.getParentFile(); -381 if (left != null && left.getName().equalsIgnoreCase("specifications")) { -382 return dependency1; -383 } -384 return dependency2; -385 } -386 return null; -387 } -388 -389 /** -390 * Bundling same swift dependencies with the same packagePath but identified -391 * by different analyzers. +361 * Bundling Ruby gems that are identified from different .gemspec files but +362 * denote the same package path. This happens when Ruby bundler installs an +363 * application's dependencies by running "bundle install". +364 * +365 * @param dependency1 dependency to compare +366 * @param dependency2 dependency to compare +367 * @return true if the the dependencies being analyzed appear to be the +368 * same; otherwise false +369 */ +370 private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) { +371 if (dependency1 == null || dependency2 == null +372 || !dependency1.getFileName().endsWith(".gemspec") +373 || !dependency2.getFileName().endsWith(".gemspec") +374 || dependency1.getPackagePath() == null +375 || dependency2.getPackagePath() == null) { +376 return false; +377 } +378 return dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath()); +379 } +380 +381 /** +382 * Ruby gems installed by "bundle install" can have zero or more *.gemspec +383 * files, all of which have the same packagePath and should be grouped. If +384 * one of these gemspec is from <parent>/specifications/*.gemspec, because +385 * it is a stub with fully resolved gem meta-data created by Ruby bundler, +386 * this dependency should be the main one. Otherwise, use dependency2 as +387 * main. +388 * +389 * This method returns null if any dependency is not from *.gemspec, or the +390 * two do not have the same packagePath. In this case, they should not be +391 * grouped. 392 * -393 * @param dependency1 dependency to test -394 * @param dependency2 dependency to test -395 * @return <code>true</code> if the dependencies appear to be the same; -396 * otherwise <code>false</code> +393 * @param dependency1 dependency to compare +394 * @param dependency2 dependency to compare +395 * @return the main dependency; or null if a gemspec is not included in the +396 * analysis 397 */ -398 private boolean isSameSwiftPackage(Dependency dependency1, Dependency dependency2) { -399 if (dependency1 == null || dependency2 == null -400 || (!dependency1.getFileName().endsWith(".podspec") -401 && !dependency1.getFileName().equals("Package.swift")) -402 || (!dependency2.getFileName().endsWith(".podspec") -403 && !dependency2.getFileName().equals("Package.swift")) -404 || dependency1.getPackagePath() == null -405 || dependency2.getPackagePath() == null) { -406 return false; -407 } -408 if (dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath())) { -409 return true; -410 } -411 return false; -412 } -413 -414 /** -415 * Determines which of the swift dependencies should be considered the -416 * primary. -417 * -418 * @param dependency1 the first swift dependency to compare -419 * @param dependency2 the second swift dependency to compare -420 * @return the primary swift dependency -421 */ -422 private Dependency getMainSwiftDependency(Dependency dependency1, Dependency dependency2) { -423 if (isSameSwiftPackage(dependency1, dependency2)) { -424 if (dependency1.getFileName().endsWith(".podspec")) { -425 return dependency1; -426 } -427 return dependency2; +398 private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) { +399 if (isSameRubyGem(dependency1, dependency2)) { +400 final File lFile = dependency1.getActualFile(); +401 final File left = lFile.getParentFile(); +402 if (left != null && left.getName().equalsIgnoreCase("specifications")) { +403 return dependency1; +404 } +405 return dependency2; +406 } +407 return null; +408 } +409 +410 /** +411 * Bundling same swift dependencies with the same packagePath but identified +412 * by different analyzers. +413 * +414 * @param dependency1 dependency to test +415 * @param dependency2 dependency to test +416 * @return <code>true</code> if the dependencies appear to be the same; +417 * otherwise <code>false</code> +418 */ +419 private boolean isSameSwiftPackage(Dependency dependency1, Dependency dependency2) { +420 if (dependency1 == null || dependency2 == null +421 || (!dependency1.getFileName().endsWith(".podspec") +422 && !dependency1.getFileName().equals("Package.swift")) +423 || (!dependency2.getFileName().endsWith(".podspec") +424 && !dependency2.getFileName().equals("Package.swift")) +425 || dependency1.getPackagePath() == null +426 || dependency2.getPackagePath() == null) { +427 return false; 428 } -429 return null; +429 return dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath()); 430 } 431 432 /** -433 * This is likely a very broken attempt at determining if the 'left' -434 * dependency is the 'core' library in comparison to the 'right' library. +433 * Determines which of the swift dependencies should be considered the +434 * primary. 435 * -436 * @param left the dependency to test -437 * @param right the dependency to test against -438 * @return a boolean indicating whether or not the left dependency should be -439 * considered the "core" version. -440 */ -441 boolean isCore(Dependency left, Dependency right) { -442 final String leftName = left.getFileName().toLowerCase(); -443 final String rightName = right.getFileName().toLowerCase(); -444 -445 final boolean returnVal; -446 if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") -447 || rightName.contains("core") && !leftName.contains("core") -448 || rightName.contains("kernel") && !leftName.contains("kernel")) { -449 returnVal = false; -450 } else if (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") -451 || !rightName.contains("core") && leftName.contains("core") -452 || !rightName.contains("kernel") && leftName.contains("kernel")) { -453 returnVal = true; -454 // } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) { -455 // returnVal = true; -456 // } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) { -457 // returnVal = false; -458 } else { -459 /* -460 * considered splitting the names up and comparing the components, -461 * but decided that the file name length should be sufficient as the -462 * "core" component, if this follows a normal naming protocol should -463 * be shorter: -464 * axis2-saaj-1.4.1.jar -465 * axis2-1.4.1.jar <----- -466 * axis2-kernel-1.4.1.jar -467 */ -468 returnVal = leftName.length() <= rightName.length(); -469 } -470 LOGGER.debug("IsCore={} ({}, {})", returnVal, left.getFileName(), right.getFileName()); -471 return returnVal; -472 } -473 -474 /** -475 * Compares the SHA1 hashes of two dependencies to determine if they are -476 * equal. -477 * -478 * @param dependency1 a dependency object to compare -479 * @param dependency2 a dependency object to compare -480 * @return true if the sha1 hashes of the two dependencies match; otherwise -481 * false -482 */ -483 private boolean hashesMatch(Dependency dependency1, Dependency dependency2) { -484 if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) { -485 return false; -486 } -487 return dependency1.getSha1sum().equals(dependency2.getSha1sum()); -488 } -489 -490 /** -491 * Determines if the jar is shaded and the created pom.xml identified the -492 * same CPE as the jar - if so, the pom.xml dependency should be removed. -493 * -494 * @param dependency a dependency to check -495 * @param nextDependency another dependency to check -496 * @return true if on of the dependencies is a pom.xml and the identifiers -497 * between the two collections match; otherwise false -498 */ -499 private boolean isShadedJar(Dependency dependency, Dependency nextDependency) { -500 final String mainName = dependency.getFileName().toLowerCase(); -501 final String nextName = nextDependency.getFileName().toLowerCase(); -502 if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) { -503 return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers()); -504 } else if (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) { -505 return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers()); -506 } -507 return false; -508 } -509 -510 /** -511 * Determines which path is shortest; if path lengths are equal then we use -512 * compareTo of the string method to determine if the first path is smaller. -513 * -514 * @param left the first path to compare -515 * @param right the second path to compare -516 * @return <code>true</code> if the leftPath is the shortest; otherwise -517 * <code>false</code> -518 */ -519 protected boolean firstPathIsShortest(String left, String right) { -520 final String leftPath = left.replace('\\', '/'); -521 final String rightPath = right.replace('\\', '/'); -522 -523 final int leftCount = countChar(leftPath, '/'); -524 final int rightCount = countChar(rightPath, '/'); -525 if (leftCount == rightCount) { -526 return leftPath.compareTo(rightPath) <= 0; -527 } else { -528 return leftCount < rightCount; -529 } -530 } -531 -532 /** -533 * Counts the number of times the character is present in the string. -534 * -535 * @param string the string to count the characters in -536 * @param c the character to count -537 * @return the number of times the character is present in the string -538 */ -539 private int countChar(String string, char c) { -540 int count = 0; -541 final int max = string.length(); -542 for (int i = 0; i < max; i++) { -543 if (c == string.charAt(i)) { -544 count++; -545 } -546 } -547 return count; -548 } -549 -550 /** -551 * Checks if the given file path is contained within a war or ear file. -552 * -553 * @param filePath the file path to check -554 * @return true if the path contains '.war\' or '.ear\'. -555 */ -556 private boolean containedInWar(String filePath) { -557 return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*"); -558 } -559 } +436 * @param dependency1 the first swift dependency to compare +437 * @param dependency2 the second swift dependency to compare +438 * @return the primary swift dependency +439 */ +440 private Dependency getMainSwiftDependency(Dependency dependency1, Dependency dependency2) { +441 if (isSameSwiftPackage(dependency1, dependency2)) { +442 if (dependency1.getFileName().endsWith(".podspec")) { +443 return dependency1; +444 } +445 return dependency2; +446 } +447 return null; +448 } +449 +450 /** +451 * This is likely a very broken attempt at determining if the 'left' +452 * dependency is the 'core' library in comparison to the 'right' library. +453 * +454 * @param left the dependency to test +455 * @param right the dependency to test against +456 * @return a boolean indicating whether or not the left dependency should be +457 * considered the "core" version. +458 */ +459 boolean isCore(Dependency left, Dependency right) { +460 final String leftName = left.getFileName().toLowerCase(); +461 final String rightName = right.getFileName().toLowerCase(); +462 +463 final boolean returnVal; +464 if (!rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") +465 || rightName.contains("core") && !leftName.contains("core") +466 || rightName.contains("kernel") && !leftName.contains("kernel")) { +467 returnVal = false; +468 } else if (rightName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") && !leftName.matches(".*\\.(tar|tgz|gz|zip|ear|war).+") +469 || !rightName.contains("core") && leftName.contains("core") +470 || !rightName.contains("kernel") && leftName.contains("kernel")) { +471 returnVal = true; +472 // } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) { +473 // returnVal = true; +474 // } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) { +475 // returnVal = false; +476 } else { +477 /* +478 * considered splitting the names up and comparing the components, +479 * but decided that the file name length should be sufficient as the +480 * "core" component, if this follows a normal naming protocol should +481 * be shorter: +482 * axis2-saaj-1.4.1.jar +483 * axis2-1.4.1.jar <----- +484 * axis2-kernel-1.4.1.jar +485 */ +486 returnVal = leftName.length() <= rightName.length(); +487 } +488 LOGGER.debug("IsCore={} ({}, {})", returnVal, left.getFileName(), right.getFileName()); +489 return returnVal; +490 } +491 +492 /** +493 * Compares the SHA1 hashes of two dependencies to determine if they are +494 * equal. +495 * +496 * @param dependency1 a dependency object to compare +497 * @param dependency2 a dependency object to compare +498 * @return true if the sha1 hashes of the two dependencies match; otherwise +499 * false +500 */ +501 private boolean hashesMatch(Dependency dependency1, Dependency dependency2) { +502 if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) { +503 return false; +504 } +505 return dependency1.getSha1sum().equals(dependency2.getSha1sum()); +506 } +507 +508 /** +509 * Determines if the jar is shaded and the created pom.xml identified the +510 * same CPE as the jar - if so, the pom.xml dependency should be removed. +511 * +512 * @param dependency a dependency to check +513 * @param nextDependency another dependency to check +514 * @return true if on of the dependencies is a pom.xml and the identifiers +515 * between the two collections match; otherwise false +516 */ +517 private boolean isShadedJar(Dependency dependency, Dependency nextDependency) { +518 final String mainName = dependency.getFileName().toLowerCase(); +519 final String nextName = nextDependency.getFileName().toLowerCase(); +520 if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) { +521 return dependency.getIdentifiers().containsAll(nextDependency.getIdentifiers()); +522 } else if (nextName.endsWith(".jar") && mainName.endsWith("pom.xml")) { +523 return nextDependency.getIdentifiers().containsAll(dependency.getIdentifiers()); +524 } +525 return false; +526 } +527 +528 /** +529 * Determines which path is shortest; if path lengths are equal then we use +530 * compareTo of the string method to determine if the first path is smaller. +531 * +532 * @param left the first path to compare +533 * @param right the second path to compare +534 * @return <code>true</code> if the leftPath is the shortest; otherwise +535 * <code>false</code> +536 */ +537 protected boolean firstPathIsShortest(String left, String right) { +538 if (left.contains("dctemp")) { +539 return false; +540 } +541 final String leftPath = left.replace('\\', '/'); +542 final String rightPath = right.replace('\\', '/'); +543 +544 final int leftCount = countChar(leftPath, '/'); +545 final int rightCount = countChar(rightPath, '/'); +546 if (leftCount == rightCount) { +547 return leftPath.compareTo(rightPath) <= 0; +548 } else { +549 return leftCount < rightCount; +550 } +551 } +552 +553 /** +554 * Counts the number of times the character is present in the string. +555 * +556 * @param string the string to count the characters in +557 * @param c the character to count +558 * @return the number of times the character is present in the string +559 */ +560 private int countChar(String string, char c) { +561 int count = 0; +562 final int max = string.length(); +563 for (int i = 0; i < max; i++) { +564 if (c == string.charAt(i)) { +565 count++; +566 } +567 } +568 return count; +569 } +570 +571 /** +572 * Checks if the given file path is contained within a war or ear file. +573 * +574 * @param filePath the file path to check +575 * @return true if the path contains '.war\' or '.ear\'. +576 */ +577 private boolean containedInWar(String filePath) { +578 return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*"); +579 } +580 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html index 5638da2e4..008e9935e 100644 --- a/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.html @@ -431,64 +431,66 @@ 423 String parentPath = dependency.getFilePath().toLowerCase(); 424 if (parentPath.contains(".jar")) { 425 parentPath = parentPath.substring(0, parentPath.indexOf(".jar") + 4); -426 final Dependency parent = findDependency(parentPath, engine.getDependencies()); -427 if (parent != null) { -428 boolean remove = false; -429 for (Identifier i : dependency.getIdentifiers()) { -430 if ("cpe".equals(i.getType())) { -431 final String trimmedCPE = trimCpeToVendor(i.getValue()); -432 for (Identifier parentId : parent.getIdentifiers()) { -433 if ("cpe".equals(parentId.getType()) && parentId.getValue().startsWith(trimmedCPE)) { -434 remove |= true; -435 } -436 } -437 } -438 if (!remove) { //we can escape early -439 return; -440 } -441 } -442 if (remove) { -443 engine.getDependencies().remove(dependency); -444 } -445 } -446 } -447 -448 } -449 } -450 -451 /** -452 * Retrieves a given dependency, based on a given path, from a list of dependencies. -453 * -454 * @param dependencyPath the path of the dependency to return -455 * @param dependencies the collection of dependencies to search -456 * @return the dependency object for the given path, otherwise null -457 */ -458 private Dependency findDependency(String dependencyPath, List<Dependency> dependencies) { -459 for (Dependency d : dependencies) { -460 if (d.getFilePath().equalsIgnoreCase(dependencyPath)) { -461 return d; -462 } -463 } -464 return null; -465 } -466 -467 /** -468 * Takes a full CPE and returns the CPE trimmed to include only vendor and product. -469 * -470 * @param value the CPE value to trim -471 * @return a CPE value that only includes the vendor and product -472 */ -473 private String trimCpeToVendor(String value) { -474 //cpe:/a:jruby:jruby:1.0.8 -475 final int pos1 = value.indexOf(':', 7); //right of vendor -476 final int pos2 = value.indexOf(':', pos1 + 1); //right of product -477 if (pos2 < 0) { -478 return value; -479 } else { -480 return value.substring(0, pos2); -481 } -482 } -483 } +426 final List<Dependency> dependencies = engine.getDependencies(); +427 synchronized (dependencies) { +428 final Dependency parent = findDependency(parentPath, dependencies); +429 if (parent != null) { +430 boolean remove = false; +431 for (Identifier i : dependency.getIdentifiers()) { +432 if ("cpe".equals(i.getType())) { +433 final String trimmedCPE = trimCpeToVendor(i.getValue()); +434 for (Identifier parentId : parent.getIdentifiers()) { +435 if ("cpe".equals(parentId.getType()) && parentId.getValue().startsWith(trimmedCPE)) { +436 remove |= true; +437 } +438 } +439 } +440 if (!remove) { //we can escape early +441 return; +442 } +443 } +444 if (remove) { +445 dependencies.remove(dependency); +446 } +447 } +448 } +449 } +450 } +451 } +452 +453 /** +454 * Retrieves a given dependency, based on a given path, from a list of dependencies. +455 * +456 * @param dependencyPath the path of the dependency to return +457 * @param dependencies the collection of dependencies to search +458 * @return the dependency object for the given path, otherwise null +459 */ +460 private Dependency findDependency(String dependencyPath, List<Dependency> dependencies) { +461 for (Dependency d : dependencies) { +462 if (d.getFilePath().equalsIgnoreCase(dependencyPath)) { +463 return d; +464 } +465 } +466 return null; +467 } +468 +469 /** +470 * Takes a full CPE and returns the CPE trimmed to include only vendor and product. +471 * +472 * @param value the CPE value to trim +473 * @return a CPE value that only includes the vendor and product +474 */ +475 private String trimCpeToVendor(String value) { +476 //cpe:/a:jruby:jruby:1.0.8 +477 final int pos1 = value.indexOf(':', 7); //right of vendor +478 final int pos2 = value.indexOf(':', pos1 + 1); //right of product +479 if (pos2 < 0) { +480 return value; +481 } else { +482 return value.substring(0, pos2); +483 } +484 } +485 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html index 026d40df0..75221ae85 100644 --- a/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.html @@ -42,7 +42,7 @@ 34 * 35 * @author Jeremy Long 36 */ -37 public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer { +37 public class FileNameAnalyzer extends AbstractAnalyzer { 38 39 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> 40 /** diff --git a/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html index 0871b68a1..a9cf03d96 100644 --- a/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/HintAnalyzer.html @@ -59,7 +59,7 @@ 51 * 52 * @author Jeremy Long 53 */ -54 public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { +54 public class HintAnalyzer extends AbstractAnalyzer { 55 56 //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer"> 57 /** @@ -331,7 +331,7 @@ 323 try { 324 org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file); 325 } catch (IOException ex) { -326 throw new HintParseException("Unable to locate suppressions file in classpath", ex); +326 throw new HintParseException("Unable to locate hints file in classpath", ex); 327 } 328 } 329 } finally { diff --git a/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html index 21f77be2a..206409b8c 100644 --- a/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/JarAnalyzer.html @@ -34,15 +34,15 @@ 26 import java.io.OutputStream; 27 import java.io.Reader; 28 import java.util.ArrayList; -29 import java.util.Collections; -30 import java.util.Enumeration; -31 import java.util.HashMap; -32 import java.util.List; -33 import java.util.Map; -34 import java.util.Map.Entry; -35 import java.util.Properties; -36 import java.util.Set; -37 import java.util.StringTokenizer; +29 import java.util.Enumeration; +30 import java.util.HashMap; +31 import java.util.List; +32 import java.util.Map; +33 import java.util.Map.Entry; +34 import java.util.Properties; +35 import java.util.Set; +36 import java.util.StringTokenizer; +37 import java.util.concurrent.atomic.AtomicInteger; 38 import java.util.jar.Attributes; 39 import java.util.jar.JarEntry; 40 import java.util.jar.JarFile; @@ -84,7 +84,7 @@ 76 * The count of directories created during analysis. This is used for 77 * creating temporary directories. 78 */ -79 private static int dirCount = 0; +79 private static final AtomicInteger DIR_COUNT = new AtomicInteger(0); 80 /** 81 * The system independent newline character. 82 */ @@ -326,919 +326,921 @@ 318 pom.processProperties(pomProperties); 319 setPomEvidence(newDependency, pom, null); 320 engine.getDependencies().add(newDependency); -321 Collections.sort(engine.getDependencies()); -322 } else { -323 if (externalPom == null) { -324 pom = PomUtils.readPom(path, jar); -325 } else { -326 pom = PomUtils.readPom(externalPom); -327 } -328 if (pom != null) { -329 pom.processProperties(pomProperties); -330 foundSomething |= setPomEvidence(dependency, pom, classes); -331 } -332 } -333 } catch (AnalysisException ex) { -334 LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath()); -335 LOGGER.trace("", ex); -336 } -337 } -338 return foundSomething; -339 } -340 -341 /** -342 * Given a path to a pom.xml within a JarFile, this method attempts to load -343 * a sibling pom.properties if one exists. -344 * -345 * @param path the path to the pom.xml within the JarFile -346 * @param jar the JarFile to load the pom.properties from -347 * @return a Properties object or null if no pom.properties was found -348 * @throws IOException thrown if there is an exception reading the -349 * pom.properties -350 */ -351 private Properties retrievePomProperties(String path, final JarFile jar) throws IOException { -352 Properties pomProperties = null; -353 final String propPath = path.substring(0, path.length() - 7) + "pom.properies"; -354 final ZipEntry propEntry = jar.getEntry(propPath); -355 if (propEntry != null) { -356 Reader reader = null; -357 try { -358 reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8"); -359 pomProperties = new Properties(); -360 pomProperties.load(reader); -361 LOGGER.debug("Read pom.properties: {}", propPath); -362 } finally { -363 if (reader != null) { -364 try { -365 reader.close(); -366 } catch (IOException ex) { -367 LOGGER.trace("close error", ex); -368 } -369 } -370 } -371 } -372 return pomProperties; -373 } -374 -375 /** -376 * Searches a JarFile for pom.xml entries and returns a listing of these -377 * entries. -378 * -379 * @param jar the JarFile to search -380 * @return a list of pom.xml entries -381 * @throws IOException thrown if there is an exception reading a JarEntry -382 */ -383 private List<String> retrievePomListing(final JarFile jar) throws IOException { -384 final List<String> pomEntries = new ArrayList<String>(); -385 final Enumeration<JarEntry> entries = jar.entries(); -386 while (entries.hasMoreElements()) { -387 final JarEntry entry = entries.nextElement(); -388 final String entryName = (new File(entry.getName())).getName().toLowerCase(); -389 if (!entry.isDirectory() && "pom.xml".equals(entryName)) { -390 LOGGER.trace("POM Entry found: {}", entry.getName()); -391 pomEntries.add(entry.getName()); -392 } -393 } -394 return pomEntries; -395 } -396 -397 /** -398 * Retrieves the specified POM from a jar file and converts it to a Model. -399 * -400 * @param path the path to the pom.xml file within the jar file -401 * @param jar the jar file to extract the pom from -402 * @param dependency the dependency being analyzed -403 * @return returns the POM object -404 * @throws AnalysisException is thrown if there is an exception extracting -405 * or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object -406 */ -407 private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException { -408 InputStream input = null; -409 FileOutputStream fos = null; -410 final File tmpDir = getNextTempDirectory(); -411 final File file = new File(tmpDir, "pom.xml"); -412 try { -413 final ZipEntry entry = jar.getEntry(path); -414 if (entry == null) { -415 throw new AnalysisException(String.format("Pom (%s)does not exist in %s", path, jar.getName())); -416 } -417 input = jar.getInputStream(entry); -418 fos = new FileOutputStream(file); -419 IOUtils.copy(input, fos); -420 dependency.setActualFilePath(file.getAbsolutePath()); -421 } catch (IOException ex) { -422 LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath()); -423 LOGGER.error("", ex); -424 } finally { -425 closeStream(fos); -426 closeStream(input); -427 } -428 return PomUtils.readPom(file); -429 } -430 -431 /** -432 * Silently closes an input stream ignoring errors. -433 * -434 * @param stream an input stream to close -435 */ -436 private void closeStream(InputStream stream) { -437 if (stream != null) { -438 try { -439 stream.close(); -440 } catch (IOException ex) { -441 LOGGER.trace("", ex); -442 } -443 } -444 } -445 -446 /** -447 * Silently closes an output stream ignoring errors. -448 * -449 * @param stream an output stream to close -450 */ -451 private void closeStream(OutputStream stream) { -452 if (stream != null) { -453 try { -454 stream.close(); -455 } catch (IOException ex) { -456 LOGGER.trace("", ex); -457 } -458 } -459 } -460 -461 /** -462 * Sets evidence from the pom on the supplied dependency. -463 * -464 * @param dependency the dependency to set data on -465 * @param pom the information from the pom -466 * @param classes a collection of ClassNameInformation - containing data -467 * about the fully qualified class names within the JAR file being analyzed -468 * @return true if there was evidence within the pom that we could use; -469 * otherwise false -470 */ -471 public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) { -472 boolean foundSomething = false; -473 boolean addAsIdentifier = true; -474 if (pom == null) { -475 return foundSomething; -476 } -477 String groupid = pom.getGroupId(); -478 String parentGroupId = pom.getParentGroupId(); -479 String artifactid = pom.getArtifactId(); -480 String parentArtifactId = pom.getParentArtifactId(); -481 String version = pom.getVersion(); -482 String parentVersion = pom.getParentVersion(); -483 -484 if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) { -485 parentGroupId = null; -486 parentArtifactId = null; -487 parentVersion = null; -488 } -489 -490 if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) { -491 groupid = parentGroupId; -492 } -493 -494 final String originalGroupID = groupid; -495 if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) { -496 groupid = groupid.substring(4); -497 } -498 -499 if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) { -500 artifactid = parentArtifactId; -501 } -502 -503 final String originalArtifactID = artifactid; -504 if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) { -505 artifactid = artifactid.substring(4); -506 } -507 -508 if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) { -509 version = parentVersion; -510 } -511 -512 if (groupid != null && !groupid.isEmpty()) { -513 foundSomething = true; -514 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST); -515 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW); -516 addMatchingValues(classes, groupid, dependency.getVendorEvidence()); -517 addMatchingValues(classes, groupid, dependency.getProductEvidence()); -518 if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) { -519 dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM); -520 dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW); -521 addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence()); -522 addMatchingValues(classes, parentGroupId, dependency.getProductEvidence()); -523 } -524 } else { -525 addAsIdentifier = false; -526 } -527 -528 if (artifactid != null && !artifactid.isEmpty()) { -529 foundSomething = true; -530 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST); -531 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW); -532 addMatchingValues(classes, artifactid, dependency.getVendorEvidence()); -533 addMatchingValues(classes, artifactid, dependency.getProductEvidence()); -534 if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) { -535 dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM); -536 dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW); -537 addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence()); -538 addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence()); -539 } -540 } else { -541 addAsIdentifier = false; -542 } -543 -544 if (version != null && !version.isEmpty()) { -545 foundSomething = true; -546 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST); -547 if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) { -548 dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW); -549 } -550 } else { -551 addAsIdentifier = false; -552 } -553 -554 if (addAsIdentifier) { -555 dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH); -556 } -557 -558 // org name -559 final String org = pom.getOrganization(); -560 if (org != null && !org.isEmpty()) { -561 dependency.getVendorEvidence().addEvidence("pom", "organization name", org, Confidence.HIGH); -562 dependency.getProductEvidence().addEvidence("pom", "organization name", org, Confidence.LOW); -563 addMatchingValues(classes, org, dependency.getVendorEvidence()); -564 addMatchingValues(classes, org, dependency.getProductEvidence()); -565 } -566 //pom name -567 final String pomName = pom.getName(); -568 if (pomName -569 != null && !pomName.isEmpty()) { -570 foundSomething = true; -571 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); -572 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); -573 addMatchingValues(classes, pomName, dependency.getVendorEvidence()); -574 addMatchingValues(classes, pomName, dependency.getProductEvidence()); -575 } -576 -577 //Description -578 final String description = pom.getDescription(); -579 if (description != null && !description.isEmpty() && !description.startsWith("POM was created by")) { -580 foundSomething = true; -581 final String trimmedDescription = addDescription(dependency, description, "pom", "description"); -582 addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence()); -583 addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence()); -584 } -585 -586 final String projectURL = pom.getProjectURL(); -587 if (projectURL != null && !projectURL.trim().isEmpty()) { -588 dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST); -589 } -590 -591 extractLicense(pom, dependency); -592 return foundSomething; -593 } -594 -595 /** -596 * Analyzes the path information of the classes contained within the -597 * JarAnalyzer to try and determine possible vendor or product names. If any -598 * are found they are stored in the packageVendor and packageProduct -599 * hashSets. -600 * -601 * @param classNames a list of class names -602 * @param dependency a dependency to analyze -603 * @param addPackagesAsEvidence a flag indicating whether or not package -604 * names should be added as evidence. -605 */ -606 protected void analyzePackageNames(List<ClassNameInformation> classNames, -607 Dependency dependency, boolean addPackagesAsEvidence) { -608 final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>(); -609 final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>(); -610 analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers); -611 -612 final int classCount = classNames.size(); -613 final EvidenceCollection vendor = dependency.getVendorEvidence(); -614 final EvidenceCollection product = dependency.getProductEvidence(); -615 -616 for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) { -617 final float ratio = entry.getValue() / (float) classCount; -618 if (ratio > 0.5) { -619 //TODO remove weighting -620 vendor.addWeighting(entry.getKey()); -621 if (addPackagesAsEvidence && entry.getKey().length() > 1) { -622 vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); -623 } -624 } -625 } -626 for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) { -627 final float ratio = entry.getValue() / (float) classCount; -628 if (ratio > 0.5) { -629 product.addWeighting(entry.getKey()); -630 if (addPackagesAsEvidence && entry.getKey().length() > 1) { -631 product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); -632 } -633 } -634 } -635 } -636 -637 /** -638 * <p> -639 * Reads the manifest from the JAR file and collects the entries. Some -640 * vendorKey entries are:</p> -641 * <ul><li>Implementation Title</li> -642 * <li>Implementation Version</li> <li>Implementation Vendor</li> -643 * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle -644 * Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main -645 * Class</li> </ul> -646 * However, all but a handful of specific entries are read in. -647 * -648 * @param dependency A reference to the dependency -649 * @param classInformation a collection of class information -650 * @return whether evidence was identified parsing the manifest -651 * @throws IOException if there is an issue reading the JAR file -652 */ -653 protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException { -654 boolean foundSomething = false; -655 JarFile jar = null; -656 try { -657 jar = new JarFile(dependency.getActualFilePath()); -658 final Manifest manifest = jar.getManifest(); -659 if (manifest == null) { -660 if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar") -661 && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar") -662 && !dependency.getFileName().toLowerCase().endsWith("-src.jar") -663 && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) { -664 LOGGER.debug("Jar file '{}' does not contain a manifest.", -665 dependency.getFileName()); -666 } -667 return false; -668 } -669 final EvidenceCollection vendorEvidence = dependency.getVendorEvidence(); -670 final EvidenceCollection productEvidence = dependency.getProductEvidence(); -671 final EvidenceCollection versionEvidence = dependency.getVersionEvidence(); -672 String source = "Manifest"; -673 String specificationVersion = null; -674 boolean hasImplementationVersion = false; -675 Attributes atts = manifest.getMainAttributes(); -676 for (Entry<Object, Object> entry : atts.entrySet()) { -677 String key = entry.getKey().toString(); -678 String value = atts.getValue(key); -679 if (HTML_DETECTION_PATTERN.matcher(value).find()) { -680 value = Jsoup.parse(value).text(); -681 } -682 if (IGNORE_VALUES.contains(value)) { -683 continue; -684 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { -685 foundSomething = true; -686 productEvidence.addEvidence(source, key, value, Confidence.HIGH); -687 addMatchingValues(classInformation, value, productEvidence); -688 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { -689 hasImplementationVersion = true; -690 foundSomething = true; -691 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); -692 } else if ("specification-version".equalsIgnoreCase(key)) { -693 specificationVersion = value; -694 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { -695 foundSomething = true; -696 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH); -697 addMatchingValues(classInformation, value, vendorEvidence); -698 } else if (key.equalsIgnoreCase(IMPLEMENTATION_VENDOR_ID)) { -699 foundSomething = true; -700 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -701 addMatchingValues(classInformation, value, vendorEvidence); -702 } else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) { -703 foundSomething = true; -704 addDescription(dependency, value, "manifest", key); -705 addMatchingValues(classInformation, value, productEvidence); -706 } else if (key.equalsIgnoreCase(BUNDLE_NAME)) { -707 foundSomething = true; -708 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -709 addMatchingValues(classInformation, value, productEvidence); -710 // //the following caused false positives. -711 // } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) { -712 } else if (key.equalsIgnoreCase(BUNDLE_VERSION)) { -713 foundSomething = true; -714 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); -715 } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) { -716 continue; -717 //skipping main class as if this has important information to add it will be added during class name analysis... -718 } else { -719 key = key.toLowerCase(); -720 if (!IGNORE_KEYS.contains(key) -721 && !key.endsWith("jdk") -722 && !key.contains("lastmodified") -723 && !key.endsWith("package") -724 && !key.endsWith("classpath") -725 && !key.endsWith("class-path") -726 && !key.endsWith("-scm") //todo change this to a regex? -727 && !key.startsWith("scm-") -728 && !value.trim().startsWith("scm:") -729 && !isImportPackage(key, value) -730 && !isPackage(key, value)) { -731 foundSomething = true; -732 if (key.contains("version")) { -733 if (!key.contains("specification")) { -734 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -735 } -736 } else if ("build-id".equals(key)) { -737 int pos = value.indexOf('('); -738 if (pos >= 0) { -739 value = value.substring(0, pos - 1); -740 } -741 pos = value.indexOf('['); -742 if (pos >= 0) { -743 value = value.substring(0, pos - 1); -744 } -745 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -746 } else if (key.contains("title")) { -747 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -748 addMatchingValues(classInformation, value, productEvidence); -749 } else if (key.contains("vendor")) { -750 if (key.contains("specification")) { -751 vendorEvidence.addEvidence(source, key, value, Confidence.LOW); -752 } else { -753 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -754 addMatchingValues(classInformation, value, vendorEvidence); -755 } -756 } else if (key.contains("name")) { -757 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -758 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -759 addMatchingValues(classInformation, value, vendorEvidence); -760 addMatchingValues(classInformation, value, productEvidence); -761 } else if (key.contains("license")) { -762 addLicense(dependency, value); -763 } else if (key.contains("description")) { -764 addDescription(dependency, value, "manifest", key); -765 } else { -766 productEvidence.addEvidence(source, key, value, Confidence.LOW); -767 vendorEvidence.addEvidence(source, key, value, Confidence.LOW); -768 addMatchingValues(classInformation, value, vendorEvidence); -769 addMatchingValues(classInformation, value, productEvidence); -770 if (value.matches(".*\\d.*")) { -771 final StringTokenizer tokenizer = new StringTokenizer(value, " "); -772 while (tokenizer.hasMoreElements()) { -773 final String s = tokenizer.nextToken(); -774 if (s.matches("^[0-9.]+$")) { -775 versionEvidence.addEvidence(source, key, s, Confidence.LOW); -776 } -777 } -778 } -779 } -780 } -781 } -782 } -783 for (Map.Entry<String, Attributes> item : manifest.getEntries().entrySet()) { -784 final String name = item.getKey(); -785 source = "manifest: " + name; -786 atts = item.getValue(); -787 for (Entry<Object, Object> entry : atts.entrySet()) { -788 final String key = entry.getKey().toString(); -789 final String value = atts.getValue(key); -790 if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { -791 foundSomething = true; -792 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -793 addMatchingValues(classInformation, value, productEvidence); -794 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { -795 foundSomething = true; -796 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -797 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { -798 foundSomething = true; -799 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -800 addMatchingValues(classInformation, value, vendorEvidence); -801 } else if (key.equalsIgnoreCase(Attributes.Name.SPECIFICATION_TITLE.toString())) { -802 foundSomething = true; -803 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); -804 addMatchingValues(classInformation, value, productEvidence); -805 } -806 } -807 } -808 if (specificationVersion != null && !hasImplementationVersion) { -809 foundSomething = true; -810 versionEvidence.addEvidence(source, "specification-version", specificationVersion, Confidence.HIGH); -811 } -812 } finally { -813 if (jar != null) { -814 jar.close(); -815 } -816 } -817 return foundSomething; -818 } -819 -820 /** -821 * Adds a description to the given dependency. If the description contains -822 * one of the following strings beyond 100 characters, then the description -823 * used will be trimmed to that position: -824 * <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses -825 * "</li></ul> -826 * -827 * @param dependency a dependency -828 * @param description the description -829 * @param source the source of the evidence -830 * @param key the "name" of the evidence -831 * @return if the description is trimmed, the trimmed version is returned; -832 * otherwise the original description is returned -833 */ -834 public static String addDescription(Dependency dependency, String description, String source, String key) { -835 if (dependency.getDescription() == null) { -836 dependency.setDescription(description); -837 } -838 String desc; -839 if (HTML_DETECTION_PATTERN.matcher(description).find()) { -840 desc = Jsoup.parse(description).text(); -841 } else { -842 desc = description; -843 } -844 dependency.setDescription(desc); -845 if (desc.length() > 100) { -846 desc = desc.replaceAll("\\s\\s+", " "); -847 final int posSuchAs = desc.toLowerCase().indexOf("such as ", 100); -848 final int posLike = desc.toLowerCase().indexOf("like ", 100); -849 final int posWillUse = desc.toLowerCase().indexOf("will use ", 100); -850 final int posUses = desc.toLowerCase().indexOf(" uses ", 100); -851 int pos = -1; -852 pos = Math.max(pos, posSuchAs); -853 if (pos >= 0 && posLike >= 0) { -854 pos = Math.min(pos, posLike); -855 } else { -856 pos = Math.max(pos, posLike); -857 } -858 if (pos >= 0 && posWillUse >= 0) { -859 pos = Math.min(pos, posWillUse); -860 } else { -861 pos = Math.max(pos, posWillUse); -862 } -863 if (pos >= 0 && posUses >= 0) { -864 pos = Math.min(pos, posUses); -865 } else { -866 pos = Math.max(pos, posUses); -867 } -868 -869 if (pos > 0) { -870 desc = desc.substring(0, pos) + "..."; -871 } -872 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW); -873 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW); -874 } else { -875 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.MEDIUM); -876 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.MEDIUM); -877 } -878 return desc; -879 } -880 -881 /** -882 * Adds a license to the given dependency. -883 * -884 * @param d a dependency -885 * @param license the license -886 */ -887 private void addLicense(Dependency d, String license) { -888 if (d.getLicense() == null) { -889 d.setLicense(license); -890 } else if (!d.getLicense().contains(license)) { -891 d.setLicense(d.getLicense() + NEWLINE + license); -892 } -893 } -894 -895 /** -896 * The parent directory for the individual directories per archive. -897 */ -898 private File tempFileLocation = null; -899 -900 /** -901 * Initializes the JarAnalyzer. -902 * -903 * @throws InitializationException is thrown if there is an exception -904 * creating a temporary directory -905 */ -906 @Override -907 public void initializeFileTypeAnalyzer() throws InitializationException { -908 try { -909 final File baseDir = Settings.getTempDirectory(); -910 tempFileLocation = File.createTempFile("check", "tmp", baseDir); -911 if (!tempFileLocation.delete()) { -912 final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath()); -913 setEnabled(false); -914 throw new InitializationException(msg); -915 } -916 if (!tempFileLocation.mkdirs()) { -917 final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath()); -918 setEnabled(false); -919 throw new InitializationException(msg); -920 } -921 } catch (IOException ex) { -922 setEnabled(false); -923 throw new InitializationException("Unable to create a temporary file", ex); -924 } -925 } -926 -927 /** -928 * Deletes any files extracted from the JAR during analysis. -929 */ -930 @Override -931 public void close() { -932 if (tempFileLocation != null && tempFileLocation.exists()) { -933 LOGGER.debug("Attempting to delete temporary files"); -934 final boolean success = FileUtils.delete(tempFileLocation); -935 if (!success) { -936 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); -937 } -938 } -939 } -940 -941 /** -942 * Determines if the key value pair from the manifest is for an "import" -943 * type entry for package names. -944 * -945 * @param key the key from the manifest -946 * @param value the value from the manifest -947 * @return true or false depending on if it is believed the entry is an -948 * "import" entry -949 */ -950 private boolean isImportPackage(String key, String value) { -951 final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$"); -952 final boolean matches = packageRx.matcher(value).matches(); -953 return matches && (key.contains("import") || key.contains("include") || value.length() > 10); -954 } -955 -956 /** -957 * Cycles through an enumeration of JarEntries, contained within the -958 * dependency, and returns a list of the class names. This does not include -959 * core Java package names (i.e. java.* or javax.*). -960 * -961 * @param dependency the dependency being analyzed -962 * @return an list of fully qualified class names -963 */ -964 private List<ClassNameInformation> collectClassNames(Dependency dependency) { -965 final List<ClassNameInformation> classNames = new ArrayList<ClassNameInformation>(); -966 JarFile jar = null; -967 try { -968 jar = new JarFile(dependency.getActualFilePath()); -969 final Enumeration<JarEntry> entries = jar.entries(); -970 while (entries.hasMoreElements()) { -971 final JarEntry entry = entries.nextElement(); -972 final String name = entry.getName().toLowerCase(); -973 //no longer stripping "|com\\.sun" - there are some com.sun jar files with CVEs. -974 if (name.endsWith(".class") && !name.matches("^javax?\\..*$")) { -975 final ClassNameInformation className = new ClassNameInformation(name.substring(0, name.length() - 6)); -976 classNames.add(className); -977 } -978 } -979 } catch (IOException ex) { -980 LOGGER.warn("Unable to open jar file '{}'.", dependency.getFileName()); -981 LOGGER.debug("", ex); -982 } finally { -983 if (jar != null) { -984 try { -985 jar.close(); -986 } catch (IOException ex) { -987 LOGGER.trace("", ex); -988 } -989 } -990 } -991 return classNames; -992 } -993 -994 /** -995 * Cycles through the list of class names and places the package levels 0-3 -996 * into the provided maps for vendor and product. This is helpful when -997 * analyzing vendor/product as many times this is included in the package -998 * name. -999 * -1000 * @param classNames a list of class names -1001 * @param vendor HashMap of possible vendor names from package names (e.g. -1002 * owasp) -1003 * @param product HashMap of possible product names from package names (e.g. -1004 * dependencycheck) -1005 */ -1006 private void analyzeFullyQualifiedClassNames(List<ClassNameInformation> classNames, -1007 Map<String, Integer> vendor, Map<String, Integer> product) { -1008 for (ClassNameInformation entry : classNames) { -1009 final List<String> list = entry.getPackageStructure(); -1010 addEntry(vendor, list.get(0)); -1011 -1012 if (list.size() == 2) { -1013 addEntry(product, list.get(1)); -1014 } -1015 if (list.size() == 3) { -1016 addEntry(vendor, list.get(1)); -1017 addEntry(product, list.get(1)); -1018 addEntry(product, list.get(2)); -1019 } -1020 if (list.size() >= 4) { -1021 addEntry(vendor, list.get(1)); -1022 addEntry(vendor, list.get(2)); -1023 addEntry(product, list.get(1)); -1024 addEntry(product, list.get(2)); -1025 addEntry(product, list.get(3)); -1026 } -1027 } -1028 } -1029 -1030 /** -1031 * Adds an entry to the specified collection and sets the Integer (e.g. the -1032 * count) to 1. If the entry already exists in the collection then the -1033 * Integer is incremented by 1. -1034 * -1035 * @param collection a collection of strings and their occurrence count -1036 * @param key the key to add to the collection -1037 */ -1038 private void addEntry(Map<String, Integer> collection, String key) { -1039 if (collection.containsKey(key)) { -1040 collection.put(key, collection.get(key) + 1); -1041 } else { -1042 collection.put(key, 1); -1043 } -1044 } -1045 -1046 /** -1047 * Cycles through the collection of class name information to see if parts -1048 * of the package names are contained in the provided value. If found, it -1049 * will be added as the HIGHEST confidence evidence because we have more -1050 * then one source corroborating the value. -1051 * -1052 * @param classes a collection of class name information -1053 * @param value the value to check to see if it contains a package name -1054 * @param evidence the evidence collection to add new entries too -1055 */ -1056 private static void addMatchingValues(List<ClassNameInformation> classes, String value, EvidenceCollection evidence) { -1057 if (value == null || value.isEmpty() || classes == null || classes.isEmpty()) { -1058 return; -1059 } -1060 final String text = value.toLowerCase(); -1061 for (ClassNameInformation cni : classes) { -1062 for (String key : cni.getPackageStructure()) { -1063 final Pattern p = Pattern.compile("\b" + key + "\b"); -1064 if (p.matcher(text).find()) { -1065 //if (text.contains(key)) { //note, package structure elements are already lowercase. -1066 evidence.addEvidence("jar", "package name", key, Confidence.HIGHEST); -1067 } -1068 } -1069 } -1070 } -1071 -1072 /** -1073 * Simple check to see if the attribute from a manifest is just a package -1074 * name. -1075 * -1076 * @param key the key of the value to check -1077 * @param value the value to check -1078 * @return true if the value looks like a java package name, otherwise false -1079 */ -1080 private boolean isPackage(String key, String value) { -1081 -1082 return !key.matches(".*(version|title|vendor|name|license|description).*") -1083 && value.matches("^([a-zA-Z_][a-zA-Z0-9_\\$]*(\\.[a-zA-Z_][a-zA-Z0-9_\\$]*)*)?$"); -1084 -1085 } +321 } else { +322 if (externalPom == null) { +323 pom = PomUtils.readPom(path, jar); +324 } else { +325 pom = PomUtils.readPom(externalPom); +326 } +327 if (pom != null) { +328 pom.processProperties(pomProperties); +329 foundSomething |= setPomEvidence(dependency, pom, classes); +330 } +331 } +332 } catch (AnalysisException ex) { +333 LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath()); +334 LOGGER.trace("", ex); +335 } +336 } +337 return foundSomething; +338 } +339 +340 /** +341 * Given a path to a pom.xml within a JarFile, this method attempts to load +342 * a sibling pom.properties if one exists. +343 * +344 * @param path the path to the pom.xml within the JarFile +345 * @param jar the JarFile to load the pom.properties from +346 * @return a Properties object or null if no pom.properties was found +347 * @throws IOException thrown if there is an exception reading the +348 * pom.properties +349 */ +350 private Properties retrievePomProperties(String path, final JarFile jar) throws IOException { +351 Properties pomProperties = null; +352 final String propPath = path.substring(0, path.length() - 7) + "pom.properies"; +353 final ZipEntry propEntry = jar.getEntry(propPath); +354 if (propEntry != null) { +355 Reader reader = null; +356 try { +357 reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8"); +358 pomProperties = new Properties(); +359 pomProperties.load(reader); +360 LOGGER.debug("Read pom.properties: {}", propPath); +361 } finally { +362 if (reader != null) { +363 try { +364 reader.close(); +365 } catch (IOException ex) { +366 LOGGER.trace("close error", ex); +367 } +368 } +369 } +370 } +371 return pomProperties; +372 } +373 +374 /** +375 * Searches a JarFile for pom.xml entries and returns a listing of these +376 * entries. +377 * +378 * @param jar the JarFile to search +379 * @return a list of pom.xml entries +380 * @throws IOException thrown if there is an exception reading a JarEntry +381 */ +382 private List<String> retrievePomListing(final JarFile jar) throws IOException { +383 final List<String> pomEntries = new ArrayList<String>(); +384 final Enumeration<JarEntry> entries = jar.entries(); +385 while (entries.hasMoreElements()) { +386 final JarEntry entry = entries.nextElement(); +387 final String entryName = (new File(entry.getName())).getName().toLowerCase(); +388 if (!entry.isDirectory() && "pom.xml".equals(entryName)) { +389 LOGGER.trace("POM Entry found: {}", entry.getName()); +390 pomEntries.add(entry.getName()); +391 } +392 } +393 return pomEntries; +394 } +395 +396 /** +397 * Retrieves the specified POM from a jar file and converts it to a Model. +398 * +399 * @param path the path to the pom.xml file within the jar file +400 * @param jar the jar file to extract the pom from +401 * @param dependency the dependency being analyzed +402 * @return returns the POM object +403 * @throws AnalysisException is thrown if there is an exception extracting +404 * or parsing the POM {@link org.owasp.dependencycheck.xml.pom.Model} object +405 */ +406 private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException { +407 InputStream input = null; +408 FileOutputStream fos = null; +409 final File tmpDir = getNextTempDirectory(); +410 final File file = new File(tmpDir, "pom.xml"); +411 try { +412 final ZipEntry entry = jar.getEntry(path); +413 if (entry == null) { +414 throw new AnalysisException(String.format("Pom (%s)does not exist in %s", path, jar.getName())); +415 } +416 input = jar.getInputStream(entry); +417 fos = new FileOutputStream(file); +418 IOUtils.copy(input, fos); +419 dependency.setActualFilePath(file.getAbsolutePath()); +420 } catch (IOException ex) { +421 LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath()); +422 LOGGER.error("", ex); +423 } finally { +424 closeStream(fos); +425 closeStream(input); +426 } +427 return PomUtils.readPom(file); +428 } +429 +430 /** +431 * Silently closes an input stream ignoring errors. +432 * +433 * @param stream an input stream to close +434 */ +435 private void closeStream(InputStream stream) { +436 if (stream != null) { +437 try { +438 stream.close(); +439 } catch (IOException ex) { +440 LOGGER.trace("", ex); +441 } +442 } +443 } +444 +445 /** +446 * Silently closes an output stream ignoring errors. +447 * +448 * @param stream an output stream to close +449 */ +450 private void closeStream(OutputStream stream) { +451 if (stream != null) { +452 try { +453 stream.close(); +454 } catch (IOException ex) { +455 LOGGER.trace("", ex); +456 } +457 } +458 } +459 +460 /** +461 * Sets evidence from the pom on the supplied dependency. +462 * +463 * @param dependency the dependency to set data on +464 * @param pom the information from the pom +465 * @param classes a collection of ClassNameInformation - containing data +466 * about the fully qualified class names within the JAR file being analyzed +467 * @return true if there was evidence within the pom that we could use; +468 * otherwise false +469 */ +470 public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) { +471 boolean foundSomething = false; +472 boolean addAsIdentifier = true; +473 if (pom == null) { +474 return foundSomething; +475 } +476 String groupid = pom.getGroupId(); +477 String parentGroupId = pom.getParentGroupId(); +478 String artifactid = pom.getArtifactId(); +479 String parentArtifactId = pom.getParentArtifactId(); +480 String version = pom.getVersion(); +481 String parentVersion = pom.getParentVersion(); +482 +483 if ("org.sonatype.oss".equals(parentGroupId) && "oss-parent".equals(parentArtifactId)) { +484 parentGroupId = null; +485 parentArtifactId = null; +486 parentVersion = null; +487 } +488 +489 if ((groupid == null || groupid.isEmpty()) && parentGroupId != null && !parentGroupId.isEmpty()) { +490 groupid = parentGroupId; +491 } +492 +493 final String originalGroupID = groupid; +494 if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) { +495 groupid = groupid.substring(4); +496 } +497 +498 if ((artifactid == null || artifactid.isEmpty()) && parentArtifactId != null && !parentArtifactId.isEmpty()) { +499 artifactid = parentArtifactId; +500 } +501 +502 final String originalArtifactID = artifactid; +503 if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) { +504 artifactid = artifactid.substring(4); +505 } +506 +507 if ((version == null || version.isEmpty()) && parentVersion != null && !parentVersion.isEmpty()) { +508 version = parentVersion; +509 } +510 +511 if (groupid != null && !groupid.isEmpty()) { +512 foundSomething = true; +513 dependency.getVendorEvidence().addEvidence("pom", "groupid", groupid, Confidence.HIGHEST); +514 dependency.getProductEvidence().addEvidence("pom", "groupid", groupid, Confidence.LOW); +515 addMatchingValues(classes, groupid, dependency.getVendorEvidence()); +516 addMatchingValues(classes, groupid, dependency.getProductEvidence()); +517 if (parentGroupId != null && !parentGroupId.isEmpty() && !parentGroupId.equals(groupid)) { +518 dependency.getVendorEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.MEDIUM); +519 dependency.getProductEvidence().addEvidence("pom", "parent-groupid", parentGroupId, Confidence.LOW); +520 addMatchingValues(classes, parentGroupId, dependency.getVendorEvidence()); +521 addMatchingValues(classes, parentGroupId, dependency.getProductEvidence()); +522 } +523 } else { +524 addAsIdentifier = false; +525 } +526 +527 if (artifactid != null && !artifactid.isEmpty()) { +528 foundSomething = true; +529 dependency.getProductEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.HIGHEST); +530 dependency.getVendorEvidence().addEvidence("pom", "artifactid", artifactid, Confidence.LOW); +531 addMatchingValues(classes, artifactid, dependency.getVendorEvidence()); +532 addMatchingValues(classes, artifactid, dependency.getProductEvidence()); +533 if (parentArtifactId != null && !parentArtifactId.isEmpty() && !parentArtifactId.equals(artifactid)) { +534 dependency.getProductEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.MEDIUM); +535 dependency.getVendorEvidence().addEvidence("pom", "parent-artifactid", parentArtifactId, Confidence.LOW); +536 addMatchingValues(classes, parentArtifactId, dependency.getVendorEvidence()); +537 addMatchingValues(classes, parentArtifactId, dependency.getProductEvidence()); +538 } +539 } else { +540 addAsIdentifier = false; +541 } +542 +543 if (version != null && !version.isEmpty()) { +544 foundSomething = true; +545 dependency.getVersionEvidence().addEvidence("pom", "version", version, Confidence.HIGHEST); +546 if (parentVersion != null && !parentVersion.isEmpty() && !parentVersion.equals(version)) { +547 dependency.getVersionEvidence().addEvidence("pom", "parent-version", version, Confidence.LOW); +548 } +549 } else { +550 addAsIdentifier = false; +551 } +552 +553 if (addAsIdentifier) { +554 dependency.addIdentifier("maven", String.format("%s:%s:%s", originalGroupID, originalArtifactID, version), null, Confidence.HIGH); +555 } +556 +557 // org name +558 final String org = pom.getOrganization(); +559 if (org != null && !org.isEmpty()) { +560 dependency.getVendorEvidence().addEvidence("pom", "organization name", org, Confidence.HIGH); +561 dependency.getProductEvidence().addEvidence("pom", "organization name", org, Confidence.LOW); +562 addMatchingValues(classes, org, dependency.getVendorEvidence()); +563 addMatchingValues(classes, org, dependency.getProductEvidence()); +564 } +565 //pom name +566 final String pomName = pom.getName(); +567 if (pomName +568 != null && !pomName.isEmpty()) { +569 foundSomething = true; +570 dependency.getProductEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); +571 dependency.getVendorEvidence().addEvidence("pom", "name", pomName, Confidence.HIGH); +572 addMatchingValues(classes, pomName, dependency.getVendorEvidence()); +573 addMatchingValues(classes, pomName, dependency.getProductEvidence()); +574 } +575 +576 //Description +577 final String description = pom.getDescription(); +578 if (description != null && !description.isEmpty() && !description.startsWith("POM was created by")) { +579 foundSomething = true; +580 final String trimmedDescription = addDescription(dependency, description, "pom", "description"); +581 addMatchingValues(classes, trimmedDescription, dependency.getVendorEvidence()); +582 addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence()); +583 } +584 +585 final String projectURL = pom.getProjectURL(); +586 if (projectURL != null && !projectURL.trim().isEmpty()) { +587 dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST); +588 } +589 +590 extractLicense(pom, dependency); +591 return foundSomething; +592 } +593 +594 /** +595 * Analyzes the path information of the classes contained within the +596 * JarAnalyzer to try and determine possible vendor or product names. If any +597 * are found they are stored in the packageVendor and packageProduct +598 * hashSets. +599 * +600 * @param classNames a list of class names +601 * @param dependency a dependency to analyze +602 * @param addPackagesAsEvidence a flag indicating whether or not package +603 * names should be added as evidence. +604 */ +605 protected void analyzePackageNames(List<ClassNameInformation> classNames, +606 Dependency dependency, boolean addPackagesAsEvidence) { +607 final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>(); +608 final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>(); +609 analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers); +610 +611 final int classCount = classNames.size(); +612 final EvidenceCollection vendor = dependency.getVendorEvidence(); +613 final EvidenceCollection product = dependency.getProductEvidence(); +614 +615 for (Map.Entry<String, Integer> entry : vendorIdentifiers.entrySet()) { +616 final float ratio = entry.getValue() / (float) classCount; +617 if (ratio > 0.5) { +618 //TODO remove weighting +619 vendor.addWeighting(entry.getKey()); +620 if (addPackagesAsEvidence && entry.getKey().length() > 1) { +621 vendor.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); +622 } +623 } +624 } +625 for (Map.Entry<String, Integer> entry : productIdentifiers.entrySet()) { +626 final float ratio = entry.getValue() / (float) classCount; +627 if (ratio > 0.5) { +628 product.addWeighting(entry.getKey()); +629 if (addPackagesAsEvidence && entry.getKey().length() > 1) { +630 product.addEvidence("jar", "package name", entry.getKey(), Confidence.LOW); +631 } +632 } +633 } +634 } +635 +636 /** +637 * <p> +638 * Reads the manifest from the JAR file and collects the entries. Some +639 * vendorKey entries are:</p> +640 * <ul><li>Implementation Title</li> +641 * <li>Implementation Version</li> <li>Implementation Vendor</li> +642 * <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle +643 * Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main +644 * Class</li> </ul> +645 * However, all but a handful of specific entries are read in. +646 * +647 * @param dependency A reference to the dependency +648 * @param classInformation a collection of class information +649 * @return whether evidence was identified parsing the manifest +650 * @throws IOException if there is an issue reading the JAR file +651 */ +652 protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException { +653 boolean foundSomething = false; +654 JarFile jar = null; +655 try { +656 jar = new JarFile(dependency.getActualFilePath()); +657 final Manifest manifest = jar.getManifest(); +658 if (manifest == null) { +659 if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar") +660 && !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar") +661 && !dependency.getFileName().toLowerCase().endsWith("-src.jar") +662 && !dependency.getFileName().toLowerCase().endsWith("-doc.jar")) { +663 LOGGER.debug("Jar file '{}' does not contain a manifest.", +664 dependency.getFileName()); +665 } +666 return false; +667 } +668 final EvidenceCollection vendorEvidence = dependency.getVendorEvidence(); +669 final EvidenceCollection productEvidence = dependency.getProductEvidence(); +670 final EvidenceCollection versionEvidence = dependency.getVersionEvidence(); +671 String source = "Manifest"; +672 String specificationVersion = null; +673 boolean hasImplementationVersion = false; +674 Attributes atts = manifest.getMainAttributes(); +675 for (Entry<Object, Object> entry : atts.entrySet()) { +676 String key = entry.getKey().toString(); +677 String value = atts.getValue(key); +678 if (HTML_DETECTION_PATTERN.matcher(value).find()) { +679 value = Jsoup.parse(value).text(); +680 } +681 if (IGNORE_VALUES.contains(value)) { +682 continue; +683 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { +684 foundSomething = true; +685 productEvidence.addEvidence(source, key, value, Confidence.HIGH); +686 addMatchingValues(classInformation, value, productEvidence); +687 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { +688 hasImplementationVersion = true; +689 foundSomething = true; +690 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); +691 } else if ("specification-version".equalsIgnoreCase(key)) { +692 specificationVersion = value; +693 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { +694 foundSomething = true; +695 vendorEvidence.addEvidence(source, key, value, Confidence.HIGH); +696 addMatchingValues(classInformation, value, vendorEvidence); +697 } else if (key.equalsIgnoreCase(IMPLEMENTATION_VENDOR_ID)) { +698 foundSomething = true; +699 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +700 addMatchingValues(classInformation, value, vendorEvidence); +701 } else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) { +702 foundSomething = true; +703 addDescription(dependency, value, "manifest", key); +704 addMatchingValues(classInformation, value, productEvidence); +705 } else if (key.equalsIgnoreCase(BUNDLE_NAME)) { +706 foundSomething = true; +707 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +708 addMatchingValues(classInformation, value, productEvidence); +709 // //the following caused false positives. +710 // } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) { +711 } else if (key.equalsIgnoreCase(BUNDLE_VERSION)) { +712 foundSomething = true; +713 versionEvidence.addEvidence(source, key, value, Confidence.HIGH); +714 } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) { +715 continue; +716 //skipping main class as if this has important information to add it will be added during class name analysis... +717 } else { +718 key = key.toLowerCase(); +719 if (!IGNORE_KEYS.contains(key) +720 && !key.endsWith("jdk") +721 && !key.contains("lastmodified") +722 && !key.endsWith("package") +723 && !key.endsWith("classpath") +724 && !key.endsWith("class-path") +725 && !key.endsWith("-scm") //todo change this to a regex? +726 && !key.startsWith("scm-") +727 && !value.trim().startsWith("scm:") +728 && !isImportPackage(key, value) +729 && !isPackage(key, value)) { +730 foundSomething = true; +731 if (key.contains("version")) { +732 if (!key.contains("specification")) { +733 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +734 } +735 } else if ("build-id".equals(key)) { +736 int pos = value.indexOf('('); +737 if (pos >= 0) { +738 value = value.substring(0, pos - 1); +739 } +740 pos = value.indexOf('['); +741 if (pos >= 0) { +742 value = value.substring(0, pos - 1); +743 } +744 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +745 } else if (key.contains("title")) { +746 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +747 addMatchingValues(classInformation, value, productEvidence); +748 } else if (key.contains("vendor")) { +749 if (key.contains("specification")) { +750 vendorEvidence.addEvidence(source, key, value, Confidence.LOW); +751 } else { +752 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +753 addMatchingValues(classInformation, value, vendorEvidence); +754 } +755 } else if (key.contains("name")) { +756 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +757 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +758 addMatchingValues(classInformation, value, vendorEvidence); +759 addMatchingValues(classInformation, value, productEvidence); +760 } else if (key.contains("license")) { +761 addLicense(dependency, value); +762 } else if (key.contains("description")) { +763 addDescription(dependency, value, "manifest", key); +764 } else { +765 productEvidence.addEvidence(source, key, value, Confidence.LOW); +766 vendorEvidence.addEvidence(source, key, value, Confidence.LOW); +767 addMatchingValues(classInformation, value, vendorEvidence); +768 addMatchingValues(classInformation, value, productEvidence); +769 if (value.matches(".*\\d.*")) { +770 final StringTokenizer tokenizer = new StringTokenizer(value, " "); +771 while (tokenizer.hasMoreElements()) { +772 final String s = tokenizer.nextToken(); +773 if (s.matches("^[0-9.]+$")) { +774 versionEvidence.addEvidence(source, key, s, Confidence.LOW); +775 } +776 } +777 } +778 } +779 } +780 } +781 } +782 for (Map.Entry<String, Attributes> item : manifest.getEntries().entrySet()) { +783 final String name = item.getKey(); +784 source = "manifest: " + name; +785 atts = item.getValue(); +786 for (Entry<Object, Object> entry : atts.entrySet()) { +787 final String key = entry.getKey().toString(); +788 final String value = atts.getValue(key); +789 if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { +790 foundSomething = true; +791 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +792 addMatchingValues(classInformation, value, productEvidence); +793 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) { +794 foundSomething = true; +795 versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +796 } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) { +797 foundSomething = true; +798 vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +799 addMatchingValues(classInformation, value, vendorEvidence); +800 } else if (key.equalsIgnoreCase(Attributes.Name.SPECIFICATION_TITLE.toString())) { +801 foundSomething = true; +802 productEvidence.addEvidence(source, key, value, Confidence.MEDIUM); +803 addMatchingValues(classInformation, value, productEvidence); +804 } +805 } +806 } +807 if (specificationVersion != null && !hasImplementationVersion) { +808 foundSomething = true; +809 versionEvidence.addEvidence(source, "specification-version", specificationVersion, Confidence.HIGH); +810 } +811 } finally { +812 if (jar != null) { +813 jar.close(); +814 } +815 } +816 return foundSomething; +817 } +818 +819 /** +820 * Adds a description to the given dependency. If the description contains +821 * one of the following strings beyond 100 characters, then the description +822 * used will be trimmed to that position: +823 * <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses +824 * "</li></ul> +825 * +826 * @param dependency a dependency +827 * @param description the description +828 * @param source the source of the evidence +829 * @param key the "name" of the evidence +830 * @return if the description is trimmed, the trimmed version is returned; +831 * otherwise the original description is returned +832 */ +833 public static String addDescription(Dependency dependency, String description, String source, String key) { +834 if (dependency.getDescription() == null) { +835 dependency.setDescription(description); +836 } +837 String desc; +838 if (HTML_DETECTION_PATTERN.matcher(description).find()) { +839 desc = Jsoup.parse(description).text(); +840 } else { +841 desc = description; +842 } +843 dependency.setDescription(desc); +844 if (desc.length() > 100) { +845 desc = desc.replaceAll("\\s\\s+", " "); +846 final int posSuchAs = desc.toLowerCase().indexOf("such as ", 100); +847 final int posLike = desc.toLowerCase().indexOf("like ", 100); +848 final int posWillUse = desc.toLowerCase().indexOf("will use ", 100); +849 final int posUses = desc.toLowerCase().indexOf(" uses ", 100); +850 int pos = -1; +851 pos = Math.max(pos, posSuchAs); +852 if (pos >= 0 && posLike >= 0) { +853 pos = Math.min(pos, posLike); +854 } else { +855 pos = Math.max(pos, posLike); +856 } +857 if (pos >= 0 && posWillUse >= 0) { +858 pos = Math.min(pos, posWillUse); +859 } else { +860 pos = Math.max(pos, posWillUse); +861 } +862 if (pos >= 0 && posUses >= 0) { +863 pos = Math.min(pos, posUses); +864 } else { +865 pos = Math.max(pos, posUses); +866 } +867 +868 if (pos > 0) { +869 desc = desc.substring(0, pos) + "..."; +870 } +871 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW); +872 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW); +873 } else { +874 dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.MEDIUM); +875 dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.MEDIUM); +876 } +877 return desc; +878 } +879 +880 /** +881 * Adds a license to the given dependency. +882 * +883 * @param d a dependency +884 * @param license the license +885 */ +886 private void addLicense(Dependency d, String license) { +887 if (d.getLicense() == null) { +888 d.setLicense(license); +889 } else if (!d.getLicense().contains(license)) { +890 d.setLicense(d.getLicense() + NEWLINE + license); +891 } +892 } +893 +894 /** +895 * The parent directory for the individual directories per archive. +896 */ +897 private File tempFileLocation = null; +898 +899 /** +900 * Initializes the JarAnalyzer. +901 * +902 * @throws InitializationException is thrown if there is an exception +903 * creating a temporary directory +904 */ +905 @Override +906 public void initializeFileTypeAnalyzer() throws InitializationException { +907 try { +908 final File baseDir = Settings.getTempDirectory(); +909 tempFileLocation = File.createTempFile("check", "tmp", baseDir); +910 if (!tempFileLocation.delete()) { +911 final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath()); +912 setEnabled(false); +913 throw new InitializationException(msg); +914 } +915 if (!tempFileLocation.mkdirs()) { +916 final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath()); +917 setEnabled(false); +918 throw new InitializationException(msg); +919 } +920 } catch (IOException ex) { +921 setEnabled(false); +922 throw new InitializationException("Unable to create a temporary file", ex); +923 } +924 } +925 +926 /** +927 * Deletes any files extracted from the JAR during analysis. +928 */ +929 @Override +930 public void close() { +931 if (tempFileLocation != null && tempFileLocation.exists()) { +932 LOGGER.debug("Attempting to delete temporary files"); +933 final boolean success = FileUtils.delete(tempFileLocation); +934 if (!success && tempFileLocation.exists()) { +935 final String[] l = tempFileLocation.list(); +936 if (l != null && l.length > 0) { +937 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); +938 } +939 } +940 } +941 } +942 +943 /** +944 * Determines if the key value pair from the manifest is for an "import" +945 * type entry for package names. +946 * +947 * @param key the key from the manifest +948 * @param value the value from the manifest +949 * @return true or false depending on if it is believed the entry is an +950 * "import" entry +951 */ +952 private boolean isImportPackage(String key, String value) { +953 final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$"); +954 final boolean matches = packageRx.matcher(value).matches(); +955 return matches && (key.contains("import") || key.contains("include") || value.length() > 10); +956 } +957 +958 /** +959 * Cycles through an enumeration of JarEntries, contained within the +960 * dependency, and returns a list of the class names. This does not include +961 * core Java package names (i.e. java.* or javax.*). +962 * +963 * @param dependency the dependency being analyzed +964 * @return an list of fully qualified class names +965 */ +966 private List<ClassNameInformation> collectClassNames(Dependency dependency) { +967 final List<ClassNameInformation> classNames = new ArrayList<ClassNameInformation>(); +968 JarFile jar = null; +969 try { +970 jar = new JarFile(dependency.getActualFilePath()); +971 final Enumeration<JarEntry> entries = jar.entries(); +972 while (entries.hasMoreElements()) { +973 final JarEntry entry = entries.nextElement(); +974 final String name = entry.getName().toLowerCase(); +975 //no longer stripping "|com\\.sun" - there are some com.sun jar files with CVEs. +976 if (name.endsWith(".class") && !name.matches("^javax?\\..*$")) { +977 final ClassNameInformation className = new ClassNameInformation(name.substring(0, name.length() - 6)); +978 classNames.add(className); +979 } +980 } +981 } catch (IOException ex) { +982 LOGGER.warn("Unable to open jar file '{}'.", dependency.getFileName()); +983 LOGGER.debug("", ex); +984 } finally { +985 if (jar != null) { +986 try { +987 jar.close(); +988 } catch (IOException ex) { +989 LOGGER.trace("", ex); +990 } +991 } +992 } +993 return classNames; +994 } +995 +996 /** +997 * Cycles through the list of class names and places the package levels 0-3 +998 * into the provided maps for vendor and product. This is helpful when +999 * analyzing vendor/product as many times this is included in the package +1000 * name. +1001 * +1002 * @param classNames a list of class names +1003 * @param vendor HashMap of possible vendor names from package names (e.g. +1004 * owasp) +1005 * @param product HashMap of possible product names from package names (e.g. +1006 * dependencycheck) +1007 */ +1008 private void analyzeFullyQualifiedClassNames(List<ClassNameInformation> classNames, +1009 Map<String, Integer> vendor, Map<String, Integer> product) { +1010 for (ClassNameInformation entry : classNames) { +1011 final List<String> list = entry.getPackageStructure(); +1012 addEntry(vendor, list.get(0)); +1013 +1014 if (list.size() == 2) { +1015 addEntry(product, list.get(1)); +1016 } +1017 if (list.size() == 3) { +1018 addEntry(vendor, list.get(1)); +1019 addEntry(product, list.get(1)); +1020 addEntry(product, list.get(2)); +1021 } +1022 if (list.size() >= 4) { +1023 addEntry(vendor, list.get(1)); +1024 addEntry(vendor, list.get(2)); +1025 addEntry(product, list.get(1)); +1026 addEntry(product, list.get(2)); +1027 addEntry(product, list.get(3)); +1028 } +1029 } +1030 } +1031 +1032 /** +1033 * Adds an entry to the specified collection and sets the Integer (e.g. the +1034 * count) to 1. If the entry already exists in the collection then the +1035 * Integer is incremented by 1. +1036 * +1037 * @param collection a collection of strings and their occurrence count +1038 * @param key the key to add to the collection +1039 */ +1040 private void addEntry(Map<String, Integer> collection, String key) { +1041 if (collection.containsKey(key)) { +1042 collection.put(key, collection.get(key) + 1); +1043 } else { +1044 collection.put(key, 1); +1045 } +1046 } +1047 +1048 /** +1049 * Cycles through the collection of class name information to see if parts +1050 * of the package names are contained in the provided value. If found, it +1051 * will be added as the HIGHEST confidence evidence because we have more +1052 * then one source corroborating the value. +1053 * +1054 * @param classes a collection of class name information +1055 * @param value the value to check to see if it contains a package name +1056 * @param evidence the evidence collection to add new entries too +1057 */ +1058 private static void addMatchingValues(List<ClassNameInformation> classes, String value, EvidenceCollection evidence) { +1059 if (value == null || value.isEmpty() || classes == null || classes.isEmpty()) { +1060 return; +1061 } +1062 final String text = value.toLowerCase(); +1063 for (ClassNameInformation cni : classes) { +1064 for (String key : cni.getPackageStructure()) { +1065 final Pattern p = Pattern.compile("\b" + key + "\b"); +1066 if (p.matcher(text).find()) { +1067 //if (text.contains(key)) { //note, package structure elements are already lowercase. +1068 evidence.addEvidence("jar", "package name", key, Confidence.HIGHEST); +1069 } +1070 } +1071 } +1072 } +1073 +1074 /** +1075 * Simple check to see if the attribute from a manifest is just a package +1076 * name. +1077 * +1078 * @param key the key of the value to check +1079 * @param value the value to check +1080 * @return true if the value looks like a java package name, otherwise false +1081 */ +1082 private boolean isPackage(String key, String value) { +1083 +1084 return !key.matches(".*(version|title|vendor|name|license|description).*") +1085 && value.matches("^([a-zA-Z_][a-zA-Z0-9_\\$]*(\\.[a-zA-Z_][a-zA-Z0-9_\\$]*)*)?$"); 1086 -1087 /** -1088 * Extracts the license information from the pom and adds it to the -1089 * dependency. -1090 * -1091 * @param pom the pom object -1092 * @param dependency the dependency to add license information too -1093 */ -1094 public static void extractLicense(Model pom, Dependency dependency) { -1095 //license -1096 if (pom.getLicenses() != null) { -1097 String license = null; -1098 for (License lic : pom.getLicenses()) { -1099 String tmp = null; -1100 if (lic.getName() != null) { -1101 tmp = lic.getName(); -1102 } -1103 if (lic.getUrl() != null) { -1104 if (tmp == null) { -1105 tmp = lic.getUrl(); -1106 } else { -1107 tmp += ": " + lic.getUrl(); -1108 } -1109 } -1110 if (tmp == null) { -1111 continue; -1112 } -1113 if (HTML_DETECTION_PATTERN.matcher(tmp).find()) { -1114 tmp = Jsoup.parse(tmp).text(); -1115 } -1116 if (license == null) { -1117 license = tmp; -1118 } else { -1119 license += "\n" + tmp; -1120 } -1121 } -1122 if (license != null) { -1123 dependency.setLicense(license); -1124 -1125 } -1126 } -1127 } -1128 -1129 /** -1130 * Stores information about a class name. -1131 */ -1132 protected static class ClassNameInformation { -1133 -1134 /** -1135 * <p> -1136 * Stores information about a given class name. This class will keep the -1137 * fully qualified class name and a list of the important parts of the -1138 * package structure. Up to the first four levels of the package -1139 * structure are stored, excluding a leading "org" or "com". -1140 * Example:</p> -1141 * <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer"); -1142 * System.out.println(obj.getName()); -1143 * for (String p : obj.getPackageStructure()) -1144 * System.out.println(p); -1145 * </code> -1146 * <p> -1147 * Would result in:</p> -1148 * <code>org.owasp.dependencycheck.analyzer.JarAnalyzer -1149 * owasp -1150 * dependencycheck -1151 * analyzer -1152 * jaranalyzer</code> -1153 * -1154 * @param className a fully qualified class name -1155 */ -1156 ClassNameInformation(String className) { -1157 name = className; -1158 if (name.contains("/")) { -1159 final String[] tmp = className.toLowerCase().split("/"); -1160 int start = 0; -1161 int end = 3; -1162 if ("com".equals(tmp[0]) || "org".equals(tmp[0])) { -1163 start = 1; -1164 end = 4; -1165 } -1166 if (tmp.length <= end) { -1167 end = tmp.length - 1; -1168 } -1169 for (int i = start; i <= end; i++) { -1170 packageStructure.add(tmp[i]); -1171 } -1172 } else { -1173 packageStructure.add(name); -1174 } -1175 } -1176 /** -1177 * The fully qualified class name. -1178 */ -1179 private String name; -1180 -1181 /** -1182 * Get the value of name -1183 * -1184 * @return the value of name -1185 */ -1186 public String getName() { -1187 return name; -1188 } -1189 -1190 /** -1191 * Set the value of name -1192 * -1193 * @param name new value of name -1194 */ -1195 public void setName(String name) { -1196 this.name = name; -1197 } -1198 /** -1199 * Up to the first four levels of the package structure, excluding a -1200 * leading "org" or "com". -1201 */ -1202 private final ArrayList<String> packageStructure = new ArrayList<String>(); -1203 -1204 /** -1205 * Get the value of packageStructure -1206 * -1207 * @return the value of packageStructure -1208 */ -1209 public ArrayList<String> getPackageStructure() { -1210 return packageStructure; -1211 } -1212 } -1213 -1214 /** -1215 * Retrieves the next temporary directory to extract an archive too. -1216 * -1217 * @return a directory -1218 * @throws AnalysisException thrown if unable to create temporary directory -1219 */ -1220 private File getNextTempDirectory() throws AnalysisException { -1221 dirCount += 1; -1222 final File directory = new File(tempFileLocation, String.valueOf(dirCount)); -1223 //getting an exception for some directories not being able to be created; might be because the directory already exists? -1224 if (directory.exists()) { -1225 return getNextTempDirectory(); -1226 } -1227 if (!directory.mkdirs()) { -1228 final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath()); -1229 throw new AnalysisException(msg); -1230 } -1231 return directory; -1232 } -1233 } +1087 } +1088 +1089 /** +1090 * Extracts the license information from the pom and adds it to the +1091 * dependency. +1092 * +1093 * @param pom the pom object +1094 * @param dependency the dependency to add license information too +1095 */ +1096 public static void extractLicense(Model pom, Dependency dependency) { +1097 //license +1098 if (pom.getLicenses() != null) { +1099 String license = null; +1100 for (License lic : pom.getLicenses()) { +1101 String tmp = null; +1102 if (lic.getName() != null) { +1103 tmp = lic.getName(); +1104 } +1105 if (lic.getUrl() != null) { +1106 if (tmp == null) { +1107 tmp = lic.getUrl(); +1108 } else { +1109 tmp += ": " + lic.getUrl(); +1110 } +1111 } +1112 if (tmp == null) { +1113 continue; +1114 } +1115 if (HTML_DETECTION_PATTERN.matcher(tmp).find()) { +1116 tmp = Jsoup.parse(tmp).text(); +1117 } +1118 if (license == null) { +1119 license = tmp; +1120 } else { +1121 license += "\n" + tmp; +1122 } +1123 } +1124 if (license != null) { +1125 dependency.setLicense(license); +1126 +1127 } +1128 } +1129 } +1130 +1131 /** +1132 * Stores information about a class name. +1133 */ +1134 protected static class ClassNameInformation { +1135 +1136 /** +1137 * <p> +1138 * Stores information about a given class name. This class will keep the +1139 * fully qualified class name and a list of the important parts of the +1140 * package structure. Up to the first four levels of the package +1141 * structure are stored, excluding a leading "org" or "com". +1142 * Example:</p> +1143 * <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer"); +1144 * System.out.println(obj.getName()); +1145 * for (String p : obj.getPackageStructure()) +1146 * System.out.println(p); +1147 * </code> +1148 * <p> +1149 * Would result in:</p> +1150 * <code>org.owasp.dependencycheck.analyzer.JarAnalyzer +1151 * owasp +1152 * dependencycheck +1153 * analyzer +1154 * jaranalyzer</code> +1155 * +1156 * @param className a fully qualified class name +1157 */ +1158 ClassNameInformation(String className) { +1159 name = className; +1160 if (name.contains("/")) { +1161 final String[] tmp = className.toLowerCase().split("/"); +1162 int start = 0; +1163 int end = 3; +1164 if ("com".equals(tmp[0]) || "org".equals(tmp[0])) { +1165 start = 1; +1166 end = 4; +1167 } +1168 if (tmp.length <= end) { +1169 end = tmp.length - 1; +1170 } +1171 for (int i = start; i <= end; i++) { +1172 packageStructure.add(tmp[i]); +1173 } +1174 } else { +1175 packageStructure.add(name); +1176 } +1177 } +1178 /** +1179 * The fully qualified class name. +1180 */ +1181 private String name; +1182 +1183 /** +1184 * Get the value of name +1185 * +1186 * @return the value of name +1187 */ +1188 public String getName() { +1189 return name; +1190 } +1191 +1192 /** +1193 * Set the value of name +1194 * +1195 * @param name new value of name +1196 */ +1197 public void setName(String name) { +1198 this.name = name; +1199 } +1200 /** +1201 * Up to the first four levels of the package structure, excluding a +1202 * leading "org" or "com". +1203 */ +1204 private final ArrayList<String> packageStructure = new ArrayList<String>(); +1205 +1206 /** +1207 * Get the value of packageStructure +1208 * +1209 * @return the value of packageStructure +1210 */ +1211 public ArrayList<String> getPackageStructure() { +1212 return packageStructure; +1213 } +1214 } +1215 +1216 /** +1217 * Retrieves the next temporary directory to extract an archive too. +1218 * +1219 * @return a directory +1220 * @throws AnalysisException thrown if unable to create temporary directory +1221 */ +1222 private File getNextTempDirectory() throws AnalysisException { +1223 final int dirCount = DIR_COUNT.incrementAndGet(); +1224 final File directory = new File(tempFileLocation, String.valueOf(dirCount)); +1225 //getting an exception for some directories not being able to be created; might be because the directory already exists? +1226 if (directory.exists()) { +1227 return getNextTempDirectory(); +1228 } +1229 if (!directory.mkdirs()) { +1230 final String msg = String.format("Unable to create temp directory '%s'.", directory.getAbsolutePath()); +1231 throw new AnalysisException(msg); +1232 } +1233 return directory; +1234 } +1235 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html index c2b44db91..3b6889c63 100644 --- a/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/NexusAnalyzer.html @@ -95,183 +95,200 @@ 87 */ 88 private static final String SUPPORTED_EXTENSIONS = "jar"; 89 -90 /** -91 * The Nexus Search to be set up for this analyzer. -92 */ -93 private NexusSearch searcher; -94 -95 /** -96 * Field indicating if the analyzer is enabled. -97 */ -98 private final boolean enabled = checkEnabled(); -99 -100 /** -101 * Determines if this analyzer is enabled -102 * -103 * @return <code>true</code> if the analyzer is enabled; otherwise -104 * <code>false</code> -105 */ -106 private boolean checkEnabled() { -107 /* Enable this analyzer ONLY if the Nexus URL has been set to something -108 other than the default one (if it's the default one, we'll use the -109 central one) and it's enabled by the user. -110 */ -111 boolean retval = false; -112 try { -113 if (!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL)) -114 && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) { -115 LOGGER.info("Enabling Nexus analyzer"); -116 retval = true; -117 } else { -118 LOGGER.debug("Nexus analyzer disabled, using Central instead"); -119 } -120 } catch (InvalidSettingException ise) { -121 LOGGER.warn("Invalid setting. Disabling Nexus analyzer"); -122 } -123 -124 return retval; -125 } -126 -127 /** -128 * Determine whether to enable this analyzer or not. -129 * -130 * @return whether the analyzer should be enabled -131 */ -132 @Override -133 public boolean isEnabled() { -134 return enabled; -135 } -136 -137 /** -138 * Initializes the analyzer once before any analysis is performed. -139 * -140 * @throws InitializationException if there's an error during initialization -141 */ -142 @Override -143 public void initializeFileTypeAnalyzer() throws InitializationException { -144 LOGGER.debug("Initializing Nexus Analyzer"); -145 LOGGER.debug("Nexus Analyzer enabled: {}", isEnabled()); -146 if (isEnabled()) { -147 final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL); -148 LOGGER.debug("Nexus Analyzer URL: {}", searchUrl); -149 try { -150 searcher = new NexusSearch(new URL(searchUrl)); -151 if (!searcher.preflightRequest()) { -152 setEnabled(false); -153 throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer."); -154 } -155 } catch (MalformedURLException mue) { -156 setEnabled(false); -157 throw new InitializationException("Malformed URL to Nexus: " + searchUrl, mue); -158 } -159 } -160 } -161 -162 /** -163 * Returns the analyzer's name. -164 * -165 * @return the name of the analyzer -166 */ -167 @Override -168 public String getName() { -169 return ANALYZER_NAME; -170 } -171 -172 /** -173 * Returns the key used in the properties file to reference the analyzer's -174 * enabled property. -175 * -176 * @return the analyzer's enabled property setting key -177 */ -178 @Override -179 protected String getAnalyzerEnabledSettingKey() { -180 return Settings.KEYS.ANALYZER_NEXUS_ENABLED; -181 } -182 -183 /** -184 * Returns the analysis phase under which the analyzer runs. -185 * -186 * @return the phase under which this analyzer runs -187 */ -188 @Override -189 public AnalysisPhase getAnalysisPhase() { -190 return ANALYSIS_PHASE; -191 } -192 -193 /** -194 * The file filter used to determine which files this analyzer supports. -195 */ -196 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(SUPPORTED_EXTENSIONS).build(); -197 -198 /** -199 * Returns the FileFilter -200 * -201 * @return the FileFilter -202 */ -203 @Override -204 protected FileFilter getFileFilter() { -205 return FILTER; -206 } -207 -208 /** -209 * Performs the analysis. -210 * -211 * @param dependency the dependency to analyze -212 * @param engine the engine -213 * @throws AnalysisException when there's an exception during analysis -214 */ -215 @Override -216 public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { -217 if (!isEnabled()) { -218 return; -219 } -220 try { -221 final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum()); -222 dependency.addAsEvidence("nexus", ma, Confidence.HIGH); -223 boolean pomAnalyzed = false; -224 LOGGER.debug("POM URL {}", ma.getPomUrl()); -225 for (Evidence e : dependency.getVendorEvidence()) { -226 if ("pom".equals(e.getSource())) { -227 pomAnalyzed = true; -228 break; -229 } -230 } -231 if (!pomAnalyzed && ma.getPomUrl() != null) { -232 File pomFile = null; -233 try { -234 final File baseDir = Settings.getTempDirectory(); -235 pomFile = File.createTempFile("pom", ".xml", baseDir); -236 if (!pomFile.delete()) { -237 LOGGER.warn("Unable to fetch pom.xml for {} from Nexus repository; " -238 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); -239 LOGGER.debug("Unable to delete temp file"); -240 } -241 LOGGER.debug("Downloading {}", ma.getPomUrl()); -242 Downloader.fetchFile(new URL(ma.getPomUrl()), pomFile); -243 PomUtils.analyzePOM(dependency, pomFile); -244 } catch (DownloadFailedException ex) { -245 LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; " -246 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); -247 } finally { -248 if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) { -249 LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString()); -250 pomFile.deleteOnExit(); -251 } -252 } -253 } -254 } catch (IllegalArgumentException iae) { -255 //dependency.addAnalysisException(new AnalysisException("Invalid SHA-1")); -256 LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName()); -257 } catch (FileNotFoundException fnfe) { -258 //dependency.addAnalysisException(new AnalysisException("Artifact not found on repository")); -259 LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName()); -260 LOGGER.debug(fnfe.getMessage(), fnfe); -261 } catch (IOException ioe) { -262 //dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe)); -263 LOGGER.debug("Could not connect to nexus repository", ioe); -264 } -265 } -266 } +90 private boolean useProxy; +91 /** +92 * The Nexus Search to be set up for this analyzer. +93 */ +94 private NexusSearch searcher; +95 +96 /** +97 * Field indicating if the analyzer is enabled. +98 */ +99 private final boolean enabled = checkEnabled(); +100 +101 /** +102 * Determines if this analyzer is enabled +103 * +104 * @return <code>true</code> if the analyzer is enabled; otherwise +105 * <code>false</code> +106 */ +107 private boolean checkEnabled() { +108 /* Enable this analyzer ONLY if the Nexus URL has been set to something +109 other than the default one (if it's the default one, we'll use the +110 central one) and it's enabled by the user. +111 */ +112 boolean retval = false; +113 try { +114 if (!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL)) +115 && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) { +116 LOGGER.info("Enabling Nexus analyzer"); +117 retval = true; +118 } else { +119 LOGGER.debug("Nexus analyzer disabled, using Central instead"); +120 } +121 } catch (InvalidSettingException ise) { +122 LOGGER.warn("Invalid setting. Disabling Nexus analyzer"); +123 } +124 +125 return retval; +126 } +127 +128 /** +129 * Determine whether to enable this analyzer or not. +130 * +131 * @return whether the analyzer should be enabled +132 */ +133 @Override +134 public boolean isEnabled() { +135 return enabled; +136 } +137 +138 /** +139 * Initializes the analyzer once before any analysis is performed. +140 * +141 * @throws InitializationException if there's an error during initialization +142 */ +143 @Override +144 public void initializeFileTypeAnalyzer() throws InitializationException { +145 LOGGER.debug("Initializing Nexus Analyzer"); +146 LOGGER.debug("Nexus Analyzer enabled: {}", isEnabled()); +147 if (isEnabled()) { +148 useProxy = useProxy(); +149 final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL); +150 LOGGER.debug("Nexus Analyzer URL: {}", searchUrl); +151 try { +152 searcher = new NexusSearch(new URL(searchUrl), useProxy); +153 if (!searcher.preflightRequest()) { +154 setEnabled(false); +155 throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer."); +156 } +157 } catch (MalformedURLException mue) { +158 setEnabled(false); +159 throw new InitializationException("Malformed URL to Nexus: " + searchUrl, mue); +160 } +161 } +162 } +163 +164 /** +165 * Returns the analyzer's name. +166 * +167 * @return the name of the analyzer +168 */ +169 @Override +170 public String getName() { +171 return ANALYZER_NAME; +172 } +173 +174 /** +175 * Returns the key used in the properties file to reference the analyzer's +176 * enabled property. +177 * +178 * @return the analyzer's enabled property setting key +179 */ +180 @Override +181 protected String getAnalyzerEnabledSettingKey() { +182 return Settings.KEYS.ANALYZER_NEXUS_ENABLED; +183 } +184 +185 /** +186 * Returns the analysis phase under which the analyzer runs. +187 * +188 * @return the phase under which this analyzer runs +189 */ +190 @Override +191 public AnalysisPhase getAnalysisPhase() { +192 return ANALYSIS_PHASE; +193 } +194 +195 /** +196 * The file filter used to determine which files this analyzer supports. +197 */ +198 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(SUPPORTED_EXTENSIONS).build(); +199 +200 /** +201 * Returns the FileFilter +202 * +203 * @return the FileFilter +204 */ +205 @Override +206 protected FileFilter getFileFilter() { +207 return FILTER; +208 } +209 +210 /** +211 * Performs the analysis. +212 * +213 * @param dependency the dependency to analyze +214 * @param engine the engine +215 * @throws AnalysisException when there's an exception during analysis +216 */ +217 @Override +218 public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { +219 if (!isEnabled()) { +220 return; +221 } +222 try { +223 final MavenArtifact ma = searcher.searchSha1(dependency.getSha1sum()); +224 dependency.addAsEvidence("nexus", ma, Confidence.HIGH); +225 boolean pomAnalyzed = false; +226 LOGGER.debug("POM URL {}", ma.getPomUrl()); +227 for (Evidence e : dependency.getVendorEvidence()) { +228 if ("pom".equals(e.getSource())) { +229 pomAnalyzed = true; +230 break; +231 } +232 } +233 if (!pomAnalyzed && ma.getPomUrl() != null) { +234 File pomFile = null; +235 try { +236 final File baseDir = Settings.getTempDirectory(); +237 pomFile = File.createTempFile("pom", ".xml", baseDir); +238 if (!pomFile.delete()) { +239 LOGGER.warn("Unable to fetch pom.xml for {} from Nexus repository; " +240 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); +241 LOGGER.debug("Unable to delete temp file"); +242 } +243 LOGGER.debug("Downloading {}", ma.getPomUrl()); +244 Downloader.fetchFile(new URL(ma.getPomUrl()), pomFile); +245 PomUtils.analyzePOM(dependency, pomFile); +246 } catch (DownloadFailedException ex) { +247 LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; " +248 + "this could result in undetected CPE/CVEs.", dependency.getFileName()); +249 } finally { +250 if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) { +251 LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString()); +252 pomFile.deleteOnExit(); +253 } +254 } +255 } +256 } catch (IllegalArgumentException iae) { +257 //dependency.addAnalysisException(new AnalysisException("Invalid SHA-1")); +258 LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName()); +259 } catch (FileNotFoundException fnfe) { +260 //dependency.addAnalysisException(new AnalysisException("Artifact not found on repository")); +261 LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName()); +262 LOGGER.debug(fnfe.getMessage(), fnfe); +263 } catch (IOException ioe) { +264 //dependency.addAnalysisException(new AnalysisException("Could not connect to repository", ioe)); +265 LOGGER.debug("Could not connect to nexus repository", ioe); +266 } +267 } +268 +269 /** +270 * Determine if a proxy should be used. +271 * +272 * @return {@code true} if a proxy should be used +273 */ +274 public static boolean useProxy() { +275 try { +276 return Settings.getString(Settings.KEYS.PROXY_SERVER) != null +277 && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY); +278 } catch (InvalidSettingException ise) { +279 LOGGER.warn("Failed to parse proxy settings.", ise); +280 return false; +281 } +282 } +283 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html index 75128b17b..22a63b4b3 100644 --- a/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.html @@ -44,7 +44,7 @@ 36 * 37 * @author Jeremy Long 38 */ -39 public class NvdCveAnalyzer implements Analyzer { +39 public class NvdCveAnalyzer extends AbstractAnalyzer { 40 /** 41 * The Logger for use throughout the class 42 */ diff --git a/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html index 21cf96edf..32bdda90e 100644 --- a/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.html @@ -53,363 +53,366 @@ 45 import org.owasp.dependencycheck.utils.FileUtils; 46 import org.owasp.dependencycheck.utils.Settings; 47 import org.owasp.dependencycheck.utils.UrlStringUtils; -48 -49 /** -50 * Used to analyze a Wheel or egg distribution files, or their contents in -51 * unzipped form, and collect information that can be used to determine the -52 * associated CPE. -53 * -54 * @author Dale Visser -55 */ -56 @Experimental -57 public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer { -58 -59 /** -60 * Name of egg metadata files to analyze. -61 */ -62 private static final String PKG_INFO = "PKG-INFO"; -63 -64 /** -65 * Name of wheel metadata files to analyze. -66 */ -67 private static final String METADATA = "METADATA"; -68 -69 /** -70 * The logger. -71 */ -72 private static final Logger LOGGER = LoggerFactory -73 .getLogger(PythonDistributionAnalyzer.class); -74 -75 /** -76 * The count of directories created during analysis. This is used for -77 * creating temporary directories. -78 */ -79 private static int dirCount = 0; -80 -81 /** -82 * The name of the analyzer. -83 */ -84 private static final String ANALYZER_NAME = "Python Distribution Analyzer"; -85 /** -86 * The phase that this analyzer is intended to run in. -87 */ -88 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; -89 -90 /** -91 * The set of file extensions supported by this analyzer. -92 */ -93 private static final String[] EXTENSIONS = {"whl", "egg", "zip"}; -94 -95 /** -96 * Used to match on egg archive candidate extensions. -97 */ -98 private static final FileFilter EGG_OR_ZIP = FileFilterBuilder.newInstance().addExtensions("egg", "zip").build(); -99 -100 /** -101 * Used to detect files with a .whl extension. -102 */ -103 private static final FileFilter WHL_FILTER = FileFilterBuilder.newInstance().addExtensions("whl").build(); -104 -105 /** -106 * The parent directory for the individual directories per archive. -107 */ -108 private File tempFileLocation; -109 -110 /** -111 * Filter that detects *.dist-info files (but doesn't verify they are -112 * directories. -113 */ -114 private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter( -115 ".dist-info"); -116 -117 /** -118 * Filter that detects files named "METADATA". -119 */ -120 private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter( -121 "EGG-INFO"); -122 -123 /** -124 * Filter that detects files named "METADATA". -125 */ -126 private static final NameFileFilter METADATA_FILTER = new NameFileFilter( -127 METADATA); -128 -129 /** -130 * Filter that detects files named "PKG-INFO". -131 */ -132 private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter( -133 PKG_INFO); -134 -135 /** -136 * The file filter used to determine which files this analyzer supports. -137 */ -138 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFileFilters( -139 METADATA_FILTER, PKG_INFO_FILTER).addExtensions(EXTENSIONS).build(); -140 -141 /** -142 * Returns the FileFilter -143 * -144 * @return the FileFilter -145 */ -146 @Override -147 protected FileFilter getFileFilter() { -148 return FILTER; -149 } -150 -151 /** -152 * Returns the name of the analyzer. -153 * -154 * @return the name of the analyzer. -155 */ -156 @Override -157 public String getName() { -158 return ANALYZER_NAME; -159 } -160 -161 /** -162 * Returns the phase that the analyzer is intended to run in. -163 * -164 * @return the phase that the analyzer is intended to run in. -165 */ -166 @Override -167 public AnalysisPhase getAnalysisPhase() { -168 return ANALYSIS_PHASE; -169 } -170 -171 /** -172 * Returns the key used in the properties file to reference the analyzer's -173 * enabled property. -174 * -175 * @return the analyzer's enabled property setting key -176 */ -177 @Override -178 protected String getAnalyzerEnabledSettingKey() { -179 return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED; -180 } -181 -182 @Override -183 protected void analyzeFileType(Dependency dependency, Engine engine) -184 throws AnalysisException { -185 final File actualFile = dependency.getActualFile(); -186 if (WHL_FILTER.accept(actualFile)) { -187 collectMetadataFromArchiveFormat(dependency, DIST_INFO_FILTER, -188 METADATA_FILTER); -189 } else if (EGG_OR_ZIP.accept(actualFile)) { -190 collectMetadataFromArchiveFormat(dependency, EGG_INFO_FILTER, -191 PKG_INFO_FILTER); -192 } else { -193 final String name = actualFile.getName(); -194 final boolean metadata = METADATA.equals(name); -195 if (metadata || PKG_INFO.equals(name)) { -196 final File parent = actualFile.getParentFile(); -197 final String parentName = parent.getName(); -198 dependency.setDisplayFileName(parentName + "/" + name); -199 if (parent.isDirectory() -200 && (metadata && parentName.endsWith(".dist-info") -201 || parentName.endsWith(".egg-info") || "EGG-INFO" -202 .equals(parentName))) { -203 collectWheelMetadata(dependency, actualFile); -204 } -205 } -206 } -207 } -208 -209 /** -210 * Collects the meta data from an archive. -211 * -212 * @param dependency the archive being scanned -213 * @param folderFilter the filter to apply to the folder -214 * @param metadataFilter the filter to apply to the meta data -215 * @throws AnalysisException thrown when there is a problem analyzing the -216 * dependency -217 */ -218 private void collectMetadataFromArchiveFormat(Dependency dependency, -219 FilenameFilter folderFilter, FilenameFilter metadataFilter) -220 throws AnalysisException { -221 final File temp = getNextTempDirectory(); -222 LOGGER.debug("{} exists? {}", temp, temp.exists()); -223 try { -224 ExtractionUtil.extractFilesUsingFilter( -225 new File(dependency.getActualFilePath()), temp, -226 metadataFilter); -227 } catch (ExtractionException ex) { -228 throw new AnalysisException(ex); -229 } -230 -231 File matchingFile = getMatchingFile(temp, folderFilter); -232 if (matchingFile != null) { -233 matchingFile = getMatchingFile(matchingFile, metadataFilter); -234 if (matchingFile != null) { -235 collectWheelMetadata(dependency, matchingFile); -236 } -237 } -238 } -239 -240 /** -241 * Makes sure a usable temporary directory is available. -242 * -243 * @throws InitializationException an AnalyzeException is thrown when the -244 * temp directory cannot be created -245 */ -246 @Override -247 protected void initializeFileTypeAnalyzer() throws InitializationException { -248 try { -249 final File baseDir = Settings.getTempDirectory(); -250 tempFileLocation = File.createTempFile("check", "tmp", baseDir); -251 if (!tempFileLocation.delete()) { -252 setEnabled(false); -253 final String msg = String.format( -254 "Unable to delete temporary file '%s'.", -255 tempFileLocation.getAbsolutePath()); -256 throw new InitializationException(msg); -257 } -258 if (!tempFileLocation.mkdirs()) { -259 setEnabled(false); -260 final String msg = String.format( -261 "Unable to create directory '%s'.", -262 tempFileLocation.getAbsolutePath()); -263 throw new InitializationException(msg); -264 } -265 } catch (IOException ex) { -266 setEnabled(false); -267 throw new InitializationException("Unable to create a temporary file", ex); -268 } -269 } -270 -271 /** -272 * Deletes any files extracted from the Wheel during analysis. -273 */ -274 @Override -275 public void close() { -276 if (tempFileLocation != null && tempFileLocation.exists()) { -277 LOGGER.debug("Attempting to delete temporary files"); -278 final boolean success = FileUtils.delete(tempFileLocation); -279 if (!success) { -280 LOGGER.warn( -281 "Failed to delete some temporary files, see the log for more details"); -282 } -283 } -284 } -285 -286 /** -287 * Gathers evidence from the METADATA file. -288 * -289 * @param dependency the dependency being analyzed -290 * @param file a reference to the manifest/properties file -291 */ -292 private static void collectWheelMetadata(Dependency dependency, File file) { -293 final InternetHeaders headers = getManifestProperties(file); -294 addPropertyToEvidence(headers, dependency.getVersionEvidence(), -295 "Version", Confidence.HIGHEST); -296 addPropertyToEvidence(headers, dependency.getProductEvidence(), "Name", -297 Confidence.HIGHEST); -298 final String url = headers.getHeader("Home-page", null); -299 final EvidenceCollection vendorEvidence = dependency -300 .getVendorEvidence(); -301 if (StringUtils.isNotBlank(url)) { -302 if (UrlStringUtils.isUrl(url)) { -303 vendorEvidence.addEvidence(METADATA, "vendor", url, -304 Confidence.MEDIUM); -305 } -306 } -307 addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW); -308 final String summary = headers.getHeader("Summary", null); -309 if (StringUtils.isNotBlank(summary)) { -310 JarAnalyzer -311 .addDescription(dependency, summary, METADATA, "summary"); -312 } -313 } -314 -315 /** -316 * Adds a value to the evidence collection. -317 * -318 * @param headers the properties collection -319 * @param evidence the evidence collection to add the value -320 * @param property the property name -321 * @param confidence the confidence of the evidence -322 */ -323 private static void addPropertyToEvidence(InternetHeaders headers, -324 EvidenceCollection evidence, String property, Confidence confidence) { -325 final String value = headers.getHeader(property, null); -326 LOGGER.debug("Property: {}, Value: {}", property, value); -327 if (StringUtils.isNotBlank(value)) { -328 evidence.addEvidence(METADATA, property, value, confidence); -329 } -330 } -331 -332 /** -333 * Returns a list of files that match the given filter, this does not -334 * recursively scan the directory. -335 * -336 * @param folder the folder to filter -337 * @param filter the filter to apply to the files in the directory -338 * @return the list of Files in the directory that match the provided filter -339 */ -340 private static File getMatchingFile(File folder, FilenameFilter filter) { -341 File result = null; -342 final File[] matches = folder.listFiles(filter); -343 if (null != matches && 1 == matches.length) { -344 result = matches[0]; -345 } -346 return result; -347 } -348 -349 /** -350 * Reads the manifest entries from the provided file. -351 * -352 * @param manifest the manifest -353 * @return the manifest entries -354 */ -355 private static InternetHeaders getManifestProperties(File manifest) { -356 final InternetHeaders result = new InternetHeaders(); -357 if (null == manifest) { -358 LOGGER.debug("Manifest file not found."); -359 } else { -360 InputStream in = null; -361 try { -362 in = new BufferedInputStream(new FileInputStream(manifest)); -363 result.load(in); -364 } catch (MessagingException e) { -365 LOGGER.warn(e.getMessage(), e); -366 } catch (FileNotFoundException e) { -367 LOGGER.warn(e.getMessage(), e); -368 } finally { -369 if (in != null) { -370 try { -371 in.close(); -372 } catch (IOException ex) { -373 LOGGER.debug("failed to close input stream", ex); -374 } -375 } -376 } -377 } -378 return result; -379 } -380 -381 /** -382 * Retrieves the next temporary destination directory for extracting an -383 * archive. -384 * -385 * @return a directory -386 * @throws AnalysisException thrown if unable to create temporary directory -387 */ -388 private File getNextTempDirectory() throws AnalysisException { -389 File directory; -390 -391 // getting an exception for some directories not being able to be -392 // created; might be because the directory already exists? -393 do { -394 dirCount += 1; -395 directory = new File(tempFileLocation, String.valueOf(dirCount)); -396 } while (directory.exists()); -397 if (!directory.mkdirs()) { -398 throw new AnalysisException(String.format( -399 "Unable to create temp directory '%s'.", -400 directory.getAbsolutePath())); -401 } -402 return directory; -403 } -404 } +48 import java.util.concurrent.atomic.AtomicInteger; +49 +50 /** +51 * Used to analyze a Wheel or egg distribution files, or their contents in +52 * unzipped form, and collect information that can be used to determine the +53 * associated CPE. +54 * +55 * @author Dale Visser +56 */ +57 @Experimental +58 public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer { +59 +60 /** +61 * Name of egg metadata files to analyze. +62 */ +63 private static final String PKG_INFO = "PKG-INFO"; +64 +65 /** +66 * Name of wheel metadata files to analyze. +67 */ +68 private static final String METADATA = "METADATA"; +69 +70 /** +71 * The logger. +72 */ +73 private static final Logger LOGGER = LoggerFactory +74 .getLogger(PythonDistributionAnalyzer.class); +75 +76 /** +77 * The count of directories created during analysis. This is used for +78 * creating temporary directories. +79 */ +80 private static final AtomicInteger DIR_COUNT = new AtomicInteger(0); +81 +82 /** +83 * The name of the analyzer. +84 */ +85 private static final String ANALYZER_NAME = "Python Distribution Analyzer"; +86 /** +87 * The phase that this analyzer is intended to run in. +88 */ +89 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; +90 +91 /** +92 * The set of file extensions supported by this analyzer. +93 */ +94 private static final String[] EXTENSIONS = {"whl", "egg", "zip"}; +95 +96 /** +97 * Used to match on egg archive candidate extensions. +98 */ +99 private static final FileFilter EGG_OR_ZIP = FileFilterBuilder.newInstance().addExtensions("egg", "zip").build(); +100 +101 /** +102 * Used to detect files with a .whl extension. +103 */ +104 private static final FileFilter WHL_FILTER = FileFilterBuilder.newInstance().addExtensions("whl").build(); +105 +106 /** +107 * The parent directory for the individual directories per archive. +108 */ +109 private File tempFileLocation; +110 +111 /** +112 * Filter that detects *.dist-info files (but doesn't verify they are +113 * directories. +114 */ +115 private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter( +116 ".dist-info"); +117 +118 /** +119 * Filter that detects files named "METADATA". +120 */ +121 private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter( +122 "EGG-INFO"); +123 +124 /** +125 * Filter that detects files named "METADATA". +126 */ +127 private static final NameFileFilter METADATA_FILTER = new NameFileFilter( +128 METADATA); +129 +130 /** +131 * Filter that detects files named "PKG-INFO". +132 */ +133 private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter( +134 PKG_INFO); +135 +136 /** +137 * The file filter used to determine which files this analyzer supports. +138 */ +139 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFileFilters( +140 METADATA_FILTER, PKG_INFO_FILTER).addExtensions(EXTENSIONS).build(); +141 +142 /** +143 * Returns the FileFilter +144 * +145 * @return the FileFilter +146 */ +147 @Override +148 protected FileFilter getFileFilter() { +149 return FILTER; +150 } +151 +152 /** +153 * Returns the name of the analyzer. +154 * +155 * @return the name of the analyzer. +156 */ +157 @Override +158 public String getName() { +159 return ANALYZER_NAME; +160 } +161 +162 /** +163 * Returns the phase that the analyzer is intended to run in. +164 * +165 * @return the phase that the analyzer is intended to run in. +166 */ +167 @Override +168 public AnalysisPhase getAnalysisPhase() { +169 return ANALYSIS_PHASE; +170 } +171 +172 /** +173 * Returns the key used in the properties file to reference the analyzer's +174 * enabled property. +175 * +176 * @return the analyzer's enabled property setting key +177 */ +178 @Override +179 protected String getAnalyzerEnabledSettingKey() { +180 return Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED; +181 } +182 +183 @Override +184 protected void analyzeFileType(Dependency dependency, Engine engine) +185 throws AnalysisException { +186 final File actualFile = dependency.getActualFile(); +187 if (WHL_FILTER.accept(actualFile)) { +188 collectMetadataFromArchiveFormat(dependency, DIST_INFO_FILTER, +189 METADATA_FILTER); +190 } else if (EGG_OR_ZIP.accept(actualFile)) { +191 collectMetadataFromArchiveFormat(dependency, EGG_INFO_FILTER, +192 PKG_INFO_FILTER); +193 } else { +194 final String name = actualFile.getName(); +195 final boolean metadata = METADATA.equals(name); +196 if (metadata || PKG_INFO.equals(name)) { +197 final File parent = actualFile.getParentFile(); +198 final String parentName = parent.getName(); +199 dependency.setDisplayFileName(parentName + "/" + name); +200 if (parent.isDirectory() +201 && (metadata && parentName.endsWith(".dist-info") +202 || parentName.endsWith(".egg-info") || "EGG-INFO" +203 .equals(parentName))) { +204 collectWheelMetadata(dependency, actualFile); +205 } +206 } +207 } +208 } +209 +210 /** +211 * Collects the meta data from an archive. +212 * +213 * @param dependency the archive being scanned +214 * @param folderFilter the filter to apply to the folder +215 * @param metadataFilter the filter to apply to the meta data +216 * @throws AnalysisException thrown when there is a problem analyzing the +217 * dependency +218 */ +219 private void collectMetadataFromArchiveFormat(Dependency dependency, +220 FilenameFilter folderFilter, FilenameFilter metadataFilter) +221 throws AnalysisException { +222 final File temp = getNextTempDirectory(); +223 LOGGER.debug("{} exists? {}", temp, temp.exists()); +224 try { +225 ExtractionUtil.extractFilesUsingFilter( +226 new File(dependency.getActualFilePath()), temp, +227 metadataFilter); +228 } catch (ExtractionException ex) { +229 throw new AnalysisException(ex); +230 } +231 +232 File matchingFile = getMatchingFile(temp, folderFilter); +233 if (matchingFile != null) { +234 matchingFile = getMatchingFile(matchingFile, metadataFilter); +235 if (matchingFile != null) { +236 collectWheelMetadata(dependency, matchingFile); +237 } +238 } +239 } +240 +241 /** +242 * Makes sure a usable temporary directory is available. +243 * +244 * @throws InitializationException an AnalyzeException is thrown when the +245 * temp directory cannot be created +246 */ +247 @Override +248 protected void initializeFileTypeAnalyzer() throws InitializationException { +249 try { +250 final File baseDir = Settings.getTempDirectory(); +251 tempFileLocation = File.createTempFile("check", "tmp", baseDir); +252 if (!tempFileLocation.delete()) { +253 setEnabled(false); +254 final String msg = String.format( +255 "Unable to delete temporary file '%s'.", +256 tempFileLocation.getAbsolutePath()); +257 throw new InitializationException(msg); +258 } +259 if (!tempFileLocation.mkdirs()) { +260 setEnabled(false); +261 final String msg = String.format( +262 "Unable to create directory '%s'.", +263 tempFileLocation.getAbsolutePath()); +264 throw new InitializationException(msg); +265 } +266 } catch (IOException ex) { +267 setEnabled(false); +268 throw new InitializationException("Unable to create a temporary file", ex); +269 } +270 } +271 +272 /** +273 * Deletes any files extracted from the Wheel during analysis. +274 */ +275 @Override +276 public void close() { +277 if (tempFileLocation != null && tempFileLocation.exists()) { +278 LOGGER.debug("Attempting to delete temporary files"); +279 final boolean success = FileUtils.delete(tempFileLocation); +280 if (!success && tempFileLocation.exists()) { +281 final String[] l = tempFileLocation.list(); +282 if (l != null && l.length > 0) { +283 LOGGER.warn("Failed to delete some temporary files, see the log for more details"); +284 } +285 } +286 } +287 } +288 +289 /** +290 * Gathers evidence from the METADATA file. +291 * +292 * @param dependency the dependency being analyzed +293 * @param file a reference to the manifest/properties file +294 */ +295 private static void collectWheelMetadata(Dependency dependency, File file) { +296 final InternetHeaders headers = getManifestProperties(file); +297 addPropertyToEvidence(headers, dependency.getVersionEvidence(), +298 "Version", Confidence.HIGHEST); +299 addPropertyToEvidence(headers, dependency.getProductEvidence(), "Name", +300 Confidence.HIGHEST); +301 final String url = headers.getHeader("Home-page", null); +302 final EvidenceCollection vendorEvidence = dependency +303 .getVendorEvidence(); +304 if (StringUtils.isNotBlank(url)) { +305 if (UrlStringUtils.isUrl(url)) { +306 vendorEvidence.addEvidence(METADATA, "vendor", url, +307 Confidence.MEDIUM); +308 } +309 } +310 addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW); +311 final String summary = headers.getHeader("Summary", null); +312 if (StringUtils.isNotBlank(summary)) { +313 JarAnalyzer +314 .addDescription(dependency, summary, METADATA, "summary"); +315 } +316 } +317 +318 /** +319 * Adds a value to the evidence collection. +320 * +321 * @param headers the properties collection +322 * @param evidence the evidence collection to add the value +323 * @param property the property name +324 * @param confidence the confidence of the evidence +325 */ +326 private static void addPropertyToEvidence(InternetHeaders headers, +327 EvidenceCollection evidence, String property, Confidence confidence) { +328 final String value = headers.getHeader(property, null); +329 LOGGER.debug("Property: {}, Value: {}", property, value); +330 if (StringUtils.isNotBlank(value)) { +331 evidence.addEvidence(METADATA, property, value, confidence); +332 } +333 } +334 +335 /** +336 * Returns a list of files that match the given filter, this does not +337 * recursively scan the directory. +338 * +339 * @param folder the folder to filter +340 * @param filter the filter to apply to the files in the directory +341 * @return the list of Files in the directory that match the provided filter +342 */ +343 private static File getMatchingFile(File folder, FilenameFilter filter) { +344 File result = null; +345 final File[] matches = folder.listFiles(filter); +346 if (null != matches && 1 == matches.length) { +347 result = matches[0]; +348 } +349 return result; +350 } +351 +352 /** +353 * Reads the manifest entries from the provided file. +354 * +355 * @param manifest the manifest +356 * @return the manifest entries +357 */ +358 private static InternetHeaders getManifestProperties(File manifest) { +359 final InternetHeaders result = new InternetHeaders(); +360 if (null == manifest) { +361 LOGGER.debug("Manifest file not found."); +362 } else { +363 InputStream in = null; +364 try { +365 in = new BufferedInputStream(new FileInputStream(manifest)); +366 result.load(in); +367 } catch (MessagingException e) { +368 LOGGER.warn(e.getMessage(), e); +369 } catch (FileNotFoundException e) { +370 LOGGER.warn(e.getMessage(), e); +371 } finally { +372 if (in != null) { +373 try { +374 in.close(); +375 } catch (IOException ex) { +376 LOGGER.debug("failed to close input stream", ex); +377 } +378 } +379 } +380 } +381 return result; +382 } +383 +384 /** +385 * Retrieves the next temporary destination directory for extracting an +386 * archive. +387 * +388 * @return a directory +389 * @throws AnalysisException thrown if unable to create temporary directory +390 */ +391 private File getNextTempDirectory() throws AnalysisException { +392 File directory; +393 +394 // getting an exception for some directories not being able to be +395 // created; might be because the directory already exists? +396 do { +397 final int dirCount = DIR_COUNT.incrementAndGet(); +398 directory = new File(tempFileLocation, String.valueOf(dirCount)); +399 } while (directory.exists()); +400 if (!directory.mkdirs()) { +401 throw new AnalysisException(String.format( +402 "Unable to create temp directory '%s'.", +403 directory.getAbsolutePath())); +404 } +405 return directory; +406 } +407 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.html index 847ae696f..8ce3074e6 100644 --- a/xref/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.html @@ -41,295 +41,289 @@ 33 import java.io.FileFilter; 34 import java.io.IOException; 35 import java.nio.charset.Charset; -36 import java.util.ArrayList; -37 import java.util.List; -38 import java.util.regex.Matcher; -39 import java.util.regex.Pattern; -40 import org.owasp.dependencycheck.exception.InitializationException; -41 -42 /** -43 * Used to analyze a Python package, and collect information that can be used to -44 * determine the associated CPE. -45 * -46 * @author Dale Visser -47 */ -48 @Experimental -49 public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { -50 -51 /** -52 * Used when compiling file scanning regex patterns. -53 */ -54 private static final int REGEX_OPTIONS = Pattern.DOTALL -55 | Pattern.CASE_INSENSITIVE; -56 -57 /** -58 * Filename extensions for files to be analyzed. -59 */ -60 private static final String EXTENSIONS = "py"; -61 -62 /** -63 * Pattern for matching the module docstring in a source file. -64 */ -65 private static final Pattern MODULE_DOCSTRING = Pattern.compile( -66 "^(['\\\"]{3})(.*?)\\1", REGEX_OPTIONS); -67 -68 /** -69 * Matches assignments to version variables in Python source code. -70 */ -71 private static final Pattern VERSION_PATTERN = Pattern.compile( -72 "\\b(__)?version(__)? *= *(['\"]+)(\\d+\\.\\d+.*?)\\3", -73 REGEX_OPTIONS); -74 -75 /** -76 * Matches assignments to title variables in Python source code. -77 */ -78 private static final Pattern TITLE_PATTERN = compileAssignPattern("title"); -79 -80 /** -81 * Matches assignments to summary variables in Python source code. -82 */ -83 private static final Pattern SUMMARY_PATTERN = compileAssignPattern("summary"); -84 -85 /** -86 * Matches assignments to URL/URL variables in Python source code. -87 */ -88 private static final Pattern URI_PATTERN = compileAssignPattern("ur[il]"); -89 -90 /** -91 * Matches assignments to home page variables in Python source code. -92 */ -93 private static final Pattern HOMEPAGE_PATTERN = compileAssignPattern("home_?page"); -94 -95 /** -96 * Matches assignments to author variables in Python source code. -97 */ -98 private static final Pattern AUTHOR_PATTERN = compileAssignPattern("author"); -99 -100 /** -101 * Filter that detects files named "__init__.py". -102 */ -103 private static final FileFilter INIT_PY_FILTER = new NameFileFilter("__init__.py"); -104 -105 /** -106 * The file filter for python files. -107 */ -108 private static final FileFilter PY_FILTER = new SuffixFileFilter(".py"); -109 -110 /** -111 * Returns the name of the Python Package Analyzer. -112 * -113 * @return the name of the analyzer -114 */ -115 @Override -116 public String getName() { -117 return "Python Package Analyzer"; -118 } -119 -120 /** -121 * Tell that we are used for information collection. -122 * -123 * @return INFORMATION_COLLECTION -124 */ -125 @Override -126 public AnalysisPhase getAnalysisPhase() { -127 return AnalysisPhase.INFORMATION_COLLECTION; -128 } -129 -130 /** -131 * The file filter used to determine which files this analyzer supports. -132 */ -133 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build(); -134 -135 /** -136 * Returns the FileFilter -137 * -138 * @return the FileFilter -139 */ -140 @Override -141 protected FileFilter getFileFilter() { -142 return FILTER; -143 } -144 -145 /** -146 * No-op initializer implementation. -147 * -148 * @throws InitializationException never thrown -149 */ -150 @Override -151 protected void initializeFileTypeAnalyzer() throws InitializationException { -152 // Nothing to do here. -153 } -154 -155 /** -156 * Utility function to create a regex pattern matcher. -157 * -158 * @param name the value to use when constructing the assignment pattern -159 * @return the compiled Pattern -160 */ -161 private static Pattern compileAssignPattern(String name) { -162 return Pattern.compile( -163 String.format("\\b(__)?%s(__)?\\b *= *(['\"]+)(.*?)\\3", name), -164 REGEX_OPTIONS); -165 } -166 -167 /** -168 * Analyzes python packages and adds evidence to the dependency. -169 * -170 * @param dependency the dependency being analyzed -171 * @param engine the engine being used to perform the scan -172 * @throws AnalysisException thrown if there is an unrecoverable error -173 * analyzing the dependency -174 */ -175 @Override -176 protected void analyzeFileType(Dependency dependency, Engine engine) -177 throws AnalysisException { -178 final File file = dependency.getActualFile(); -179 final File parent = file.getParentFile(); -180 final String parentName = parent.getName(); -181 if (INIT_PY_FILTER.accept(file)) { -182 //by definition, the containing folder of __init__.py is considered the package, even the file is empty: -183 //"The __init__.py files are required to make Python treat the directories as containing packages" -184 //see section "6.4 Packages" from https://docs.python.org/2/tutorial/modules.html; -185 dependency.setDisplayFileName(parentName + "/__init__.py"); -186 dependency.getProductEvidence().addEvidence(file.getName(), -187 "PackageName", parentName, Confidence.HIGHEST); -188 -189 final File[] fileList = parent.listFiles(PY_FILTER); -190 if (fileList != null) { -191 for (final File sourceFile : fileList) { -192 analyzeFileContents(dependency, sourceFile); -193 } -194 } -195 } else { -196 // copy, alter and set in case some other thread is iterating over -197 final List<Dependency> dependencies = new ArrayList<Dependency>( -198 engine.getDependencies()); -199 dependencies.remove(dependency); -200 engine.setDependencies(dependencies); -201 } -202 } -203 -204 /** -205 * This should gather information from leading docstrings, file comments, -206 * and assignments to __version__, __title__, __summary__, __uri__, __url__, -207 * __home*page__, __author__, and their all caps equivalents. -208 * -209 * @param dependency the dependency being analyzed -210 * @param file the file name to analyze -211 * @return whether evidence was found -212 * @throws AnalysisException thrown if there is an unrecoverable error -213 */ -214 private boolean analyzeFileContents(Dependency dependency, File file) -215 throws AnalysisException { -216 String contents; -217 try { -218 contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); -219 } catch (IOException e) { -220 throw new AnalysisException( -221 "Problem occurred while reading dependency file.", e); -222 } -223 boolean found = false; -224 if (!contents.isEmpty()) { -225 final String source = file.getName(); -226 found = gatherEvidence(VERSION_PATTERN, contents, source, -227 dependency.getVersionEvidence(), "SourceVersion", -228 Confidence.MEDIUM); -229 found |= addSummaryInfo(dependency, SUMMARY_PATTERN, 4, contents, -230 source, "summary"); -231 if (INIT_PY_FILTER.accept(file)) { -232 found |= addSummaryInfo(dependency, MODULE_DOCSTRING, 2, -233 contents, source, "docstring"); -234 } -235 found |= gatherEvidence(TITLE_PATTERN, contents, source, -236 dependency.getProductEvidence(), "SourceTitle", -237 Confidence.LOW); -238 final EvidenceCollection vendorEvidence = dependency -239 .getVendorEvidence(); -240 found |= gatherEvidence(AUTHOR_PATTERN, contents, source, -241 vendorEvidence, "SourceAuthor", Confidence.MEDIUM); -242 found |= gatherHomePageEvidence(URI_PATTERN, vendorEvidence, -243 source, "URL", contents); -244 found |= gatherHomePageEvidence(HOMEPAGE_PATTERN, -245 vendorEvidence, source, "HomePage", contents); -246 } -247 return found; -248 } -249 -250 /** -251 * Adds summary information to the dependency -252 * -253 * @param dependency the dependency being analyzed -254 * @param pattern the pattern used to perform analysis -255 * @param group the group from the pattern that indicates the data to use -256 * @param contents the data being analyzed -257 * @param source the source name to use when recording the evidence -258 * @param key the key name to use when recording the evidence -259 * @return true if evidence was collected; otherwise false -260 */ -261 private boolean addSummaryInfo(Dependency dependency, Pattern pattern, -262 int group, String contents, String source, String key) { -263 final Matcher matcher = pattern.matcher(contents); -264 final boolean found = matcher.find(); -265 if (found) { -266 JarAnalyzer.addDescription(dependency, matcher.group(group), -267 source, key); -268 } -269 return found; -270 } -271 -272 /** -273 * Collects evidence from the home page URL. -274 * -275 * @param pattern the pattern to match -276 * @param evidence the evidence collection to add the evidence to -277 * @param source the source of the evidence -278 * @param name the name of the evidence -279 * @param contents the home page URL -280 * @return true if evidence was collected; otherwise false -281 */ -282 private boolean gatherHomePageEvidence(Pattern pattern, -283 EvidenceCollection evidence, String source, String name, -284 String contents) { -285 final Matcher matcher = pattern.matcher(contents); -286 boolean found = false; -287 if (matcher.find()) { -288 final String url = matcher.group(4); -289 if (UrlStringUtils.isUrl(url)) { -290 found = true; -291 evidence.addEvidence(source, name, url, Confidence.MEDIUM); -292 } -293 } -294 return found; -295 } -296 -297 /** -298 * Gather evidence from a Python source file using the given string -299 * assignment regex pattern. -300 * -301 * @param pattern to scan contents with -302 * @param contents of Python source file -303 * @param source for storing evidence -304 * @param evidence to store evidence in -305 * @param name of evidence -306 * @param confidence in evidence -307 * @return whether evidence was found -308 */ -309 private boolean gatherEvidence(Pattern pattern, String contents, -310 String source, EvidenceCollection evidence, String name, -311 Confidence confidence) { -312 final Matcher matcher = pattern.matcher(contents); -313 final boolean found = matcher.find(); -314 if (found) { -315 evidence.addEvidence(source, name, matcher.group(4), confidence); -316 } -317 return found; -318 } -319 -320 @Override -321 protected String getAnalyzerEnabledSettingKey() { -322 return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED; -323 } -324 } +36 import java.util.regex.Matcher; +37 import java.util.regex.Pattern; +38 import org.owasp.dependencycheck.exception.InitializationException; +39 +40 /** +41 * Used to analyze a Python package, and collect information that can be used to +42 * determine the associated CPE. +43 * +44 * @author Dale Visser +45 */ +46 @Experimental +47 public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { +48 +49 /** +50 * Used when compiling file scanning regex patterns. +51 */ +52 private static final int REGEX_OPTIONS = Pattern.DOTALL +53 | Pattern.CASE_INSENSITIVE; +54 +55 /** +56 * Filename extensions for files to be analyzed. +57 */ +58 private static final String EXTENSIONS = "py"; +59 +60 /** +61 * Pattern for matching the module docstring in a source file. +62 */ +63 private static final Pattern MODULE_DOCSTRING = Pattern.compile( +64 "^(['\\\"]{3})(.*?)\\1", REGEX_OPTIONS); +65 +66 /** +67 * Matches assignments to version variables in Python source code. +68 */ +69 private static final Pattern VERSION_PATTERN = Pattern.compile( +70 "\\b(__)?version(__)? *= *(['\"]+)(\\d+\\.\\d+.*?)\\3", +71 REGEX_OPTIONS); +72 +73 /** +74 * Matches assignments to title variables in Python source code. +75 */ +76 private static final Pattern TITLE_PATTERN = compileAssignPattern("title"); +77 +78 /** +79 * Matches assignments to summary variables in Python source code. +80 */ +81 private static final Pattern SUMMARY_PATTERN = compileAssignPattern("summary"); +82 +83 /** +84 * Matches assignments to URL/URL variables in Python source code. +85 */ +86 private static final Pattern URI_PATTERN = compileAssignPattern("ur[il]"); +87 +88 /** +89 * Matches assignments to home page variables in Python source code. +90 */ +91 private static final Pattern HOMEPAGE_PATTERN = compileAssignPattern("home_?page"); +92 +93 /** +94 * Matches assignments to author variables in Python source code. +95 */ +96 private static final Pattern AUTHOR_PATTERN = compileAssignPattern("author"); +97 +98 /** +99 * Filter that detects files named "__init__.py". +100 */ +101 private static final FileFilter INIT_PY_FILTER = new NameFileFilter("__init__.py"); +102 +103 /** +104 * The file filter for python files. +105 */ +106 private static final FileFilter PY_FILTER = new SuffixFileFilter(".py"); +107 +108 /** +109 * Returns the name of the Python Package Analyzer. +110 * +111 * @return the name of the analyzer +112 */ +113 @Override +114 public String getName() { +115 return "Python Package Analyzer"; +116 } +117 +118 /** +119 * Tell that we are used for information collection. +120 * +121 * @return INFORMATION_COLLECTION +122 */ +123 @Override +124 public AnalysisPhase getAnalysisPhase() { +125 return AnalysisPhase.INFORMATION_COLLECTION; +126 } +127 +128 /** +129 * The file filter used to determine which files this analyzer supports. +130 */ +131 private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build(); +132 +133 /** +134 * Returns the FileFilter +135 * +136 * @return the FileFilter +137 */ +138 @Override +139 protected FileFilter getFileFilter() { +140 return FILTER; +141 } +142 +143 /** +144 * No-op initializer implementation. +145 * +146 * @throws InitializationException never thrown +147 */ +148 @Override +149 protected void initializeFileTypeAnalyzer() throws InitializationException { +150 // Nothing to do here. +151 } +152 +153 /** +154 * Utility function to create a regex pattern matcher. +155 * +156 * @param name the value to use when constructing the assignment pattern +157 * @return the compiled Pattern +158 */ +159 private static Pattern compileAssignPattern(String name) { +160 return Pattern.compile( +161 String.format("\\b(__)?%s(__)?\\b *= *(['\"]+)(.*?)\\3", name), +162 REGEX_OPTIONS); +163 } +164 +165 /** +166 * Analyzes python packages and adds evidence to the dependency. +167 * +168 * @param dependency the dependency being analyzed +169 * @param engine the engine being used to perform the scan +170 * @throws AnalysisException thrown if there is an unrecoverable error +171 * analyzing the dependency +172 */ +173 @Override +174 protected void analyzeFileType(Dependency dependency, Engine engine) +175 throws AnalysisException { +176 final File file = dependency.getActualFile(); +177 final File parent = file.getParentFile(); +178 final String parentName = parent.getName(); +179 if (INIT_PY_FILTER.accept(file)) { +180 //by definition, the containing folder of __init__.py is considered the package, even the file is empty: +181 //"The __init__.py files are required to make Python treat the directories as containing packages" +182 //see section "6.4 Packages" from https://docs.python.org/2/tutorial/modules.html; +183 dependency.setDisplayFileName(parentName + "/__init__.py"); +184 dependency.getProductEvidence().addEvidence(file.getName(), +185 "PackageName", parentName, Confidence.HIGHEST); +186 +187 final File[] fileList = parent.listFiles(PY_FILTER); +188 if (fileList != null) { +189 for (final File sourceFile : fileList) { +190 analyzeFileContents(dependency, sourceFile); +191 } +192 } +193 } else { +194 engine.getDependencies().remove(dependency); +195 } +196 } +197 +198 /** +199 * This should gather information from leading docstrings, file comments, +200 * and assignments to __version__, __title__, __summary__, __uri__, __url__, +201 * __home*page__, __author__, and their all caps equivalents. +202 * +203 * @param dependency the dependency being analyzed +204 * @param file the file name to analyze +205 * @return whether evidence was found +206 * @throws AnalysisException thrown if there is an unrecoverable error +207 */ +208 private boolean analyzeFileContents(Dependency dependency, File file) +209 throws AnalysisException { +210 String contents; +211 try { +212 contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); +213 } catch (IOException e) { +214 throw new AnalysisException( +215 "Problem occurred while reading dependency file.", e); +216 } +217 boolean found = false; +218 if (!contents.isEmpty()) { +219 final String source = file.getName(); +220 found = gatherEvidence(VERSION_PATTERN, contents, source, +221 dependency.getVersionEvidence(), "SourceVersion", +222 Confidence.MEDIUM); +223 found |= addSummaryInfo(dependency, SUMMARY_PATTERN, 4, contents, +224 source, "summary"); +225 if (INIT_PY_FILTER.accept(file)) { +226 found |= addSummaryInfo(dependency, MODULE_DOCSTRING, 2, +227 contents, source, "docstring"); +228 } +229 found |= gatherEvidence(TITLE_PATTERN, contents, source, +230 dependency.getProductEvidence(), "SourceTitle", +231 Confidence.LOW); +232 final EvidenceCollection vendorEvidence = dependency +233 .getVendorEvidence(); +234 found |= gatherEvidence(AUTHOR_PATTERN, contents, source, +235 vendorEvidence, "SourceAuthor", Confidence.MEDIUM); +236 found |= gatherHomePageEvidence(URI_PATTERN, vendorEvidence, +237 source, "URL", contents); +238 found |= gatherHomePageEvidence(HOMEPAGE_PATTERN, +239 vendorEvidence, source, "HomePage", contents); +240 } +241 return found; +242 } +243 +244 /** +245 * Adds summary information to the dependency +246 * +247 * @param dependency the dependency being analyzed +248 * @param pattern the pattern used to perform analysis +249 * @param group the group from the pattern that indicates the data to use +250 * @param contents the data being analyzed +251 * @param source the source name to use when recording the evidence +252 * @param key the key name to use when recording the evidence +253 * @return true if evidence was collected; otherwise false +254 */ +255 private boolean addSummaryInfo(Dependency dependency, Pattern pattern, +256 int group, String contents, String source, String key) { +257 final Matcher matcher = pattern.matcher(contents); +258 final boolean found = matcher.find(); +259 if (found) { +260 JarAnalyzer.addDescription(dependency, matcher.group(group), +261 source, key); +262 } +263 return found; +264 } +265 +266 /** +267 * Collects evidence from the home page URL. +268 * +269 * @param pattern the pattern to match +270 * @param evidence the evidence collection to add the evidence to +271 * @param source the source of the evidence +272 * @param name the name of the evidence +273 * @param contents the home page URL +274 * @return true if evidence was collected; otherwise false +275 */ +276 private boolean gatherHomePageEvidence(Pattern pattern, +277 EvidenceCollection evidence, String source, String name, +278 String contents) { +279 final Matcher matcher = pattern.matcher(contents); +280 boolean found = false; +281 if (matcher.find()) { +282 final String url = matcher.group(4); +283 if (UrlStringUtils.isUrl(url)) { +284 found = true; +285 evidence.addEvidence(source, name, url, Confidence.MEDIUM); +286 } +287 } +288 return found; +289 } +290 +291 /** +292 * Gather evidence from a Python source file using the given string +293 * assignment regex pattern. +294 * +295 * @param pattern to scan contents with +296 * @param contents of Python source file +297 * @param source for storing evidence +298 * @param evidence to store evidence in +299 * @param name of evidence +300 * @param confidence in evidence +301 * @return whether evidence was found +302 */ +303 private boolean gatherEvidence(Pattern pattern, String contents, +304 String source, EvidenceCollection evidence, String name, +305 Confidence confidence) { +306 final Matcher matcher = pattern.matcher(contents); +307 final boolean found = matcher.find(); +308 if (found) { +309 evidence.addEvidence(source, name, matcher.group(4), confidence); +310 } +311 return found; +312 } +313 +314 @Override +315 protected String getAnalyzerEnabledSettingKey() { +316 return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED; +317 } +318 }
      diff --git a/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html b/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html index 3cd157e12..3c4daa4be 100644 --- a/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html +++ b/xref/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.html @@ -294,7 +294,7 @@ 286 } catch (InterruptedException ie) { 287 throw new AnalysisException("bundle-audit process interrupted", ie); 288 } -289 if (exitValue != 0) { +289 if (exitValue < 0 || exitValue > 1) { 290 final String msg = String.format("Unexpected exit code from bundle-audit process; exit code: %s", exitValue); 291 throw new AnalysisException(msg); 292 } diff --git a/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html b/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html index b0971b9e8..addaaef34 100644 --- a/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html +++ b/xref/org/owasp/dependencycheck/analyzer/exception/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.analyzer.exception + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.analyzer.exception diff --git a/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html b/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html index 97d576deb..35cd52cbc 100644 --- a/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html +++ b/xref/org/owasp/dependencycheck/analyzer/exception/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.analyzer.exception + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.analyzer.exception diff --git a/xref/org/owasp/dependencycheck/analyzer/package-frame.html b/xref/org/owasp/dependencycheck/analyzer/package-frame.html index 71b88d8fd..6897d618e 100644 --- a/xref/org/owasp/dependencycheck/analyzer/package-frame.html +++ b/xref/org/owasp/dependencycheck/analyzer/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.analyzer diff --git a/xref/org/owasp/dependencycheck/analyzer/package-summary.html b/xref/org/owasp/dependencycheck/analyzer/package-summary.html index 32f07292a..8ea4fb7c5 100644 --- a/xref/org/owasp/dependencycheck/analyzer/package-summary.html +++ b/xref/org/owasp/dependencycheck/analyzer/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.analyzer + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.analyzer diff --git a/xref/org/owasp/dependencycheck/ant/logging/AntLoggerAdapter.html b/xref/org/owasp/dependencycheck/ant/logging/AntLoggerAdapter.html index acddbbbba..5b4488ba0 100644 --- a/xref/org/owasp/dependencycheck/ant/logging/AntLoggerAdapter.html +++ b/xref/org/owasp/dependencycheck/ant/logging/AntLoggerAdapter.html @@ -32,253 +32,258 @@ 24 import org.slf4j.helpers.MessageFormatter; 25 26 /** -27 * An instance of {@link org.slf4j.Logger} which simply calls the log method on the delegate Ant task. -28 * -29 * @author colezlaw -30 */ -31 public class AntLoggerAdapter extends MarkerIgnoringBase { -32 -33 /** -34 * A reference to the Ant task used for logging. -35 */ -36 private Task task; -37 +27 * An instance of {@link org.slf4j.Logger} which simply calls the log method on +28 * the delegate Ant task. +29 * +30 * @author colezlaw +31 */ +32 public class AntLoggerAdapter extends MarkerIgnoringBase { +33 +34 /** +35 * serialization UID. +36 */ +37 private static final long serialVersionUID = -1337; 38 /** -39 * Constructs an Ant Logger Adapter. -40 * -41 * @param task the Ant Task to use for logging -42 */ -43 public AntLoggerAdapter(Task task) { -44 super(); -45 this.task = task; -46 } -47 -48 /** -49 * Sets the current Ant task to use for logging. -50 * -51 * @param task the Ant task to use for logging -52 */ -53 public void setTask(Task task) { -54 this.task = task; -55 } -56 -57 @Override -58 public boolean isTraceEnabled() { -59 // Might be a more efficient way to do this, but Ant doesn't enable or disable -60 // various levels globally - it just fires things at registered Listeners. -61 return true; -62 } -63 -64 @Override -65 public void trace(String msg) { -66 if (task != null) { -67 task.log(msg, Project.MSG_VERBOSE); -68 } -69 } -70 -71 @Override -72 public void trace(String format, Object arg) { -73 if (task != null) { -74 final FormattingTuple tp = MessageFormatter.format(format, arg); -75 task.log(tp.getMessage(), Project.MSG_VERBOSE); -76 } -77 } -78 -79 @Override -80 public void trace(String format, Object arg1, Object arg2) { -81 if (task != null) { -82 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -83 task.log(tp.getMessage(), Project.MSG_VERBOSE); -84 } -85 } -86 -87 @Override -88 public void trace(String format, Object... arguments) { -89 if (task != null) { -90 final FormattingTuple tp = MessageFormatter.format(format, arguments); -91 task.log(tp.getMessage(), Project.MSG_VERBOSE); -92 } -93 } -94 -95 @Override -96 public void trace(String msg, Throwable t) { -97 if (task != null) { -98 task.log(msg, t, Project.MSG_VERBOSE); -99 } -100 } -101 -102 @Override -103 public boolean isDebugEnabled() { -104 return true; +39 * A reference to the Ant task used for logging. +40 */ +41 private transient Task task; +42 +43 /** +44 * Constructs an Ant Logger Adapter. +45 * +46 * @param task the Ant Task to use for logging +47 */ +48 public AntLoggerAdapter(Task task) { +49 super(); +50 this.task = task; +51 } +52 +53 /** +54 * Sets the current Ant task to use for logging. +55 * +56 * @param task the Ant task to use for logging +57 */ +58 public void setTask(Task task) { +59 this.task = task; +60 } +61 +62 @Override +63 public boolean isTraceEnabled() { +64 // Might be a more efficient way to do this, but Ant doesn't enable or disable +65 // various levels globally - it just fires things at registered Listeners. +66 return true; +67 } +68 +69 @Override +70 public void trace(String msg) { +71 if (task != null) { +72 task.log(msg, Project.MSG_VERBOSE); +73 } +74 } +75 +76 @Override +77 public void trace(String format, Object arg) { +78 if (task != null) { +79 final FormattingTuple tp = MessageFormatter.format(format, arg); +80 task.log(tp.getMessage(), Project.MSG_VERBOSE); +81 } +82 } +83 +84 @Override +85 public void trace(String format, Object arg1, Object arg2) { +86 if (task != null) { +87 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +88 task.log(tp.getMessage(), Project.MSG_VERBOSE); +89 } +90 } +91 +92 @Override +93 public void trace(String format, Object... arguments) { +94 if (task != null) { +95 final FormattingTuple tp = MessageFormatter.format(format, arguments); +96 task.log(tp.getMessage(), Project.MSG_VERBOSE); +97 } +98 } +99 +100 @Override +101 public void trace(String msg, Throwable t) { +102 if (task != null) { +103 task.log(msg, t, Project.MSG_VERBOSE); +104 } 105 } 106 107 @Override -108 public void debug(String msg) { -109 if (task != null) { -110 task.log(msg, Project.MSG_DEBUG); -111 } -112 } -113 -114 @Override -115 public void debug(String format, Object arg) { -116 if (task != null) { -117 final FormattingTuple tp = MessageFormatter.format(format, arg); -118 task.log(tp.getMessage(), Project.MSG_DEBUG); -119 } -120 } -121 -122 @Override -123 public void debug(String format, Object arg1, Object arg2) { -124 if (task != null) { -125 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -126 task.log(tp.getMessage(), Project.MSG_DEBUG); -127 } -128 } -129 -130 @Override -131 public void debug(String format, Object... arguments) { -132 if (task != null) { -133 final FormattingTuple tp = MessageFormatter.format(format, arguments); -134 task.log(tp.getMessage(), Project.MSG_DEBUG); -135 } -136 } -137 -138 @Override -139 public void debug(String msg, Throwable t) { -140 if (task != null) { -141 task.log(msg, t, Project.MSG_DEBUG); -142 } -143 } -144 -145 @Override -146 public boolean isInfoEnabled() { -147 return true; +108 public boolean isDebugEnabled() { +109 return true; +110 } +111 +112 @Override +113 public void debug(String msg) { +114 if (task != null) { +115 task.log(msg, Project.MSG_DEBUG); +116 } +117 } +118 +119 @Override +120 public void debug(String format, Object arg) { +121 if (task != null) { +122 final FormattingTuple tp = MessageFormatter.format(format, arg); +123 task.log(tp.getMessage(), Project.MSG_DEBUG); +124 } +125 } +126 +127 @Override +128 public void debug(String format, Object arg1, Object arg2) { +129 if (task != null) { +130 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +131 task.log(tp.getMessage(), Project.MSG_DEBUG); +132 } +133 } +134 +135 @Override +136 public void debug(String format, Object... arguments) { +137 if (task != null) { +138 final FormattingTuple tp = MessageFormatter.format(format, arguments); +139 task.log(tp.getMessage(), Project.MSG_DEBUG); +140 } +141 } +142 +143 @Override +144 public void debug(String msg, Throwable t) { +145 if (task != null) { +146 task.log(msg, t, Project.MSG_DEBUG); +147 } 148 } 149 150 @Override -151 public void info(String msg) { -152 if (task != null) { -153 task.log(msg, Project.MSG_INFO); -154 } -155 } -156 -157 @Override -158 public void info(String format, Object arg) { -159 if (task != null) { -160 final FormattingTuple tp = MessageFormatter.format(format, arg); -161 task.log(tp.getMessage(), Project.MSG_INFO); -162 } -163 } -164 -165 @Override -166 public void info(String format, Object arg1, Object arg2) { -167 if (task != null) { -168 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -169 task.log(tp.getMessage(), Project.MSG_INFO); -170 } -171 } -172 -173 @Override -174 public void info(String format, Object... arguments) { -175 if (task != null) { -176 final FormattingTuple tp = MessageFormatter.format(format, arguments); -177 task.log(tp.getMessage(), Project.MSG_INFO); -178 } -179 } -180 -181 @Override -182 public void info(String msg, Throwable t) { -183 if (task != null) { -184 task.log(msg, t, Project.MSG_INFO); -185 } -186 } -187 -188 @Override -189 public boolean isWarnEnabled() { -190 return true; +151 public boolean isInfoEnabled() { +152 return true; +153 } +154 +155 @Override +156 public void info(String msg) { +157 if (task != null) { +158 task.log(msg, Project.MSG_INFO); +159 } +160 } +161 +162 @Override +163 public void info(String format, Object arg) { +164 if (task != null) { +165 final FormattingTuple tp = MessageFormatter.format(format, arg); +166 task.log(tp.getMessage(), Project.MSG_INFO); +167 } +168 } +169 +170 @Override +171 public void info(String format, Object arg1, Object arg2) { +172 if (task != null) { +173 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +174 task.log(tp.getMessage(), Project.MSG_INFO); +175 } +176 } +177 +178 @Override +179 public void info(String format, Object... arguments) { +180 if (task != null) { +181 final FormattingTuple tp = MessageFormatter.format(format, arguments); +182 task.log(tp.getMessage(), Project.MSG_INFO); +183 } +184 } +185 +186 @Override +187 public void info(String msg, Throwable t) { +188 if (task != null) { +189 task.log(msg, t, Project.MSG_INFO); +190 } 191 } 192 193 @Override -194 public void warn(String msg) { -195 if (task != null) { -196 task.log(msg, Project.MSG_WARN); -197 } -198 } -199 -200 @Override -201 public void warn(String format, Object arg) { -202 if (task != null) { -203 final FormattingTuple tp = MessageFormatter.format(format, arg); -204 task.log(tp.getMessage(), Project.MSG_WARN); -205 } -206 } -207 -208 @Override -209 public void warn(String format, Object... arguments) { -210 if (task != null) { -211 final FormattingTuple tp = MessageFormatter.format(format, arguments); -212 task.log(tp.getMessage(), Project.MSG_WARN); -213 } -214 } -215 -216 @Override -217 public void warn(String format, Object arg1, Object arg2) { -218 if (task != null) { -219 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -220 task.log(tp.getMessage(), Project.MSG_WARN); -221 } -222 } -223 -224 @Override -225 public void warn(String msg, Throwable t) { -226 if (task != null) { -227 task.log(msg, t, Project.MSG_WARN); -228 } -229 } -230 -231 @Override -232 public boolean isErrorEnabled() { -233 return true; +194 public boolean isWarnEnabled() { +195 return true; +196 } +197 +198 @Override +199 public void warn(String msg) { +200 if (task != null) { +201 task.log(msg, Project.MSG_WARN); +202 } +203 } +204 +205 @Override +206 public void warn(String format, Object arg) { +207 if (task != null) { +208 final FormattingTuple tp = MessageFormatter.format(format, arg); +209 task.log(tp.getMessage(), Project.MSG_WARN); +210 } +211 } +212 +213 @Override +214 public void warn(String format, Object... arguments) { +215 if (task != null) { +216 final FormattingTuple tp = MessageFormatter.format(format, arguments); +217 task.log(tp.getMessage(), Project.MSG_WARN); +218 } +219 } +220 +221 @Override +222 public void warn(String format, Object arg1, Object arg2) { +223 if (task != null) { +224 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +225 task.log(tp.getMessage(), Project.MSG_WARN); +226 } +227 } +228 +229 @Override +230 public void warn(String msg, Throwable t) { +231 if (task != null) { +232 task.log(msg, t, Project.MSG_WARN); +233 } 234 } 235 236 @Override -237 public void error(String msg) { -238 if (task != null) { -239 task.log(msg, Project.MSG_ERR); -240 } -241 } -242 -243 @Override -244 public void error(String format, Object arg) { -245 if (task != null) { -246 final FormattingTuple tp = MessageFormatter.format(format, arg); -247 task.log(tp.getMessage(), Project.MSG_ERR); -248 } -249 } -250 -251 @Override -252 public void error(String format, Object arg1, Object arg2) { -253 if (task != null) { -254 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); -255 task.log(tp.getMessage(), Project.MSG_ERR); -256 } -257 } -258 -259 @Override -260 public void error(String format, Object... arguments) { -261 if (task != null) { -262 final FormattingTuple tp = MessageFormatter.format(format, arguments); -263 task.log(tp.getMessage(), Project.MSG_ERR); -264 } -265 } -266 -267 @Override -268 public void error(String msg, Throwable t) { -269 if (task != null) { -270 task.log(msg, t, Project.MSG_ERR); -271 } -272 } -273 } +237 public boolean isErrorEnabled() { +238 return true; +239 } +240 +241 @Override +242 public void error(String msg) { +243 if (task != null) { +244 task.log(msg, Project.MSG_ERR); +245 } +246 } +247 +248 @Override +249 public void error(String format, Object arg) { +250 if (task != null) { +251 final FormattingTuple tp = MessageFormatter.format(format, arg); +252 task.log(tp.getMessage(), Project.MSG_ERR); +253 } +254 } +255 +256 @Override +257 public void error(String format, Object arg1, Object arg2) { +258 if (task != null) { +259 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); +260 task.log(tp.getMessage(), Project.MSG_ERR); +261 } +262 } +263 +264 @Override +265 public void error(String format, Object... arguments) { +266 if (task != null) { +267 final FormattingTuple tp = MessageFormatter.format(format, arguments); +268 task.log(tp.getMessage(), Project.MSG_ERR); +269 } +270 } +271 +272 @Override +273 public void error(String msg, Throwable t) { +274 if (task != null) { +275 task.log(msg, t, Project.MSG_ERR); +276 } +277 } +278 }
      diff --git a/xref/org/owasp/dependencycheck/ant/logging/package-frame.html b/xref/org/owasp/dependencycheck/ant/logging/package-frame.html index 7e6d7ad72..92ff1b1ea 100644 --- a/xref/org/owasp/dependencycheck/ant/logging/package-frame.html +++ b/xref/org/owasp/dependencycheck/ant/logging/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.ant.logging + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.ant.logging diff --git a/xref/org/owasp/dependencycheck/ant/logging/package-summary.html b/xref/org/owasp/dependencycheck/ant/logging/package-summary.html index 38e88e0de..e642db94a 100644 --- a/xref/org/owasp/dependencycheck/ant/logging/package-summary.html +++ b/xref/org/owasp/dependencycheck/ant/logging/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.ant.logging + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.ant.logging diff --git a/xref/org/owasp/dependencycheck/data/central/CentralSearch.html b/xref/org/owasp/dependencycheck/data/central/CentralSearch.html index b7dba63dd..4d8e1cc43 100644 --- a/xref/org/owasp/dependencycheck/data/central/CentralSearch.html +++ b/xref/org/owasp/dependencycheck/data/central/CentralSearch.html @@ -59,7 +59,7 @@ 51 /** 52 * Whether to use the Proxy when making requests 53 */ -54 private boolean useProxy; +54 private final boolean useProxy; 55 56 /** 57 * Used for logging. @@ -118,62 +118,63 @@ 110 if (conn.getResponseCode() == 200) { 111 boolean missing = false; 112 try { -113 final DocumentBuilder builder = DocumentBuilderFactory -114 .newInstance().newDocumentBuilder(); -115 final Document doc = builder.parse(conn.getInputStream()); -116 final XPath xpath = XPathFactory.newInstance().newXPath(); -117 final String numFound = xpath.evaluate("/response/result/@numFound", doc); -118 if ("0".equals(numFound)) { -119 missing = true; -120 } else { -121 result = new ArrayList<MavenArtifact>(); -122 final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET); -123 for (int i = 0; i < docs.getLength(); i++) { -124 final String g = xpath.evaluate("./str[@name='g']", docs.item(i)); -125 LOGGER.trace("GroupId: {}", g); -126 final String a = xpath.evaluate("./str[@name='a']", docs.item(i)); -127 LOGGER.trace("ArtifactId: {}", a); -128 final String v = xpath.evaluate("./str[@name='v']", docs.item(i)); -129 NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET); -130 boolean pomAvailable = false; -131 boolean jarAvailable = false; -132 for (int x = 0; x < atts.getLength(); x++) { -133 final String tmp = xpath.evaluate(".", atts.item(x)); -134 if (".pom".equals(tmp)) { -135 pomAvailable = true; -136 } else if (".jar".equals(tmp)) { -137 jarAvailable = true; -138 } -139 } -140 -141 atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET); -142 boolean useHTTPS = false; -143 for (int x = 0; x < atts.getLength(); x++) { -144 final String tmp = xpath.evaluate(".", atts.item(x)); -145 if ("https".equals(tmp)) { -146 useHTTPS = true; -147 } -148 } -149 LOGGER.trace("Version: {}", v); -150 result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS)); -151 } -152 } -153 } catch (Throwable e) { -154 // Anything else is jacked up XML stuff that we really can't recover from well -155 throw new IOException(e.getMessage(), e); -156 } -157 -158 if (missing) { -159 throw new FileNotFoundException("Artifact not found in Central"); -160 } -161 } else { -162 LOGGER.debug("Could not connect to Central received response code: {} {}", -163 conn.getResponseCode(), conn.getResponseMessage()); -164 throw new IOException("Could not connect to Central"); -165 } -166 return result; -167 } -168 } +113 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +114 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +115 final DocumentBuilder builder = factory.newDocumentBuilder(); +116 final Document doc = builder.parse(conn.getInputStream()); +117 final XPath xpath = XPathFactory.newInstance().newXPath(); +118 final String numFound = xpath.evaluate("/response/result/@numFound", doc); +119 if ("0".equals(numFound)) { +120 missing = true; +121 } else { +122 result = new ArrayList<MavenArtifact>(); +123 final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET); +124 for (int i = 0; i < docs.getLength(); i++) { +125 final String g = xpath.evaluate("./str[@name='g']", docs.item(i)); +126 LOGGER.trace("GroupId: {}", g); +127 final String a = xpath.evaluate("./str[@name='a']", docs.item(i)); +128 LOGGER.trace("ArtifactId: {}", a); +129 final String v = xpath.evaluate("./str[@name='v']", docs.item(i)); +130 NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET); +131 boolean pomAvailable = false; +132 boolean jarAvailable = false; +133 for (int x = 0; x < atts.getLength(); x++) { +134 final String tmp = xpath.evaluate(".", atts.item(x)); +135 if (".pom".equals(tmp)) { +136 pomAvailable = true; +137 } else if (".jar".equals(tmp)) { +138 jarAvailable = true; +139 } +140 } +141 +142 atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET); +143 boolean useHTTPS = false; +144 for (int x = 0; x < atts.getLength(); x++) { +145 final String tmp = xpath.evaluate(".", atts.item(x)); +146 if ("https".equals(tmp)) { +147 useHTTPS = true; +148 } +149 } +150 LOGGER.trace("Version: {}", v); +151 result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS)); +152 } +153 } +154 } catch (Throwable e) { +155 // Anything else is jacked up XML stuff that we really can't recover from well +156 throw new IOException(e.getMessage(), e); +157 } +158 +159 if (missing) { +160 throw new FileNotFoundException("Artifact not found in Central"); +161 } +162 } else { +163 LOGGER.debug("Could not connect to Central received response code: {} {}", +164 conn.getResponseCode(), conn.getResponseMessage()); +165 throw new IOException("Could not connect to Central"); +166 } +167 return result; +168 } +169 }
      diff --git a/xref/org/owasp/dependencycheck/data/central/package-frame.html b/xref/org/owasp/dependencycheck/data/central/package-frame.html index 1110619b7..d5c1e38e6 100644 --- a/xref/org/owasp/dependencycheck/data/central/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/central/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.central diff --git a/xref/org/owasp/dependencycheck/data/central/package-summary.html b/xref/org/owasp/dependencycheck/data/central/package-summary.html index 76122895b..68767d279 100644 --- a/xref/org/owasp/dependencycheck/data/central/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/central/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.central + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.central diff --git a/xref/org/owasp/dependencycheck/data/composer/package-frame.html b/xref/org/owasp/dependencycheck/data/composer/package-frame.html index 8430b0865..a45529fb7 100644 --- a/xref/org/owasp/dependencycheck/data/composer/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/composer/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.composer diff --git a/xref/org/owasp/dependencycheck/data/composer/package-summary.html b/xref/org/owasp/dependencycheck/data/composer/package-summary.html index 66a530780..32e81df8a 100644 --- a/xref/org/owasp/dependencycheck/data/composer/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/composer/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.composer + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.composer diff --git a/xref/org/owasp/dependencycheck/data/cpe/package-frame.html b/xref/org/owasp/dependencycheck/data/cpe/package-frame.html index 36b62e432..3604a954a 100644 --- a/xref/org/owasp/dependencycheck/data/cpe/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/cpe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.cpe diff --git a/xref/org/owasp/dependencycheck/data/cpe/package-summary.html b/xref/org/owasp/dependencycheck/data/cpe/package-summary.html index 2884a27b2..ac6343db1 100644 --- a/xref/org/owasp/dependencycheck/data/cpe/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/cpe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.cpe + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.cpe diff --git a/xref/org/owasp/dependencycheck/data/cwe/package-frame.html b/xref/org/owasp/dependencycheck/data/cwe/package-frame.html index e78c9f00d..8939e76d9 100644 --- a/xref/org/owasp/dependencycheck/data/cwe/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/cwe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.cwe diff --git a/xref/org/owasp/dependencycheck/data/cwe/package-summary.html b/xref/org/owasp/dependencycheck/data/cwe/package-summary.html index c7525ee6c..c57d4a44c 100644 --- a/xref/org/owasp/dependencycheck/data/cwe/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/cwe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.cwe + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.cwe diff --git a/xref/org/owasp/dependencycheck/data/lucene/package-frame.html b/xref/org/owasp/dependencycheck/data/lucene/package-frame.html index e49c33407..eaefa052e 100644 --- a/xref/org/owasp/dependencycheck/data/lucene/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/lucene/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.lucene diff --git a/xref/org/owasp/dependencycheck/data/lucene/package-summary.html b/xref/org/owasp/dependencycheck/data/lucene/package-summary.html index 4d36964af..c7676bbe0 100644 --- a/xref/org/owasp/dependencycheck/data/lucene/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/lucene/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.lucene + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.lucene diff --git a/xref/org/owasp/dependencycheck/data/nexus/NexusSearch.html b/xref/org/owasp/dependencycheck/data/nexus/NexusSearch.html index 45df20fa9..53f965702 100644 --- a/xref/org/owasp/dependencycheck/data/nexus/NexusSearch.html +++ b/xref/org/owasp/dependencycheck/data/nexus/NexusSearch.html @@ -33,165 +33,163 @@ 25 import javax.xml.parsers.DocumentBuilderFactory; 26 import javax.xml.xpath.XPath; 27 import javax.xml.xpath.XPathFactory; -28 import org.owasp.dependencycheck.utils.InvalidSettingException; -29 import org.owasp.dependencycheck.utils.Settings; -30 import org.owasp.dependencycheck.utils.URLConnectionFactory; -31 import org.slf4j.Logger; -32 import org.slf4j.LoggerFactory; -33 import org.w3c.dom.Document; -34 -35 /** -36 * Class of methods to search Nexus repositories. -37 * -38 * @author colezlaw -39 */ -40 public class NexusSearch { -41 -42 /** -43 * The root URL for the Nexus repository service. -44 */ -45 private final URL rootURL; -46 -47 /** -48 * Whether to use the Proxy when making requests. -49 */ -50 private boolean useProxy; -51 /** -52 * Used for logging. -53 */ -54 private static final Logger LOGGER = LoggerFactory.getLogger(NexusSearch.class); -55 -56 /** -57 * Creates a NexusSearch for the given repository URL. -58 * -59 * @param rootURL the root URL of the repository on which searches should execute. full URL's are calculated relative to this -60 * URL, so it should end with a / -61 */ -62 public NexusSearch(URL rootURL) { -63 this.rootURL = rootURL; -64 try { -65 if (null != Settings.getString(Settings.KEYS.PROXY_SERVER) -66 && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY)) { -67 useProxy = true; -68 LOGGER.debug("Using proxy"); -69 } else { -70 useProxy = false; -71 LOGGER.debug("Not using proxy"); -72 } -73 } catch (InvalidSettingException ise) { -74 useProxy = false; -75 } -76 } -77 -78 /** -79 * Searches the configured Nexus repository for the given sha1 hash. If the artifact is found, a <code>MavenArtifact</code> is -80 * populated with the coordinate information. -81 * -82 * @param sha1 The SHA-1 hash string for which to search -83 * @return the populated Maven coordinates -84 * @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not found. -85 */ -86 public MavenArtifact searchSha1(String sha1) throws IOException { -87 if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) { -88 throw new IllegalArgumentException("Invalid SHA1 format"); -89 } +28 +29 import org.owasp.dependencycheck.utils.InvalidSettingException; +30 import org.owasp.dependencycheck.utils.Settings; +31 import org.owasp.dependencycheck.utils.URLConnectionFactory; +32 import org.slf4j.Logger; +33 import org.slf4j.LoggerFactory; +34 import org.w3c.dom.Document; +35 +36 /** +37 * Class of methods to search Nexus repositories. +38 * +39 * @author colezlaw +40 */ +41 public class NexusSearch { +42 +43 /** +44 * The root URL for the Nexus repository service. +45 */ +46 private final URL rootURL; +47 +48 /** +49 * Whether to use the Proxy when making requests. +50 */ +51 private final boolean useProxy; +52 /** +53 * Used for logging. +54 */ +55 private static final Logger LOGGER = LoggerFactory.getLogger(NexusSearch.class); +56 +57 /** +58 * Creates a NexusSearch for the given repository URL. +59 * +60 * @param rootURL the root URL of the repository on which searches should +61 * execute. full URL's are calculated relative to this URL, so it should end +62 * with a / +63 * @param useProxy flag indicating if the proxy settings should be used +64 */ +65 public NexusSearch(URL rootURL, boolean useProxy) { +66 this.rootURL = rootURL; +67 this.useProxy = useProxy; +68 LOGGER.debug("Using proxy: {}", useProxy); +69 } +70 +71 /** +72 * Searches the configured Nexus repository for the given sha1 hash. If the +73 * artifact is found, a <code>MavenArtifact</code> is populated with the +74 * coordinate information. +75 * +76 * @param sha1 The SHA-1 hash string for which to search +77 * @return the populated Maven coordinates +78 * @throws IOException if it's unable to connect to the specified repository +79 * or if the specified artifact is not found. +80 */ +81 public MavenArtifact searchSha1(String sha1) throws IOException { +82 if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) { +83 throw new IllegalArgumentException("Invalid SHA1 format"); +84 } +85 +86 final URL url = new URL(rootURL, String.format("identify/sha1/%s", +87 sha1.toLowerCase())); +88 +89 LOGGER.debug("Searching Nexus url {}", url); 90 -91 final URL url = new URL(rootURL, String.format("identify/sha1/%s", -92 sha1.toLowerCase())); -93 -94 LOGGER.debug("Searching Nexus url {}", url); -95 -96 // Determine if we need to use a proxy. The rules: -97 // 1) If the proxy is set, AND the setting is set to true, use the proxy -98 // 2) Otherwise, don't use the proxy (either the proxy isn't configured, -99 // or proxy is specifically set to false -100 HttpURLConnection conn; -101 conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); -102 conn.setDoOutput(true); +91 // Determine if we need to use a proxy. The rules: +92 // 1) If the proxy is set, AND the setting is set to true, use the proxy +93 // 2) Otherwise, don't use the proxy (either the proxy isn't configured, +94 // or proxy is specifically set to false +95 HttpURLConnection conn; +96 conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); +97 conn.setDoOutput(true); +98 +99 // JSON would be more elegant, but there's not currently a dependency +100 // on JSON, so don't want to add one just for this +101 conn.addRequestProperty("Accept", "application/xml"); +102 conn.connect(); 103 -104 // JSON would be more elegant, but there's not currently a dependency -105 // on JSON, so don't want to add one just for this -106 conn.addRequestProperty("Accept", "application/xml"); -107 conn.connect(); -108 -109 if (conn.getResponseCode() == 200) { -110 try { -111 final DocumentBuilder builder = DocumentBuilderFactory -112 .newInstance().newDocumentBuilder(); -113 final Document doc = builder.parse(conn.getInputStream()); -114 final XPath xpath = XPathFactory.newInstance().newXPath(); -115 final String groupId = xpath -116 .evaluate( -117 "/org.sonatype.nexus.rest.model.NexusArtifact/groupId", -118 doc); -119 final String artifactId = xpath.evaluate( -120 "/org.sonatype.nexus.rest.model.NexusArtifact/artifactId", -121 doc); -122 final String version = xpath -123 .evaluate( -124 "/org.sonatype.nexus.rest.model.NexusArtifact/version", -125 doc); -126 final String link = xpath -127 .evaluate( -128 "/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink", -129 doc); -130 final String pomLink = xpath -131 .evaluate( -132 "/org.sonatype.nexus.rest.model.NexusArtifact/pomLink", -133 doc); -134 final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version); -135 if (link != null && !link.isEmpty()) { -136 ma.setArtifactUrl(link); -137 } -138 if (pomLink != null && !pomLink.isEmpty()) { -139 ma.setPomUrl(pomLink); -140 } -141 return ma; -142 } catch (Throwable e) { -143 // Anything else is jacked-up XML stuff that we really can't recover -144 // from well -145 throw new IOException(e.getMessage(), e); -146 } -147 } else if (conn.getResponseCode() == 404) { -148 throw new FileNotFoundException("Artifact not found in Nexus"); -149 } else { -150 LOGGER.debug("Could not connect to Nexus received response code: {} {}", -151 conn.getResponseCode(), conn.getResponseMessage()); -152 throw new IOException("Could not connect to Nexus"); -153 } -154 } -155 -156 /** -157 * Do a preflight request to see if the repository is actually working. -158 * -159 * @return whether the repository is listening and returns the /status URL correctly -160 */ -161 public boolean preflightRequest() { -162 HttpURLConnection conn; -163 try { -164 final URL url = new URL(rootURL, "status"); -165 conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); -166 conn.addRequestProperty("Accept", "application/xml"); -167 conn.connect(); -168 if (conn.getResponseCode() != 200) { -169 LOGGER.warn("Expected 200 result from Nexus, got {}", conn.getResponseCode()); -170 return false; -171 } -172 final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); -173 final Document doc = builder.parse(conn.getInputStream()); -174 if (!"status".equals(doc.getDocumentElement().getNodeName())) { -175 LOGGER.warn("Expected root node name of status, got {}", doc.getDocumentElement().getNodeName()); -176 return false; -177 } -178 } catch (Throwable e) { -179 return false; -180 } -181 -182 return true; -183 } -184 } -185 -186 // vim: cc=120:sw=4:ts=4:sts=4 +104 switch (conn.getResponseCode()) { +105 case 200: +106 try { +107 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +108 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +109 final DocumentBuilder builder = factory.newDocumentBuilder(); +110 final Document doc = builder.parse(conn.getInputStream()); +111 final XPath xpath = XPathFactory.newInstance().newXPath(); +112 final String groupId = xpath +113 .evaluate( +114 "/org.sonatype.nexus.rest.model.NexusArtifact/groupId", +115 doc); +116 final String artifactId = xpath.evaluate( +117 "/org.sonatype.nexus.rest.model.NexusArtifact/artifactId", +118 doc); +119 final String version = xpath +120 .evaluate( +121 "/org.sonatype.nexus.rest.model.NexusArtifact/version", +122 doc); +123 final String link = xpath +124 .evaluate( +125 "/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink", +126 doc); +127 final String pomLink = xpath +128 .evaluate( +129 "/org.sonatype.nexus.rest.model.NexusArtifact/pomLink", +130 doc); +131 final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version); +132 if (link != null && !link.isEmpty()) { +133 ma.setArtifactUrl(link); +134 } +135 if (pomLink != null && !pomLink.isEmpty()) { +136 ma.setPomUrl(pomLink); +137 } +138 return ma; +139 } catch (Throwable e) { +140 // Anything else is jacked-up XML stuff that we really can't recover +141 // from well +142 throw new IOException(e.getMessage(), e); +143 } +144 case 404: +145 throw new FileNotFoundException("Artifact not found in Nexus"); +146 default: +147 LOGGER.debug("Could not connect to Nexus received response code: {} {}", +148 conn.getResponseCode(), conn.getResponseMessage()); +149 throw new IOException("Could not connect to Nexus"); +150 } +151 } +152 +153 /** +154 * Do a preflight request to see if the repository is actually working. +155 * +156 * @return whether the repository is listening and returns the /status URL +157 * correctly +158 */ +159 public boolean preflightRequest() { +160 HttpURLConnection conn; +161 try { +162 final URL url = new URL(rootURL, "status"); +163 conn = URLConnectionFactory.createHttpURLConnection(url, useProxy); +164 conn.addRequestProperty("Accept", "application/xml"); +165 conn.connect(); +166 if (conn.getResponseCode() != 200) { +167 LOGGER.warn("Expected 200 result from Nexus, got {}", conn.getResponseCode()); +168 return false; +169 } +170 final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); +171 final Document doc = builder.parse(conn.getInputStream()); +172 if (!"status".equals(doc.getDocumentElement().getNodeName())) { +173 LOGGER.warn("Expected root node name of status, got {}", doc.getDocumentElement().getNodeName()); +174 return false; +175 } +176 } catch (Throwable e) { +177 return false; +178 } +179 +180 return true; +181 } +182 } +183 +184 // vim: cc=120:sw=4:ts=4:sts=4
      diff --git a/xref/org/owasp/dependencycheck/data/nexus/package-frame.html b/xref/org/owasp/dependencycheck/data/nexus/package-frame.html index eb8df971d..a8ed5b273 100644 --- a/xref/org/owasp/dependencycheck/data/nexus/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/nexus/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.nexus diff --git a/xref/org/owasp/dependencycheck/data/nexus/package-summary.html b/xref/org/owasp/dependencycheck/data/nexus/package-summary.html index 61551b25b..db70f9949 100644 --- a/xref/org/owasp/dependencycheck/data/nexus/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/nexus/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nexus + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.nexus diff --git a/xref/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.html b/xref/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.html index 6714f54b9..8dc802819 100644 --- a/xref/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.html +++ b/xref/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.html @@ -44,49 +44,53 @@ 36 * Gets the string value of a node or null if it's not present 37 * 38 * @param n the node to test -39 * @return the string content of the node, or null if the node itself is null -40 */ -41 private String getOrNull(Node n) { -42 if (n != null) { -43 return n.getTextContent(); -44 } else { -45 return null; -46 } -47 } -48 -49 /** -50 * Parse an input stream and return the resulting {@link NugetPackage}. -51 * -52 * @param stream the input stream to parse -53 * @return the populated bean -54 * @throws NuspecParseException when an exception occurs -55 */ -56 @Override -57 public NugetPackage parse(InputStream stream) throws NuspecParseException { -58 try { -59 final Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream); -60 final XPath xpath = XPathFactory.newInstance().newXPath(); -61 final NugetPackage nuspec = new NugetPackage(); -62 -63 if (xpath.evaluate("/package/metadata/id", d, XPathConstants.NODE) == null -64 || xpath.evaluate("/package/metadata/version", d, XPathConstants.NODE) == null -65 || xpath.evaluate("/package/metadata/authors", d, XPathConstants.NODE) == null -66 || xpath.evaluate("/package/metadata/description", d, XPathConstants.NODE) == null) { -67 throw new NuspecParseException("Invalid Nuspec format"); -68 } -69 -70 nuspec.setId(xpath.evaluate("/package/metadata/id", d)); -71 nuspec.setVersion(xpath.evaluate("/package/metadata/version", d)); -72 nuspec.setAuthors(xpath.evaluate("/package/metadata/authors", d)); -73 nuspec.setOwners(getOrNull((Node) xpath.evaluate("/package/metadata/owners", d, XPathConstants.NODE))); -74 nuspec.setLicenseUrl(getOrNull((Node) xpath.evaluate("/package/metadata/licenseUrl", d, XPathConstants.NODE))); -75 nuspec.setTitle(getOrNull((Node) xpath.evaluate("/package/metadata/title", d, XPathConstants.NODE))); -76 return nuspec; -77 } catch (Throwable e) { -78 throw new NuspecParseException("Unable to parse nuspec", e); -79 } -80 } -81 } +39 * @return the string content of the node, or null if the node itself is +40 * null +41 */ +42 private String getOrNull(Node n) { +43 if (n != null) { +44 return n.getTextContent(); +45 } else { +46 return null; +47 } +48 } +49 +50 /** +51 * Parse an input stream and return the resulting {@link NugetPackage}. +52 * +53 * @param stream the input stream to parse +54 * @return the populated bean +55 * @throws NuspecParseException when an exception occurs +56 */ +57 @Override +58 public NugetPackage parse(InputStream stream) throws NuspecParseException { +59 try { +60 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +61 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +62 final Document d = factory.newDocumentBuilder().parse(stream); +63 +64 final XPath xpath = XPathFactory.newInstance().newXPath(); +65 final NugetPackage nuspec = new NugetPackage(); +66 +67 if (xpath.evaluate("/package/metadata/id", d, XPathConstants.NODE) == null +68 || xpath.evaluate("/package/metadata/version", d, XPathConstants.NODE) == null +69 || xpath.evaluate("/package/metadata/authors", d, XPathConstants.NODE) == null +70 || xpath.evaluate("/package/metadata/description", d, XPathConstants.NODE) == null) { +71 throw new NuspecParseException("Invalid Nuspec format"); +72 } +73 +74 nuspec.setId(xpath.evaluate("/package/metadata/id", d)); +75 nuspec.setVersion(xpath.evaluate("/package/metadata/version", d)); +76 nuspec.setAuthors(xpath.evaluate("/package/metadata/authors", d)); +77 nuspec.setOwners(getOrNull((Node) xpath.evaluate("/package/metadata/owners", d, XPathConstants.NODE))); +78 nuspec.setLicenseUrl(getOrNull((Node) xpath.evaluate("/package/metadata/licenseUrl", d, XPathConstants.NODE))); +79 nuspec.setTitle(getOrNull((Node) xpath.evaluate("/package/metadata/title", d, XPathConstants.NODE))); +80 return nuspec; +81 } catch (Throwable e) { +82 throw new NuspecParseException("Unable to parse nuspec", e); +83 } +84 } +85 }
      diff --git a/xref/org/owasp/dependencycheck/data/nuget/package-frame.html b/xref/org/owasp/dependencycheck/data/nuget/package-frame.html index 31ebdccda..6cb44b779 100644 --- a/xref/org/owasp/dependencycheck/data/nuget/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/nuget/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/xref/org/owasp/dependencycheck/data/nuget/package-summary.html b/xref/org/owasp/dependencycheck/data/nuget/package-summary.html index eeaa8ffe1..ca36faece 100644 --- a/xref/org/owasp/dependencycheck/data/nuget/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/nuget/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nuget + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.nuget diff --git a/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html b/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html index 1d4d2db7a..acfa82354 100644 --- a/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html +++ b/xref/org/owasp/dependencycheck/data/nvdcve/CveDB.html @@ -127,7 +127,7 @@ 119 * @throws DatabaseException thrown if there is an error opening the 120 * database connection 121 */ -122 public final void open() throws DatabaseException { +122 public final synchronized void open() throws DatabaseException { 123 if (!isOpen()) { 124 conn = ConnectionFactory.getConnection(); 125 } @@ -137,7 +137,7 @@ 129 * Closes the DB4O database. Close should be called on this object when it 130 * is done being used. 131 */ -132 public void close() { +132 public synchronized void close() { 133 if (conn != null) { 134 try { 135 conn.close(); @@ -157,7 +157,7 @@ 149 * 150 * @return whether the database connection is open or closed 151 */ -152 public boolean isOpen() { +152 public synchronized boolean isOpen() { 153 return conn != null; 154 } 155 @@ -166,7 +166,7 @@ 158 * 159 * @throws SQLException thrown if a SQL Exception occurs 160 */ -161 public void commit() throws SQLException { +161 public synchronized void commit() throws SQLException { 162 //temporary remove this as autocommit is on. 163 //if (conn != null) { 164 // conn.commit(); @@ -210,7 +210,7 @@ 202 * analyzed 203 * @return a set of vulnerable software 204 */ -205 public Set<VulnerableSoftware> getCPEs(String vendor, String product) { +205 public synchronized Set<VulnerableSoftware> getCPEs(String vendor, String product) { 206 final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>(); 207 ResultSet rs = null; 208 PreparedStatement ps = null; @@ -242,7 +242,7 @@ 234 * @throws DatabaseException thrown when there is an error retrieving the 235 * data from the DB 236 */ -237 public Set<Pair<String, String>> getVendorProductList() throws DatabaseException { +237 public synchronized Set<Pair<String, String>> getVendorProductList() throws DatabaseException { 238 final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>(); 239 ResultSet rs = null; 240 PreparedStatement ps = null; @@ -267,7 +267,7 @@ 259 * 260 * @return the properties from the database 261 */ -262 Properties getProperties() { +262 synchronized Properties getProperties() { 263 final Properties prop = new Properties(); 264 PreparedStatement ps = null; 265 ResultSet rs = null; @@ -293,7 +293,7 @@ 285 * @param key the property key 286 * @param value the property value 287 */ -288 void saveProperty(String key, String value) { +288 synchronized void saveProperty(String key, String value) { 289 try { 290 try { 291 final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY")); @@ -336,7 +336,7 @@ 328 * @return a list of Vulnerabilities 329 * @throws DatabaseException thrown if there is an exception retrieving data 330 */ -331 public List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException { +331 public synchronized List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException { 332 final VulnerableSoftware cpe = new VulnerableSoftware(); 333 try { 334 cpe.parseName(cpeStr); @@ -397,7 +397,7 @@ 389 * @return a vulnerability object 390 * @throws DatabaseException if an exception occurs 391 */ -392 public Vulnerability getVulnerability(String cve) throws DatabaseException { +392 public synchronized Vulnerability getVulnerability(String cve) throws DatabaseException { 393 PreparedStatement psV = null; 394 PreparedStatement psR = null; 395 PreparedStatement psS = null; @@ -470,7 +470,7 @@ 462 * @param vuln the vulnerability to add to the database 463 * @throws DatabaseException is thrown if the database 464 */ -465 public void updateVulnerability(Vulnerability vuln) throws DatabaseException { +465 public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException { 466 PreparedStatement selectVulnerabilityId = null; 467 PreparedStatement deleteVulnerability = null; 468 PreparedStatement deleteReferences = null; @@ -646,7 +646,7 @@ 638 * 639 * @return <code>true</code> if data exists; otherwise <code>false</code> 640 */ -641 public boolean dataExists() { +641 public synchronized boolean dataExists() { 642 Statement cs = null; 643 ResultSet rs = null; 644 try { @@ -682,7 +682,7 @@ 674 * updates. This should be called after all updates have been completed to 675 * ensure orphan entries are removed. 676 */ -677 public void cleanupDatabase() { +677 public synchronized void cleanupDatabase() { 678 PreparedStatement ps = null; 679 try { 680 ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS")); @@ -820,7 +820,7 @@ 812 * 813 * Deletes unused dictionary entries from the database. 814 */ -815 public void deleteUnusedCpe() { +815 public synchronized void deleteUnusedCpe() { 816 PreparedStatement ps = null; 817 try { 818 ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE")); @@ -842,7 +842,7 @@ 834 * @param vendor the CPE vendor 835 * @param product the CPE product 836 */ -837 public void addCpe(String cpe, String vendor, String product) { +837 public synchronized void addCpe(String cpe, String vendor, String product) { 838 PreparedStatement ps = null; 839 try { 840 ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE")); diff --git a/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html b/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html index 315e84eee..a615c3222 100644 --- a/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/nvdcve/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.nvdcve diff --git a/xref/org/owasp/dependencycheck/data/nvdcve/package-summary.html b/xref/org/owasp/dependencycheck/data/nvdcve/package-summary.html index 5209749a5..c5288628e 100644 --- a/xref/org/owasp/dependencycheck/data/nvdcve/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/nvdcve/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.nvdcve + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.nvdcve diff --git a/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html b/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html index 7a0aec0a8..4551a7929 100644 --- a/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html +++ b/xref/org/owasp/dependencycheck/data/update/CpeUpdater.html @@ -52,162 +52,170 @@ 44 45 /** 46 * -47 * This class is currently unused and if enabled will likely not work on MySQL as the MERGE statement is used. -48 * -49 * The CpeUpdater is designed to download the CPE data file from NIST and import the data into the database. However, as this -50 * currently adds no beneficial data, compared to what is in the CPE data contained in the CVE data files, this class is not -51 * currently used. The code is being kept as a future update may utilize more data from the CPE xml files. -52 * -53 * @author Jeremy Long -54 */ -55 public class CpeUpdater extends BaseUpdater implements CachedWebDataSource { -56 -57 /** -58 * Static logger. -59 */ -60 private static final Logger LOGGER = LoggerFactory.getLogger(CpeUpdater.class); -61 -62 @Override -63 public void update() throws UpdateException { -64 try { -65 openDataStores(); -66 if (updateNeeded()) { -67 LOGGER.info("Updating the Common Platform Enumeration (CPE)"); -68 final File xml = downloadCpe(); -69 final List<Cpe> cpes = processXML(xml); -70 getCveDB().deleteUnusedCpe(); -71 for (Cpe cpe : cpes) { -72 getCveDB().addCpe(cpe.getValue(), cpe.getVendor(), cpe.getProduct()); -73 } -74 final long now = System.currentTimeMillis(); -75 getProperties().save(LAST_CPE_UPDATE, Long.toString(now)); -76 LOGGER.info("CPE update complete"); -77 } -78 } finally { -79 closeDataStores(); -80 } -81 } -82 -83 /** -84 * Downloads the CPE XML file. -85 * -86 * @return the file reference to the CPE.xml file -87 * @throws UpdateException thrown if there is an issue downloading the XML file -88 */ -89 private File downloadCpe() throws UpdateException { -90 File xml; -91 final URL url; -92 try { -93 url = new URL(Settings.getString(Settings.KEYS.CPE_URL)); -94 xml = File.createTempFile("cpe", ".xml", Settings.getTempDirectory()); -95 Downloader.fetchFile(url, xml); -96 if (url.toExternalForm().endsWith(".xml.gz")) { -97 extractGzip(xml); -98 } -99 -100 } catch (MalformedURLException ex) { -101 throw new UpdateException("Invalid CPE URL", ex); -102 } catch (DownloadFailedException ex) { -103 throw new UpdateException("Unable to download CPE XML file", ex); -104 } catch (IOException ex) { -105 throw new UpdateException("Unable to create temporary file to download CPE", ex); -106 } -107 return xml; -108 } -109 -110 /** -111 * Parses the CPE XML file to return a list of CPE entries. -112 * -113 * @param xml the CPE data file -114 * @return the list of CPE entries -115 * @throws UpdateException thrown if there is an issue with parsing the XML file -116 */ -117 private List<Cpe> processXML(final File xml) throws UpdateException { -118 try { -119 final SAXParserFactory factory = SAXParserFactory.newInstance(); -120 final SAXParser saxParser = factory.newSAXParser(); -121 final CPEHandler handler = new CPEHandler(); -122 saxParser.parse(xml, handler); -123 return handler.getData(); -124 } catch (ParserConfigurationException ex) { -125 throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Issue", ex); -126 } catch (SAXException ex) { -127 throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Exception", ex); -128 } catch (IOException ex) { -129 throw new UpdateException("Unable to parse CPE XML file due to IO Failure", ex); -130 } -131 } -132 -133 /** -134 * Checks to find the last time the CPE data was refreshed and if it needs to be updated. -135 * -136 * @return true if the CPE data should be refreshed -137 */ -138 private boolean updateNeeded() { -139 final long now = System.currentTimeMillis(); -140 final int days = Settings.getInt(Settings.KEYS.CPE_MODIFIED_VALID_FOR_DAYS, 30); -141 long timestamp = 0; -142 final String ts = getProperties().getProperty(LAST_CPE_UPDATE); -143 if (ts != null && ts.matches("^[0-9]+$")) { -144 timestamp = Long.parseLong(ts); -145 } -146 return !DateUtil.withinDateRange(timestamp, now, days); -147 } -148 -149 /** -150 * Extracts the file contained in a gzip archive. The extracted file is placed in the exact same path as the file specified. -151 * -152 * @param file the archive file -153 * @throws FileNotFoundException thrown if the file does not exist -154 * @throws IOException thrown if there is an error extracting the file. -155 */ -156 private void extractGzip(File file) throws FileNotFoundException, IOException { -157 //TODO - move this to a util class as it is duplicative of (copy of) code in the DownloadTask -158 final String originalPath = file.getPath(); -159 final File gzip = new File(originalPath + ".gz"); -160 if (gzip.isFile() && !gzip.delete()) { -161 LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString()); -162 gzip.deleteOnExit(); -163 } -164 if (!file.renameTo(gzip)) { -165 throw new IOException("Unable to rename '" + file.getPath() + "'"); -166 } -167 final File newfile = new File(originalPath); -168 -169 final byte[] buffer = new byte[4096]; -170 -171 GZIPInputStream cin = null; -172 FileOutputStream out = null; -173 try { -174 cin = new GZIPInputStream(new FileInputStream(gzip)); -175 out = new FileOutputStream(newfile); +47 * This class is currently unused and if enabled will likely not work on MySQL +48 * as the MERGE statement is used. +49 * +50 * The CpeUpdater is designed to download the CPE data file from NIST and import +51 * the data into the database. However, as this currently adds no beneficial +52 * data, compared to what is in the CPE data contained in the CVE data files, +53 * this class is not currently used. The code is being kept as a future update +54 * may utilize more data from the CPE XML files. +55 * +56 * @author Jeremy Long +57 */ +58 public class CpeUpdater extends BaseUpdater implements CachedWebDataSource { +59 +60 /** +61 * Static logger. +62 */ +63 private static final Logger LOGGER = LoggerFactory.getLogger(CpeUpdater.class); +64 +65 @Override +66 public void update() throws UpdateException { +67 try { +68 openDataStores(); +69 if (updateNeeded()) { +70 LOGGER.info("Updating the Common Platform Enumeration (CPE)"); +71 final File xml = downloadCpe(); +72 final List<Cpe> cpes = processXML(xml); +73 getCveDB().deleteUnusedCpe(); +74 for (Cpe cpe : cpes) { +75 getCveDB().addCpe(cpe.getValue(), cpe.getVendor(), cpe.getProduct()); +76 } +77 final long now = System.currentTimeMillis(); +78 getProperties().save(LAST_CPE_UPDATE, Long.toString(now)); +79 LOGGER.info("CPE update complete"); +80 } +81 } finally { +82 closeDataStores(); +83 } +84 } +85 +86 /** +87 * Downloads the CPE XML file. +88 * +89 * @return the file reference to the CPE.xml file +90 * @throws UpdateException thrown if there is an issue downloading the XML +91 * file +92 */ +93 private File downloadCpe() throws UpdateException { +94 File xml; +95 final URL url; +96 try { +97 url = new URL(Settings.getString(Settings.KEYS.CPE_URL)); +98 xml = File.createTempFile("cpe", ".xml", Settings.getTempDirectory()); +99 Downloader.fetchFile(url, xml); +100 if (url.toExternalForm().endsWith(".xml.gz")) { +101 extractGzip(xml); +102 } +103 +104 } catch (MalformedURLException ex) { +105 throw new UpdateException("Invalid CPE URL", ex); +106 } catch (DownloadFailedException ex) { +107 throw new UpdateException("Unable to download CPE XML file", ex); +108 } catch (IOException ex) { +109 throw new UpdateException("Unable to create temporary file to download CPE", ex); +110 } +111 return xml; +112 } +113 +114 /** +115 * Parses the CPE XML file to return a list of CPE entries. +116 * +117 * @param xml the CPE data file +118 * @return the list of CPE entries +119 * @throws UpdateException thrown if there is an issue with parsing the XML +120 * file +121 */ +122 private List<Cpe> processXML(final File xml) throws UpdateException { +123 try { +124 final SAXParserFactory factory = SAXParserFactory.newInstance(); +125 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +126 final SAXParser saxParser = factory.newSAXParser(); +127 final CPEHandler handler = new CPEHandler(); +128 saxParser.parse(xml, handler); +129 return handler.getData(); +130 } catch (ParserConfigurationException ex) { +131 throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Issue", ex); +132 } catch (SAXException ex) { +133 throw new UpdateException("Unable to parse CPE XML file due to SAX Parser Exception", ex); +134 } catch (IOException ex) { +135 throw new UpdateException("Unable to parse CPE XML file due to IO Failure", ex); +136 } +137 } +138 +139 /** +140 * Checks to find the last time the CPE data was refreshed and if it needs +141 * to be updated. +142 * +143 * @return true if the CPE data should be refreshed +144 */ +145 private boolean updateNeeded() { +146 final long now = System.currentTimeMillis(); +147 final int days = Settings.getInt(Settings.KEYS.CPE_MODIFIED_VALID_FOR_DAYS, 30); +148 long timestamp = 0; +149 final String ts = getProperties().getProperty(LAST_CPE_UPDATE); +150 if (ts != null && ts.matches("^[0-9]+$")) { +151 timestamp = Long.parseLong(ts); +152 } +153 return !DateUtil.withinDateRange(timestamp, now, days); +154 } +155 +156 /** +157 * Extracts the file contained in a gzip archive. The extracted file is +158 * placed in the exact same path as the file specified. +159 * +160 * @param file the archive file +161 * @throws FileNotFoundException thrown if the file does not exist +162 * @throws IOException thrown if there is an error extracting the file. +163 */ +164 private void extractGzip(File file) throws FileNotFoundException, IOException { +165 //TODO - move this to a util class as it is duplicative of (copy of) code in the DownloadTask +166 final String originalPath = file.getPath(); +167 final File gzip = new File(originalPath + ".gz"); +168 if (gzip.isFile() && !gzip.delete()) { +169 LOGGER.debug("Failed to delete intial temporary file {}", gzip.toString()); +170 gzip.deleteOnExit(); +171 } +172 if (!file.renameTo(gzip)) { +173 throw new IOException("Unable to rename '" + file.getPath() + "'"); +174 } +175 final File newfile = new File(originalPath); 176 -177 int len; -178 while ((len = cin.read(buffer)) > 0) { -179 out.write(buffer, 0, len); -180 } -181 } finally { -182 if (cin != null) { -183 try { -184 cin.close(); -185 } catch (IOException ex) { -186 LOGGER.trace("ignore", ex); -187 } +177 final byte[] buffer = new byte[4096]; +178 +179 GZIPInputStream cin = null; +180 FileOutputStream out = null; +181 try { +182 cin = new GZIPInputStream(new FileInputStream(gzip)); +183 out = new FileOutputStream(newfile); +184 +185 int len; +186 while ((len = cin.read(buffer)) > 0) { +187 out.write(buffer, 0, len); 188 } -189 if (out != null) { -190 try { -191 out.close(); -192 } catch (IOException ex) { -193 LOGGER.trace("ignore", ex); -194 } -195 } -196 if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) { -197 LOGGER.debug("Failed to delete temporary file {}", gzip.toString()); -198 gzip.deleteOnExit(); -199 } -200 } -201 } -202 } +189 } finally { +190 if (cin != null) { +191 try { +192 cin.close(); +193 } catch (IOException ex) { +194 LOGGER.trace("ignore", ex); +195 } +196 } +197 if (out != null) { +198 try { +199 out.close(); +200 } catch (IOException ex) { +201 LOGGER.trace("ignore", ex); +202 } +203 } +204 if (gzip.isFile() && !FileUtils.deleteQuietly(gzip)) { +205 LOGGER.debug("Failed to delete temporary file {}", gzip.toString()); +206 gzip.deleteOnExit(); +207 } +208 } +209 } +210 }
      diff --git a/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html b/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html index 1edd3a333..e5e5eaa97 100644 --- a/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html +++ b/xref/org/owasp/dependencycheck/data/update/EngineVersionCheck.html @@ -126,7 +126,7 @@ 118 } 119 } catch (DatabaseException ex) { 120 LOGGER.debug("Database Exception opening databases to retrieve properties", ex); -121 throw new UpdateException("Error occured updating database properties."); +121 throw new UpdateException("Error occurred updating database properties."); 122 } catch (InvalidSettingException ex) { 123 LOGGER.debug("Unable to determine if autoupdate is enabled", ex); 124 } finally { diff --git a/xref/org/owasp/dependencycheck/data/update/cpe/package-frame.html b/xref/org/owasp/dependencycheck/data/update/cpe/package-frame.html index 5bb3cbe38..2c1bf273b 100644 --- a/xref/org/owasp/dependencycheck/data/update/cpe/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/update/cpe/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update.cpe + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.update.cpe diff --git a/xref/org/owasp/dependencycheck/data/update/cpe/package-summary.html b/xref/org/owasp/dependencycheck/data/update/cpe/package-summary.html index db77799fa..bd9778bfd 100644 --- a/xref/org/owasp/dependencycheck/data/update/cpe/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/update/cpe/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update.cpe + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.update.cpe diff --git a/xref/org/owasp/dependencycheck/data/update/exception/package-frame.html b/xref/org/owasp/dependencycheck/data/update/exception/package-frame.html index b2abb9cfa..cab90add7 100644 --- a/xref/org/owasp/dependencycheck/data/update/exception/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/update/exception/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update.exception + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.update.exception diff --git a/xref/org/owasp/dependencycheck/data/update/exception/package-summary.html b/xref/org/owasp/dependencycheck/data/update/exception/package-summary.html index a74f48053..a5d5e0425 100644 --- a/xref/org/owasp/dependencycheck/data/update/exception/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/update/exception/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update.exception + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.update.exception diff --git a/xref/org/owasp/dependencycheck/data/update/nvd/ProcessTask.html b/xref/org/owasp/dependencycheck/data/update/nvd/ProcessTask.html index 20cccb9a5..5f722217a 100644 --- a/xref/org/owasp/dependencycheck/data/update/nvd/ProcessTask.html +++ b/xref/org/owasp/dependencycheck/data/update/nvd/ProcessTask.html @@ -46,151 +46,158 @@ 38 import org.xml.sax.SAXException; 39 40 /** -41 * A callable task that will process a given set of NVD CVE xml files and update the Cve Database accordingly. -42 * -43 * @author Jeremy Long -44 */ -45 public class ProcessTask implements Callable<ProcessTask> { -46 -47 /** -48 * The logger. -49 */ -50 private static final Logger LOGGER = LoggerFactory.getLogger(ProcessTask.class); -51 /** -52 * A field to store any update exceptions that occur during the "call". -53 */ -54 private UpdateException exception = null; -55 -56 /** -57 * Get the value of exception. -58 * -59 * @return the value of exception -60 */ -61 public UpdateException getException() { -62 return exception; -63 } -64 -65 /** -66 * Set the value of exception. -67 * -68 * @param exception new value of exception -69 */ -70 public void setException(UpdateException exception) { -71 this.exception = exception; -72 } -73 /** -74 * A reference to the CveDB. -75 */ -76 private final CveDB cveDB; -77 /** -78 * A reference to the callable download task. -79 */ -80 private final DownloadTask filePair; -81 /** -82 * A reference to the properties. -83 */ -84 private final DatabaseProperties properties; -85 /** -86 * A reference to the global settings object. -87 */ -88 private final Settings settings; -89 -90 /** -91 * Constructs a new ProcessTask used to process an NVD CVE update. -92 * -93 * @param cveDB the data store object -94 * @param filePair the download task that contains the URL references to download -95 * @param settings a reference to the global settings object; this is necessary so that when the thread is started the -96 * dependencies have a correct reference to the global settings. -97 */ -98 public ProcessTask(final CveDB cveDB, final DownloadTask filePair, Settings settings) { -99 this.cveDB = cveDB; -100 this.filePair = filePair; -101 this.properties = cveDB.getDatabaseProperties(); -102 this.settings = settings; -103 } -104 -105 /** -106 * Implements the callable interface. -107 * -108 * @return this object -109 * @throws Exception thrown if there is an exception; note that any UpdateExceptions are simply added to the tasks exception -110 * collection -111 */ -112 @Override -113 public ProcessTask call() throws Exception { -114 try { -115 Settings.setInstance(settings); -116 processFiles(); -117 } catch (UpdateException ex) { -118 this.exception = ex; -119 } finally { -120 Settings.cleanup(false); -121 } -122 return this; -123 } -124 -125 /** -126 * Imports the NVD CVE XML File into the Lucene Index. -127 * -128 * @param file the file containing the NVD CVE XML -129 * @param oldVersion contains the file containing the NVD CVE XML 1.2 -130 * @throws ParserConfigurationException is thrown if there is a parser configuration exception -131 * @throws SAXException is thrown if there is a SAXException -132 * @throws IOException is thrown if there is a IO Exception -133 * @throws SQLException is thrown if there is a SQL exception -134 * @throws DatabaseException is thrown if there is a database exception -135 * @throws ClassNotFoundException thrown if the h2 database driver cannot be loaded -136 */ -137 protected void importXML(File file, File oldVersion) throws ParserConfigurationException, -138 SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException { -139 -140 final SAXParserFactory factory = SAXParserFactory.newInstance(); -141 final SAXParser saxParser = factory.newSAXParser(); -142 -143 final NvdCve12Handler cve12Handler = new NvdCve12Handler(); -144 saxParser.parse(oldVersion, cve12Handler); -145 final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities(); -146 -147 final NvdCve20Handler cve20Handler = new NvdCve20Handler(); -148 cve20Handler.setCveDB(cveDB); -149 cve20Handler.setPrevVersionVulnMap(prevVersionVulnMap); -150 saxParser.parse(file, cve20Handler); -151 } +41 * A callable task that will process a given set of NVD CVE xml files and update +42 * the Cve Database accordingly. +43 * +44 * @author Jeremy Long +45 */ +46 public class ProcessTask implements Callable<ProcessTask> { +47 +48 /** +49 * The logger. +50 */ +51 private static final Logger LOGGER = LoggerFactory.getLogger(ProcessTask.class); +52 /** +53 * A field to store any update exceptions that occur during the "call". +54 */ +55 private UpdateException exception = null; +56 +57 /** +58 * Get the value of exception. +59 * +60 * @return the value of exception +61 */ +62 public UpdateException getException() { +63 return exception; +64 } +65 +66 /** +67 * Set the value of exception. +68 * +69 * @param exception new value of exception +70 */ +71 public void setException(UpdateException exception) { +72 this.exception = exception; +73 } +74 /** +75 * A reference to the CveDB. +76 */ +77 private final CveDB cveDB; +78 /** +79 * A reference to the callable download task. +80 */ +81 private final DownloadTask filePair; +82 /** +83 * A reference to the properties. +84 */ +85 private final DatabaseProperties properties; +86 /** +87 * A reference to the global settings object. +88 */ +89 private final Settings settings; +90 +91 /** +92 * Constructs a new ProcessTask used to process an NVD CVE update. +93 * +94 * @param cveDB the data store object +95 * @param filePair the download task that contains the URL references to +96 * download +97 * @param settings a reference to the global settings object; this is +98 * necessary so that when the thread is started the dependencies have a +99 * correct reference to the global settings. +100 */ +101 public ProcessTask(final CveDB cveDB, final DownloadTask filePair, Settings settings) { +102 this.cveDB = cveDB; +103 this.filePair = filePair; +104 this.properties = cveDB.getDatabaseProperties(); +105 this.settings = settings; +106 } +107 +108 /** +109 * Implements the callable interface. +110 * +111 * @return this object +112 * @throws Exception thrown if there is an exception; note that any +113 * UpdateExceptions are simply added to the tasks exception collection +114 */ +115 @Override +116 public ProcessTask call() throws Exception { +117 try { +118 Settings.setInstance(settings); +119 processFiles(); +120 } catch (UpdateException ex) { +121 this.exception = ex; +122 } finally { +123 Settings.cleanup(false); +124 } +125 return this; +126 } +127 +128 /** +129 * Imports the NVD CVE XML File into the Lucene Index. +130 * +131 * @param file the file containing the NVD CVE XML +132 * @param oldVersion contains the file containing the NVD CVE XML 1.2 +133 * @throws ParserConfigurationException is thrown if there is a parser +134 * configuration exception +135 * @throws SAXException is thrown if there is a SAXException +136 * @throws IOException is thrown if there is a IO Exception +137 * @throws SQLException is thrown if there is a SQL exception +138 * @throws DatabaseException is thrown if there is a database exception +139 * @throws ClassNotFoundException thrown if the h2 database driver cannot be +140 * loaded +141 */ +142 protected void importXML(File file, File oldVersion) throws ParserConfigurationException, +143 SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException { +144 +145 final SAXParserFactory factory = SAXParserFactory.newInstance(); +146 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +147 final SAXParser saxParser = factory.newSAXParser(); +148 +149 final NvdCve12Handler cve12Handler = new NvdCve12Handler(); +150 saxParser.parse(oldVersion, cve12Handler); +151 final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities(); 152 -153 /** -154 * Processes the NVD CVE XML file and imports the data into the DB. -155 * -156 * @throws UpdateException thrown if there is an error loading the data into the database -157 */ -158 private void processFiles() throws UpdateException { -159 LOGGER.info("Processing Started for NVD CVE - {}", filePair.getNvdCveInfo().getId()); -160 final long startProcessing = System.currentTimeMillis(); -161 try { -162 importXML(filePair.getFirst(), filePair.getSecond()); -163 cveDB.commit(); -164 properties.save(filePair.getNvdCveInfo()); -165 } catch (FileNotFoundException ex) { -166 throw new UpdateException(ex); -167 } catch (ParserConfigurationException ex) { -168 throw new UpdateException(ex); -169 } catch (SAXException ex) { -170 throw new UpdateException(ex); -171 } catch (IOException ex) { -172 throw new UpdateException(ex); -173 } catch (SQLException ex) { -174 throw new UpdateException(ex); -175 } catch (DatabaseException ex) { -176 throw new UpdateException(ex); -177 } catch (ClassNotFoundException ex) { -178 throw new UpdateException(ex); -179 } finally { -180 filePair.cleanup(); -181 } -182 LOGGER.info("Processing Complete for NVD CVE - {} ({} ms)", filePair.getNvdCveInfo().getId(), -183 System.currentTimeMillis() - startProcessing); -184 } -185 } +153 final NvdCve20Handler cve20Handler = new NvdCve20Handler(); +154 cve20Handler.setCveDB(cveDB); +155 cve20Handler.setPrevVersionVulnMap(prevVersionVulnMap); +156 saxParser.parse(file, cve20Handler); +157 } +158 +159 /** +160 * Processes the NVD CVE XML file and imports the data into the DB. +161 * +162 * @throws UpdateException thrown if there is an error loading the data into +163 * the database +164 */ +165 private void processFiles() throws UpdateException { +166 LOGGER.info("Processing Started for NVD CVE - {}", filePair.getNvdCveInfo().getId()); +167 final long startProcessing = System.currentTimeMillis(); +168 try { +169 importXML(filePair.getFirst(), filePair.getSecond()); +170 cveDB.commit(); +171 properties.save(filePair.getNvdCveInfo()); +172 } catch (FileNotFoundException ex) { +173 throw new UpdateException(ex); +174 } catch (ParserConfigurationException ex) { +175 throw new UpdateException(ex); +176 } catch (SAXException ex) { +177 throw new UpdateException(ex); +178 } catch (IOException ex) { +179 throw new UpdateException(ex); +180 } catch (SQLException ex) { +181 throw new UpdateException(ex); +182 } catch (DatabaseException ex) { +183 throw new UpdateException(ex); +184 } catch (ClassNotFoundException ex) { +185 throw new UpdateException(ex); +186 } finally { +187 filePair.cleanup(); +188 } +189 LOGGER.info("Processing Complete for NVD CVE - {} ({} ms)", filePair.getNvdCveInfo().getId(), +190 System.currentTimeMillis() - startProcessing); +191 } +192 }
      diff --git a/xref/org/owasp/dependencycheck/data/update/nvd/package-frame.html b/xref/org/owasp/dependencycheck/data/update/nvd/package-frame.html index 90134865e..28fbaf4d9 100644 --- a/xref/org/owasp/dependencycheck/data/update/nvd/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/update/nvd/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.update.nvd diff --git a/xref/org/owasp/dependencycheck/data/update/nvd/package-summary.html b/xref/org/owasp/dependencycheck/data/update/nvd/package-summary.html index ef04d5911..00700193a 100644 --- a/xref/org/owasp/dependencycheck/data/update/nvd/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/update/nvd/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update.nvd + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.update.nvd diff --git a/xref/org/owasp/dependencycheck/data/update/package-frame.html b/xref/org/owasp/dependencycheck/data/update/package-frame.html index c77fe7898..bedd6f8d7 100644 --- a/xref/org/owasp/dependencycheck/data/update/package-frame.html +++ b/xref/org/owasp/dependencycheck/data/update/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.update diff --git a/xref/org/owasp/dependencycheck/data/update/package-summary.html b/xref/org/owasp/dependencycheck/data/update/package-summary.html index 285a903d6..4f23f1e36 100644 --- a/xref/org/owasp/dependencycheck/data/update/package-summary.html +++ b/xref/org/owasp/dependencycheck/data/update/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.data.update + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.data.update diff --git a/xref/org/owasp/dependencycheck/dependency/Evidence.html b/xref/org/owasp/dependencycheck/dependency/Evidence.html index 6607886c1..e4a87d8dd 100644 --- a/xref/org/owasp/dependencycheck/dependency/Evidence.html +++ b/xref/org/owasp/dependencycheck/dependency/Evidence.html @@ -61,9 +61,9 @@ 53 /** 54 * Creates a new Evidence objects. 55 * -56 * @param source the source of the evidence. -57 * @param name the name of the evidence. -58 * @param value the value of the evidence. +56 * @param source the source of the evidence. +57 * @param name the name of the evidence. +58 * @param value the value of the evidence. 59 * @param confidence the confidence of the evidence. 60 */ 61 public Evidence(String source, String name, String value, Confidence confidence) { @@ -135,167 +135,176 @@ 127 } 128 129 /** -130 * Get the value of value. If setUsed is set to false this call to get will not mark the evidence as used. -131 * -132 * @param setUsed whether or not this call to getValue should cause the used flag to be updated -133 * @return the value of value -134 */ -135 public String getValue(Boolean setUsed) { -136 used = used || setUsed; -137 return value; -138 } -139 -140 /** -141 * Set the value of value. -142 * -143 * @param value new value of value -144 */ -145 public void setValue(String value) { -146 this.value = value; -147 } -148 -149 /** -150 * A value indicating if the Evidence has been "used" (aka read). -151 */ -152 private boolean used; -153 -154 /** -155 * Get the value of used. -156 * -157 * @return the value of used -158 */ -159 public boolean isUsed() { -160 return used; -161 } -162 -163 /** -164 * Set the value of used. -165 * -166 * @param used new value of used -167 */ -168 public void setUsed(boolean used) { -169 this.used = used; -170 } -171 -172 /** -173 * The confidence level for the evidence. -174 */ -175 private Confidence confidence; -176 -177 /** -178 * Get the value of confidence. -179 * -180 * @return the value of confidence -181 */ -182 public Confidence getConfidence() { -183 return confidence; -184 } -185 -186 /** -187 * Set the value of confidence. -188 * -189 * @param confidence new value of confidence -190 */ -191 public void setConfidence(Confidence confidence) { -192 this.confidence = confidence; -193 } -194 -195 /** -196 * Implements the hashCode for Evidence. -197 * -198 * @return hash code. -199 */ -200 @Override -201 public int hashCode() { -202 return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER) -203 .append(StringUtils.lowerCase(name)) -204 .append(StringUtils.lowerCase(source)) -205 .append(StringUtils.lowerCase(value)) -206 .append(confidence) -207 .toHashCode(); -208 } -209 -210 /** -211 * Implements equals for Evidence. -212 * -213 * @param that an object to check the equality of. -214 * @return whether the two objects are equal. -215 */ -216 @Override -217 public boolean equals(Object that) { -218 if (this == that) { -219 return true; -220 } -221 if (!(that instanceof Evidence)) { -222 return false; +130 * Get the value of value. If setUsed is set to false this call to get will +131 * not mark the evidence as used. +132 * +133 * @param setUsed whether or not this call to getValue should cause the used +134 * flag to be updated +135 * @return the value of value +136 */ +137 public String getValue(Boolean setUsed) { +138 used = used || setUsed; +139 return value; +140 } +141 +142 /** +143 * Set the value of value. +144 * +145 * @param value new value of value +146 */ +147 public void setValue(String value) { +148 this.value = value; +149 } +150 +151 /** +152 * A value indicating if the Evidence has been "used" (aka read). +153 */ +154 private boolean used; +155 +156 /** +157 * Get the value of used. +158 * +159 * @return the value of used +160 */ +161 public boolean isUsed() { +162 return used; +163 } +164 +165 /** +166 * Set the value of used. +167 * +168 * @param used new value of used +169 */ +170 public void setUsed(boolean used) { +171 this.used = used; +172 } +173 +174 /** +175 * The confidence level for the evidence. +176 */ +177 private Confidence confidence; +178 +179 /** +180 * Get the value of confidence. +181 * +182 * @return the value of confidence +183 */ +184 public Confidence getConfidence() { +185 return confidence; +186 } +187 +188 /** +189 * Set the value of confidence. +190 * +191 * @param confidence new value of confidence +192 */ +193 public void setConfidence(Confidence confidence) { +194 this.confidence = confidence; +195 } +196 +197 /** +198 * Implements the hashCode for Evidence. +199 * +200 * @return hash code. +201 */ +202 @Override +203 public int hashCode() { +204 return new HashCodeBuilder(MAGIC_HASH_INIT_VALUE, MAGIC_HASH_MULTIPLIER) +205 .append(StringUtils.lowerCase(name)) +206 .append(StringUtils.lowerCase(source)) +207 .append(StringUtils.lowerCase(value)) +208 .append(confidence) +209 .toHashCode(); +210 } +211 +212 /** +213 * Implements equals for Evidence. +214 * +215 * @param that an object to check the equality of. +216 * @return whether the two objects are equal. +217 */ +218 @SuppressWarnings("deprecation") +219 @Override +220 public boolean equals(Object that) { +221 if (this == that) { +222 return true; 223 } -224 final Evidence e = (Evidence) that; -225 -226 return StringUtils.equalsIgnoreCase(name, e.name) -227 && StringUtils.equalsIgnoreCase(source, e.source) -228 && StringUtils.equalsIgnoreCase(value, e.value) -229 && ObjectUtils.equals(confidence, e.confidence); -230 } -231 -232 /** -233 * Implementation of the comparable interface. -234 * -235 * @param o the evidence being compared -236 * @return an integer indicating the ordering of the two objects -237 */ -238 @Override -239 public int compareTo(Evidence o) { -240 if (o == null) { -241 return 1; -242 } -243 if (StringUtils.equalsIgnoreCase(source, o.source)) { -244 if (StringUtils.equalsIgnoreCase(name, o.name)) { -245 if (StringUtils.equalsIgnoreCase(value, o.value)) { -246 if (ObjectUtils.equals(confidence, o.confidence)) { -247 return 0; //they are equal -248 } else { -249 return ObjectUtils.compare(confidence, o.confidence); -250 } -251 } else { -252 return compareToIgnoreCaseWithNullCheck(value, o.value); -253 } -254 } else { -255 return compareToIgnoreCaseWithNullCheck(name, o.name); -256 } -257 } else { -258 return compareToIgnoreCaseWithNullCheck(source, o.source); -259 } -260 } -261 -262 /** -263 * Wrapper around {@link java.lang.String#compareToIgnoreCase(java.lang.String) String.compareToIgnoreCase} with an -264 * exhaustive, possibly duplicative, check against nulls. -265 * -266 * @param me the value to be compared -267 * @param other the other value to be compared -268 * @return true if the values are equal; otherwise false -269 */ -270 private int compareToIgnoreCaseWithNullCheck(String me, String other) { -271 if (me == null && other == null) { -272 return 0; -273 } else if (me == null) { -274 return -1; //the other string is greater then me -275 } else if (other == null) { -276 return 1; //me is greater then the other string -277 } -278 return me.compareToIgnoreCase(other); -279 } -280 -281 /** -282 * Standard toString() implementation. -283 * -284 * @return the string representation of the object -285 */ -286 @Override -287 public String toString() { -288 return "Evidence{" + "name=" + name + ", source=" + source + ", value=" + value + ", confidence=" + confidence + '}'; -289 } -290 } +224 if (!(that instanceof Evidence)) { +225 return false; +226 } +227 final Evidence e = (Evidence) that; +228 +229 //TODO the call to ObjectUtils.equals needs to be replaced when we +230 //stop supporting Jenkins 1.6 requirement. +231 return StringUtils.equalsIgnoreCase(name, e.name) +232 && StringUtils.equalsIgnoreCase(source, e.source) +233 && StringUtils.equalsIgnoreCase(value, e.value) +234 && ObjectUtils.equals(confidence, e.confidence); +235 } +236 +237 /** +238 * Implementation of the comparable interface. +239 * +240 * @param o the evidence being compared +241 * @return an integer indicating the ordering of the two objects +242 */ +243 @SuppressWarnings("deprecation") +244 @Override +245 public int compareTo(Evidence o) { +246 if (o == null) { +247 return 1; +248 } +249 if (StringUtils.equalsIgnoreCase(source, o.source)) { +250 if (StringUtils.equalsIgnoreCase(name, o.name)) { +251 if (StringUtils.equalsIgnoreCase(value, o.value)) { +252 //TODO the call to ObjectUtils.equals needs to be replaced when we +253 //stop supporting Jenkins 1.6 requirement. +254 if (ObjectUtils.equals(confidence, o.confidence)) { +255 return 0; //they are equal +256 } else { +257 return ObjectUtils.compare(confidence, o.confidence); +258 } +259 } else { +260 return compareToIgnoreCaseWithNullCheck(value, o.value); +261 } +262 } else { +263 return compareToIgnoreCaseWithNullCheck(name, o.name); +264 } +265 } else { +266 return compareToIgnoreCaseWithNullCheck(source, o.source); +267 } +268 } +269 +270 /** +271 * Wrapper around +272 * {@link java.lang.String#compareToIgnoreCase(java.lang.String) String.compareToIgnoreCase} +273 * with an exhaustive, possibly duplicative, check against nulls. +274 * +275 * @param me the value to be compared +276 * @param other the other value to be compared +277 * @return true if the values are equal; otherwise false +278 */ +279 private int compareToIgnoreCaseWithNullCheck(String me, String other) { +280 if (me == null && other == null) { +281 return 0; +282 } else if (me == null) { +283 return -1; //the other string is greater then me +284 } else if (other == null) { +285 return 1; //me is greater then the other string +286 } +287 return me.compareToIgnoreCase(other); +288 } +289 +290 /** +291 * Standard toString() implementation. +292 * +293 * @return the string representation of the object +294 */ +295 @Override +296 public String toString() { +297 return "Evidence{" + "name=" + name + ", source=" + source + ", value=" + value + ", confidence=" + confidence + '}'; +298 } +299 }
      diff --git a/xref/org/owasp/dependencycheck/dependency/package-frame.html b/xref/org/owasp/dependencycheck/dependency/package-frame.html index 8e5806dd8..c59632e44 100644 --- a/xref/org/owasp/dependencycheck/dependency/package-frame.html +++ b/xref/org/owasp/dependencycheck/dependency/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.dependency diff --git a/xref/org/owasp/dependencycheck/dependency/package-summary.html b/xref/org/owasp/dependencycheck/dependency/package-summary.html index 7a87e079c..cec0360e3 100644 --- a/xref/org/owasp/dependencycheck/dependency/package-summary.html +++ b/xref/org/owasp/dependencycheck/dependency/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.dependency + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.dependency diff --git a/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html b/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html index 05272f763..73e0ed175 100644 --- a/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html +++ b/xref/org/owasp/dependencycheck/exception/ExceptionCollection.html @@ -33,7 +33,7 @@ 25 /** 26 * A collection of several exceptions. 27 * -28 * @author Jeremy Lomg +28 * @author Jeremy Long 29 */ 30 public class ExceptionCollection extends Exception { 31 @@ -62,7 +62,7 @@ 54 * Instantiates a new exception collection. 55 * 56 * @param exceptions a list of exceptions -57 * @param fatal indicates if the exception that occurred is fatal - meaning +57 * @param fatal indicates if any of the exceptions that occurred is fatal - meaning 58 * that no analysis was performed. 59 */ 60 public ExceptionCollection(List<Throwable> exceptions, boolean fatal) { @@ -76,7 +76,7 @@ 68 * 69 * @param msg the exception message 70 * @param exceptions a list of exceptions -71 * @param fatal indicates if the exception that occurred is fatal - meaning +71 * @param fatal indicates if any of the exceptions that occurred is fatal - meaning 72 * that no analysis was performed. 73 */ 74 public ExceptionCollection(String msg, List<Throwable> exceptions, boolean fatal) { @@ -189,7 +189,7 @@ 181 */ 182 @Override 183 public void printStackTrace(PrintWriter s) { -184 s.println("Multiple Exceptions Occured"); +184 s.println("Multiple Exceptions Occurred"); 185 super.printStackTrace(s); 186 for (Throwable t : this.exceptions) { 187 s.println("Next Exception:"); @@ -223,7 +223,7 @@ 215 final StringBuilder sb = new StringBuilder(); 216 final String msg = super.getMessage(); 217 if (msg == null || msg.isEmpty()) { -218 sb.append("One or more exceptions occured during analysis:"); +218 sb.append("One or more exceptions occurred during analysis:"); 219 } else { 220 sb.append(msg); 221 } diff --git a/xref/org/owasp/dependencycheck/exception/package-frame.html b/xref/org/owasp/dependencycheck/exception/package-frame.html index d87498521..2444d7491 100644 --- a/xref/org/owasp/dependencycheck/exception/package-frame.html +++ b/xref/org/owasp/dependencycheck/exception/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.exception + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.exception diff --git a/xref/org/owasp/dependencycheck/exception/package-summary.html b/xref/org/owasp/dependencycheck/exception/package-summary.html index 536cc0052..9625978a3 100644 --- a/xref/org/owasp/dependencycheck/exception/package-summary.html +++ b/xref/org/owasp/dependencycheck/exception/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.exception + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.exception diff --git a/xref/org/owasp/dependencycheck/maven/AggregateMojo.html b/xref/org/owasp/dependencycheck/maven/AggregateMojo.html index 6939c508a..0588b910e 100644 --- a/xref/org/owasp/dependencycheck/maven/AggregateMojo.html +++ b/xref/org/owasp/dependencycheck/maven/AggregateMojo.html @@ -131,9 +131,9 @@ 123 exCol.addException(ex); 124 } 125 if (this.isFailOnError()) { -126 throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); +126 throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol); 127 } else { -128 getLog().debug("One or more exceptions occured during dependency-check analysis", exCol); +128 getLog().debug("One or more exceptions occurred during dependency-check analysis", exCol); 129 } 130 } 131 showSummary(this.getProject(), engine.getDependencies()); @@ -248,7 +248,7 @@ 240 if (getLog().isDebugEnabled()) { 241 getLog().debug("Database connection error", ex); 242 } -243 final String msg = "An exception occured connecting to the local database. Please see the log file for more details."; +243 final String msg = "An exception occurred connecting to the local database. Please see the log file for more details."; 244 if (this.isFailOnError()) { 245 throw new MojoExecutionException(msg, ex); 246 } diff --git a/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html b/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html index a8d9cb601..7fa7f4b90 100644 --- a/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html +++ b/xref/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.html @@ -214,1058 +214,1066 @@ 206 */ 207 @Parameter(property = "suppressionFile", defaultValue = "", required = false) 208 private String suppressionFile; -209 /** -210 * Flag indicating whether or not to show a summary in the output. -211 */ -212 @SuppressWarnings("CanBeFinal") -213 @Parameter(property = "showSummary", defaultValue = "true", required = false) -214 private boolean showSummary = true; +209 +210 /** +211 * The path to the hints file. +212 */ +213 @Parameter(property = "hintsFile", defaultValue = "", required = false) +214 private String hintsFile; 215 216 /** -217 * Whether or not the Jar Analyzer is enabled. +217 * Flag indicating whether or not to show a summary in the output. 218 */ -219 @Parameter(property = "jarAnalyzerEnabled", required = false) -220 private Boolean jarAnalyzerEnabled; -221 -222 /** -223 * Whether or not the Archive Analyzer is enabled. -224 */ -225 @Parameter(property = "archiveAnalyzerEnabled", required = false) -226 private Boolean archiveAnalyzerEnabled; -227 -228 /** -229 * Sets whether the Python Distribution Analyzer will be used. -230 */ -231 @Parameter(property = "pyDistributionAnalyzerEnabled", required = false) -232 private Boolean pyDistributionAnalyzerEnabled; -233 /** -234 * Sets whether the Python Package Analyzer will be used. -235 */ -236 @Parameter(property = "pyPackageAnalyzerEnabled", required = false) -237 private Boolean pyPackageAnalyzerEnabled; -238 /** -239 * Sets whether the Ruby Gemspec Analyzer will be used. -240 */ -241 @Parameter(property = "rubygemsAnalyzerEnabled", required = false) -242 private Boolean rubygemsAnalyzerEnabled; -243 /** -244 * Sets whether or not the openssl Analyzer should be used. -245 */ -246 @Parameter(property = "opensslAnalyzerEnabled", required = false) -247 private Boolean opensslAnalyzerEnabled; -248 /** -249 * Sets whether or not the CMake Analyzer should be used. -250 */ -251 @Parameter(property = "cmakeAnalyzerEnabled", required = false) -252 private Boolean cmakeAnalyzerEnabled; -253 /** -254 * Sets whether or not the autoconf Analyzer should be used. -255 */ -256 @Parameter(property = "autoconfAnalyzerEnabled", required = false) -257 private Boolean autoconfAnalyzerEnabled; -258 /** -259 * Sets whether or not the PHP Composer Lock File Analyzer should be used. -260 */ -261 @Parameter(property = "composerAnalyzerEnabled", required = false) -262 private Boolean composerAnalyzerEnabled; -263 /** -264 * Sets whether or not the Node.js Analyzer should be used. -265 */ -266 @Parameter(property = "nodeAnalyzerEnabled", required = false) -267 private Boolean nodeAnalyzerEnabled; -268 -269 /** -270 * Whether or not the .NET Assembly Analyzer is enabled. -271 */ -272 @Parameter(property = "assemblyAnalyzerEnabled", required = false) -273 private Boolean assemblyAnalyzerEnabled; -274 -275 /** -276 * Whether or not the .NET Nuspec Analyzer is enabled. -277 */ -278 @Parameter(property = "nuspecAnalyzerEnabled", required = false) -279 private Boolean nuspecAnalyzerEnabled; -280 -281 /** -282 * Whether or not the Central Analyzer is enabled. -283 */ -284 @Parameter(property = "centralAnalyzerEnabled", required = false) -285 private Boolean centralAnalyzerEnabled; -286 -287 /** -288 * Whether or not the Nexus Analyzer is enabled. -289 */ -290 @Parameter(property = "nexusAnalyzerEnabled", required = false) -291 private Boolean nexusAnalyzerEnabled; -292 -293 /** -294 * The URL of a Nexus server's REST API end point -295 * (http://domain/nexus/service/local). +219 @SuppressWarnings("CanBeFinal") +220 @Parameter(property = "showSummary", defaultValue = "true", required = false) +221 private boolean showSummary = true; +222 +223 /** +224 * Whether or not the Jar Analyzer is enabled. +225 */ +226 @Parameter(property = "jarAnalyzerEnabled", required = false) +227 private Boolean jarAnalyzerEnabled; +228 +229 /** +230 * Whether or not the Archive Analyzer is enabled. +231 */ +232 @Parameter(property = "archiveAnalyzerEnabled", required = false) +233 private Boolean archiveAnalyzerEnabled; +234 +235 /** +236 * Sets whether the Python Distribution Analyzer will be used. +237 */ +238 @Parameter(property = "pyDistributionAnalyzerEnabled", required = false) +239 private Boolean pyDistributionAnalyzerEnabled; +240 /** +241 * Sets whether the Python Package Analyzer will be used. +242 */ +243 @Parameter(property = "pyPackageAnalyzerEnabled", required = false) +244 private Boolean pyPackageAnalyzerEnabled; +245 /** +246 * Sets whether the Ruby Gemspec Analyzer will be used. +247 */ +248 @Parameter(property = "rubygemsAnalyzerEnabled", required = false) +249 private Boolean rubygemsAnalyzerEnabled; +250 /** +251 * Sets whether or not the openssl Analyzer should be used. +252 */ +253 @Parameter(property = "opensslAnalyzerEnabled", required = false) +254 private Boolean opensslAnalyzerEnabled; +255 /** +256 * Sets whether or not the CMake Analyzer should be used. +257 */ +258 @Parameter(property = "cmakeAnalyzerEnabled", required = false) +259 private Boolean cmakeAnalyzerEnabled; +260 /** +261 * Sets whether or not the autoconf Analyzer should be used. +262 */ +263 @Parameter(property = "autoconfAnalyzerEnabled", required = false) +264 private Boolean autoconfAnalyzerEnabled; +265 /** +266 * Sets whether or not the PHP Composer Lock File Analyzer should be used. +267 */ +268 @Parameter(property = "composerAnalyzerEnabled", required = false) +269 private Boolean composerAnalyzerEnabled; +270 /** +271 * Sets whether or not the Node.js Analyzer should be used. +272 */ +273 @Parameter(property = "nodeAnalyzerEnabled", required = false) +274 private Boolean nodeAnalyzerEnabled; +275 +276 /** +277 * Whether or not the .NET Assembly Analyzer is enabled. +278 */ +279 @Parameter(property = "assemblyAnalyzerEnabled", required = false) +280 private Boolean assemblyAnalyzerEnabled; +281 +282 /** +283 * Whether or not the .NET Nuspec Analyzer is enabled. +284 */ +285 @Parameter(property = "nuspecAnalyzerEnabled", required = false) +286 private Boolean nuspecAnalyzerEnabled; +287 +288 /** +289 * Whether or not the Central Analyzer is enabled. +290 */ +291 @Parameter(property = "centralAnalyzerEnabled", required = false) +292 private Boolean centralAnalyzerEnabled; +293 +294 /** +295 * Whether or not the Nexus Analyzer is enabled. 296 */ -297 @Parameter(property = "nexusUrl", required = false) -298 private String nexusUrl; -299 /** -300 * Whether or not the configured proxy is used to connect to Nexus. -301 */ -302 @Parameter(property = "nexusUsesProxy", required = false) -303 private Boolean nexusUsesProxy; -304 /** -305 * The database connection string. -306 */ -307 @Parameter(property = "connectionString", defaultValue = "", required = false) -308 private String connectionString; -309 -310 /** -311 * Returns the connection string. -312 * -313 * @return the connection string -314 */ -315 protected String getConnectionString() { -316 return connectionString; -317 } -318 /** -319 * The database driver name. An example would be org.h2.Driver. -320 */ -321 @Parameter(property = "databaseDriverName", defaultValue = "", required = false) -322 private String databaseDriverName; -323 /** -324 * The path to the database driver if it is not on the class path. -325 */ -326 @Parameter(property = "databaseDriverPath", defaultValue = "", required = false) -327 private String databaseDriverPath; -328 /** -329 * The server id in the settings.xml; used to retrieve encrypted passwords -330 * from the settings.xml. -331 */ -332 @Parameter(property = "serverId", defaultValue = "", required = false) -333 private String serverId; -334 /** -335 * A reference to the settings.xml settings. -336 */ -337 @Parameter(defaultValue = "${settings}", readonly = true, required = true) -338 private org.apache.maven.settings.Settings settingsXml; -339 /** -340 * The security dispatcher that can decrypt passwords in the settings.xml. -341 */ -342 @Component(role = SecDispatcher.class, hint = "default") -343 private SecDispatcher securityDispatcher; -344 /** -345 * The database user name. -346 */ -347 @Parameter(property = "databaseUser", defaultValue = "", required = false) -348 private String databaseUser; -349 /** -350 * The password to use when connecting to the database. -351 */ -352 @Parameter(property = "databasePassword", defaultValue = "", required = false) -353 private String databasePassword; -354 /** -355 * A comma-separated list of file extensions to add to analysis next to jar, -356 * zip, .... -357 */ -358 @Parameter(property = "zipExtensions", required = false) -359 private String zipExtensions; -360 /** -361 * Skip Dependency Check altogether. -362 */ -363 @SuppressWarnings("CanBeFinal") -364 @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false) -365 private boolean skip = false; -366 /** -367 * Skip Analysis for Test Scope Dependencies. -368 */ -369 @SuppressWarnings("CanBeFinal") -370 @Parameter(property = "skipTestScope", defaultValue = "true", required = false) -371 private boolean skipTestScope = true; -372 /** -373 * Skip Analysis for Runtime Scope Dependencies. -374 */ -375 @SuppressWarnings("CanBeFinal") -376 @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false) -377 private boolean skipRuntimeScope = false; -378 /** -379 * Skip Analysis for Provided Scope Dependencies. -380 */ -381 @SuppressWarnings("CanBeFinal") -382 @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false) -383 private boolean skipProvidedScope = false; -384 /** -385 * The data directory, hold DC SQL DB. -386 */ -387 @Parameter(property = "dataDirectory", defaultValue = "", required = false) -388 private String dataDirectory; -389 /** -390 * Data Mirror URL for CVE 1.2. -391 */ -392 @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false) -393 private String cveUrl12Modified; -394 /** -395 * Data Mirror URL for CVE 2.0. -396 */ -397 @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false) -398 private String cveUrl20Modified; -399 /** -400 * Base Data Mirror URL for CVE 1.2. -401 */ -402 @Parameter(property = "cveUrl12Base", defaultValue = "", required = false) -403 private String cveUrl12Base; -404 /** -405 * Data Mirror URL for CVE 2.0. -406 */ -407 @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) -408 private String cveUrl20Base; -409 /** -410 * Optionally skip excessive CVE update checks for a designated duration in -411 * hours. -412 */ -413 @Parameter(property = "cveValidForHours", defaultValue = "", required = false) -414 private Integer cveValidForHours; -415 +297 @Parameter(property = "nexusAnalyzerEnabled", required = false) +298 private Boolean nexusAnalyzerEnabled; +299 +300 /** +301 * The URL of a Nexus server's REST API end point +302 * (http://domain/nexus/service/local). +303 */ +304 @Parameter(property = "nexusUrl", required = false) +305 private String nexusUrl; +306 /** +307 * Whether or not the configured proxy is used to connect to Nexus. +308 */ +309 @Parameter(property = "nexusUsesProxy", required = false) +310 private Boolean nexusUsesProxy; +311 /** +312 * The database connection string. +313 */ +314 @Parameter(property = "connectionString", defaultValue = "", required = false) +315 private String connectionString; +316 +317 /** +318 * Returns the connection string. +319 * +320 * @return the connection string +321 */ +322 protected String getConnectionString() { +323 return connectionString; +324 } +325 /** +326 * The database driver name. An example would be org.h2.Driver. +327 */ +328 @Parameter(property = "databaseDriverName", defaultValue = "", required = false) +329 private String databaseDriverName; +330 /** +331 * The path to the database driver if it is not on the class path. +332 */ +333 @Parameter(property = "databaseDriverPath", defaultValue = "", required = false) +334 private String databaseDriverPath; +335 /** +336 * The server id in the settings.xml; used to retrieve encrypted passwords +337 * from the settings.xml. +338 */ +339 @Parameter(property = "serverId", defaultValue = "", required = false) +340 private String serverId; +341 /** +342 * A reference to the settings.xml settings. +343 */ +344 @Parameter(defaultValue = "${settings}", readonly = true, required = true) +345 private org.apache.maven.settings.Settings settingsXml; +346 /** +347 * The security dispatcher that can decrypt passwords in the settings.xml. +348 */ +349 @Component(role = SecDispatcher.class, hint = "default") +350 private SecDispatcher securityDispatcher; +351 /** +352 * The database user name. +353 */ +354 @Parameter(property = "databaseUser", defaultValue = "", required = false) +355 private String databaseUser; +356 /** +357 * The password to use when connecting to the database. +358 */ +359 @Parameter(property = "databasePassword", defaultValue = "", required = false) +360 private String databasePassword; +361 /** +362 * A comma-separated list of file extensions to add to analysis next to jar, +363 * zip, .... +364 */ +365 @Parameter(property = "zipExtensions", required = false) +366 private String zipExtensions; +367 /** +368 * Skip Dependency Check altogether. +369 */ +370 @SuppressWarnings("CanBeFinal") +371 @Parameter(property = "dependency-check.skip", defaultValue = "false", required = false) +372 private boolean skip = false; +373 /** +374 * Skip Analysis for Test Scope Dependencies. +375 */ +376 @SuppressWarnings("CanBeFinal") +377 @Parameter(property = "skipTestScope", defaultValue = "true", required = false) +378 private boolean skipTestScope = true; +379 /** +380 * Skip Analysis for Runtime Scope Dependencies. +381 */ +382 @SuppressWarnings("CanBeFinal") +383 @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false) +384 private boolean skipRuntimeScope = false; +385 /** +386 * Skip Analysis for Provided Scope Dependencies. +387 */ +388 @SuppressWarnings("CanBeFinal") +389 @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false) +390 private boolean skipProvidedScope = false; +391 /** +392 * The data directory, hold DC SQL DB. +393 */ +394 @Parameter(property = "dataDirectory", defaultValue = "", required = false) +395 private String dataDirectory; +396 /** +397 * Data Mirror URL for CVE 1.2. +398 */ +399 @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false) +400 private String cveUrl12Modified; +401 /** +402 * Data Mirror URL for CVE 2.0. +403 */ +404 @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false) +405 private String cveUrl20Modified; +406 /** +407 * Base Data Mirror URL for CVE 1.2. +408 */ +409 @Parameter(property = "cveUrl12Base", defaultValue = "", required = false) +410 private String cveUrl12Base; +411 /** +412 * Data Mirror URL for CVE 2.0. +413 */ +414 @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) +415 private String cveUrl20Base; 416 /** -417 * The path to mono for .NET Assembly analysis on non-windows systems. -418 */ -419 @Parameter(property = "pathToMono", defaultValue = "", required = false) -420 private String pathToMono; -421 -422 /** -423 * The Proxy URL. -424 * -425 * @deprecated Please use mavenSettings instead -426 */ -427 @SuppressWarnings("CanBeFinal") -428 @Parameter(property = "proxyUrl", defaultValue = "", required = false) -429 @Deprecated -430 private String proxyUrl = null; -431 /** -432 * Sets whether or not the external report format should be used. -433 * -434 * @deprecated the internal report is no longer supported -435 */ -436 @SuppressWarnings("CanBeFinal") -437 @Parameter(property = "externalReport") -438 @Deprecated -439 private String externalReport = null; -440 // </editor-fold> -441 //<editor-fold defaultstate="collapsed" desc="Base Maven implementation"> -442 -443 /** -444 * Executes dependency-check. -445 * -446 * @throws MojoExecutionException thrown if there is an exception executing -447 * the mojo -448 * @throws MojoFailureException thrown if dependency-check failed the build -449 */ -450 @Override -451 public void execute() throws MojoExecutionException, MojoFailureException { -452 generatingSite = false; -453 if (skip) { -454 getLog().info("Skipping " + getName(Locale.US)); -455 } else { -456 validateAggregate(); -457 project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory); -458 runCheck(); -459 } -460 } -461 -462 /** -463 * Checks if the aggregate configuration parameter has been set to true. If -464 * it has a MojoExecutionException is thrown because the aggregate -465 * configuration parameter is no longer supported. -466 * -467 * @throws MojoExecutionException thrown if aggregate is set to true -468 */ -469 private void validateAggregate() throws MojoExecutionException { -470 if (aggregate != null && aggregate) { -471 final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. " -472 + "Please use the aggregate goal instead."; -473 throw new MojoExecutionException(msg); -474 } -475 } -476 -477 /** -478 * Generates the Dependency-Check Site Report. -479 * -480 * @param sink the sink to write the report to -481 * @param locale the locale to use when generating the report -482 * @throws MavenReportException if a maven report exception occurs -483 * @deprecated use -484 * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)} -485 * instead. -486 */ -487 @Override -488 @Deprecated -489 public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException { -490 generate((Sink) sink, locale); -491 } -492 -493 /** -494 * A flag indicating whether or not the maven site is being generated. -495 */ -496 private boolean generatingSite = false; -497 -498 /** -499 * Returns true if the Maven site is being generated. -500 * -501 * @return true if the Maven site is being generated +417 * Optionally skip excessive CVE update checks for a designated duration in +418 * hours. +419 */ +420 @Parameter(property = "cveValidForHours", defaultValue = "", required = false) +421 private Integer cveValidForHours; +422 +423 /** +424 * The path to mono for .NET Assembly analysis on non-windows systems. +425 */ +426 @Parameter(property = "pathToMono", defaultValue = "", required = false) +427 private String pathToMono; +428 +429 /** +430 * The Proxy URL. +431 * +432 * @deprecated Please use mavenSettings instead +433 */ +434 @SuppressWarnings("CanBeFinal") +435 @Parameter(property = "proxyUrl", defaultValue = "", required = false) +436 @Deprecated +437 private String proxyUrl = null; +438 /** +439 * Sets whether or not the external report format should be used. +440 * +441 * @deprecated the internal report is no longer supported +442 */ +443 @SuppressWarnings("CanBeFinal") +444 @Parameter(property = "externalReport") +445 @Deprecated +446 private String externalReport = null; +447 // </editor-fold> +448 //<editor-fold defaultstate="collapsed" desc="Base Maven implementation"> +449 +450 /** +451 * Executes dependency-check. +452 * +453 * @throws MojoExecutionException thrown if there is an exception executing +454 * the mojo +455 * @throws MojoFailureException thrown if dependency-check failed the build +456 */ +457 @Override +458 public void execute() throws MojoExecutionException, MojoFailureException { +459 generatingSite = false; +460 if (skip) { +461 getLog().info("Skipping " + getName(Locale.US)); +462 } else { +463 validateAggregate(); +464 project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory); +465 runCheck(); +466 } +467 } +468 +469 /** +470 * Checks if the aggregate configuration parameter has been set to true. If +471 * it has a MojoExecutionException is thrown because the aggregate +472 * configuration parameter is no longer supported. +473 * +474 * @throws MojoExecutionException thrown if aggregate is set to true +475 */ +476 private void validateAggregate() throws MojoExecutionException { +477 if (aggregate != null && aggregate) { +478 final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. " +479 + "Please use the aggregate goal instead."; +480 throw new MojoExecutionException(msg); +481 } +482 } +483 +484 /** +485 * Generates the Dependency-Check Site Report. +486 * +487 * @param sink the sink to write the report to +488 * @param locale the locale to use when generating the report +489 * @throws MavenReportException if a maven report exception occurs +490 * @deprecated use +491 * {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale)} +492 * instead. +493 */ +494 @Override +495 @Deprecated +496 public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException { +497 generate((Sink) sink, locale); +498 } +499 +500 /** +501 * A flag indicating whether or not the maven site is being generated. 502 */ -503 protected boolean isGeneratingSite() { -504 return generatingSite; -505 } -506 -507 /** -508 * Generates the Dependency-Check Site Report. -509 * -510 * @param sink the sink to write the report to -511 * @param locale the locale to use when generating the report -512 * @throws MavenReportException if a maven report exception occurs -513 */ -514 public void generate(Sink sink, Locale locale) throws MavenReportException { -515 generatingSite = true; -516 try { -517 validateAggregate(); -518 } catch (MojoExecutionException ex) { -519 throw new MavenReportException(ex.getMessage()); -520 } -521 project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory()); -522 try { -523 runCheck(); -524 } catch (MojoExecutionException ex) { -525 throw new MavenReportException(ex.getMessage(), ex); -526 } catch (MojoFailureException ex) { -527 getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build"); -528 } -529 } -530 -531 /** -532 * Returns the correct output directory depending on if a site is being -533 * executed or not. -534 * -535 * @return the directory to write the report(s) -536 * @throws MojoExecutionException thrown if there is an error loading the -537 * file path -538 */ -539 protected File getCorrectOutputDirectory() throws MojoExecutionException { -540 return getCorrectOutputDirectory(this.project); -541 } -542 -543 /** -544 * Returns the correct output directory depending on if a site is being -545 * executed or not. -546 * -547 * @param current the Maven project to get the output directory from -548 * @return the directory to write the report(s) -549 */ -550 protected File getCorrectOutputDirectory(MavenProject current) { -551 final Object obj = current.getContextValue(getOutputDirectoryContextKey()); -552 if (obj != null && obj instanceof File) { -553 return (File) obj; -554 } -555 File target = new File(current.getBuild().getDirectory()); -556 if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) { -557 target = target.getParentFile(); -558 } -559 return target; -560 } -561 -562 /** -563 * Returns the correct output directory depending on if a site is being -564 * executed or not. -565 * -566 * @param current the Maven project to get the output directory from -567 * @return the directory to write the report(s) -568 */ -569 protected File getDataFile(MavenProject current) { -570 if (getLog().isDebugEnabled()) { -571 getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey())); -572 } -573 final Object obj = current.getContextValue(getDataFileContextKey()); -574 if (obj != null) { -575 if (obj instanceof String) { -576 final File f = new File((String) obj); -577 return f; -578 } -579 } else if (getLog().isDebugEnabled()) { -580 getLog().debug("Context value not found"); -581 } -582 return null; -583 } -584 -585 /** -586 * Scans the project's artifacts and adds them to the engine's dependency -587 * list. -588 * -589 * @param project the project to scan the dependencies of -590 * @param engine the engine to use to scan the dependencies -591 * @return a collection of exceptions that may have occurred while resolving -592 * and scanning the dependencies -593 */ -594 protected ExceptionCollection scanArtifacts(MavenProject project, MavenEngine engine) { -595 // <editor-fold defaultstate="collapsed" desc="old implementation"> -596 /* -597 for (Artifact a : project.getArtifacts()) { -598 if (excludeFromScan(a)) { -599 continue; -600 } -601 final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile()); -602 if (deps != null) { -603 if (deps.size() == 1) { -604 final Dependency d = deps.get(0); -605 if (d != null) { -606 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); -607 d.addAsEvidence("pom", ma, Confidence.HIGHEST); -608 d.addProjectReference(project.getName()); -609 if (getLog().isDebugEnabled()) { -610 getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(), -611 d.getDisplayFileName())); -612 } -613 } -614 } else if (getLog().isDebugEnabled()) { -615 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", -616 a.getGroupId(), a.getArtifactId(), a.getVersion()); -617 getLog().debug(msg); -618 } +503 private boolean generatingSite = false; +504 +505 /** +506 * Returns true if the Maven site is being generated. +507 * +508 * @return true if the Maven site is being generated +509 */ +510 protected boolean isGeneratingSite() { +511 return generatingSite; +512 } +513 +514 /** +515 * Generates the Dependency-Check Site Report. +516 * +517 * @param sink the sink to write the report to +518 * @param locale the locale to use when generating the report +519 * @throws MavenReportException if a maven report exception occurs +520 */ +521 public void generate(Sink sink, Locale locale) throws MavenReportException { +522 generatingSite = true; +523 try { +524 validateAggregate(); +525 } catch (MojoExecutionException ex) { +526 throw new MavenReportException(ex.getMessage()); +527 } +528 project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory()); +529 try { +530 runCheck(); +531 } catch (MojoExecutionException ex) { +532 throw new MavenReportException(ex.getMessage(), ex); +533 } catch (MojoFailureException ex) { +534 getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build"); +535 } +536 } +537 +538 /** +539 * Returns the correct output directory depending on if a site is being +540 * executed or not. +541 * +542 * @return the directory to write the report(s) +543 * @throws MojoExecutionException thrown if there is an error loading the +544 * file path +545 */ +546 protected File getCorrectOutputDirectory() throws MojoExecutionException { +547 return getCorrectOutputDirectory(this.project); +548 } +549 +550 /** +551 * Returns the correct output directory depending on if a site is being +552 * executed or not. +553 * +554 * @param current the Maven project to get the output directory from +555 * @return the directory to write the report(s) +556 */ +557 protected File getCorrectOutputDirectory(MavenProject current) { +558 final Object obj = current.getContextValue(getOutputDirectoryContextKey()); +559 if (obj != null && obj instanceof File) { +560 return (File) obj; +561 } +562 File target = new File(current.getBuild().getDirectory()); +563 if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) { +564 target = target.getParentFile(); +565 } +566 return target; +567 } +568 +569 /** +570 * Returns the correct output directory depending on if a site is being +571 * executed or not. +572 * +573 * @param current the Maven project to get the output directory from +574 * @return the directory to write the report(s) +575 */ +576 protected File getDataFile(MavenProject current) { +577 if (getLog().isDebugEnabled()) { +578 getLog().debug(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey())); +579 } +580 final Object obj = current.getContextValue(getDataFileContextKey()); +581 if (obj != null) { +582 if (obj instanceof String) { +583 final File f = new File((String) obj); +584 return f; +585 } +586 } else if (getLog().isDebugEnabled()) { +587 getLog().debug("Context value not found"); +588 } +589 return null; +590 } +591 +592 /** +593 * Scans the project's artifacts and adds them to the engine's dependency +594 * list. +595 * +596 * @param project the project to scan the dependencies of +597 * @param engine the engine to use to scan the dependencies +598 * @return a collection of exceptions that may have occurred while resolving +599 * and scanning the dependencies +600 */ +601 protected ExceptionCollection scanArtifacts(MavenProject project, MavenEngine engine) { +602 // <editor-fold defaultstate="collapsed" desc="old implementation"> +603 /* +604 for (Artifact a : project.getArtifacts()) { +605 if (excludeFromScan(a)) { +606 continue; +607 } +608 final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile()); +609 if (deps != null) { +610 if (deps.size() == 1) { +611 final Dependency d = deps.get(0); +612 if (d != null) { +613 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); +614 d.addAsEvidence("pom", ma, Confidence.HIGHEST); +615 d.addProjectReference(project.getName()); +616 if (getLog().isDebugEnabled()) { +617 getLog().debug(String.format("Adding project reference %s on dependency %s", project.getName(), +618 d.getDisplayFileName())); 619 } 620 } -621 */ -622 // </editor-fold> -623 try { -624 final DependencyNode dn = dependencyGraphBuilder.buildDependencyGraph(project, null, reactorProjects); -625 return collectDependencies(engine, project, dn.getChildren()); -626 } catch (DependencyGraphBuilderException ex) { -627 final String msg = String.format("Unable to build dependency graph on project %s", project.getName()); -628 getLog().debug(msg, ex); -629 return new ExceptionCollection(msg, ex); -630 } -631 } -632 -633 /** -634 * Resolves the projects artifacts using Aether and scans the resulting -635 * dependencies. -636 * -637 * @param engine the core dependency-check engine -638 * @param project the project being scanned -639 * @param nodes the list of dependency nodes, generally obtained via the -640 * DependencyGraphBuilder -641 * @return a collection of exceptions that may have occurred while resolving -642 * and scanning the dependencies -643 */ -644 private ExceptionCollection collectDependencies(MavenEngine engine, MavenProject project, List<DependencyNode> nodes) { -645 ExceptionCollection exCol = null; -646 for (DependencyNode dependencyNode : nodes) { -647 exCol = collectDependencies(engine, project, dependencyNode.getChildren()); -648 if (excludeFromScan(dependencyNode.getArtifact().getScope())) { -649 continue; -650 } -651 final ArtifactRequest request = new ArtifactRequest(); -652 request.setArtifact(new DefaultArtifact(dependencyNode.getArtifact().getId())); -653 request.setRepositories(remoteRepos); -654 try { -655 final ArtifactResult result = repoSystem.resolveArtifact(repoSession, request); -656 if (result.isResolved() && result.getArtifact() != null && result.getArtifact().getFile() != null) { -657 final List<Dependency> deps = engine.scan(result.getArtifact().getFile().getAbsoluteFile()); -658 if (deps != null) { -659 if (deps.size() == 1) { -660 final Dependency d = deps.get(0); -661 if (d != null) { -662 final Artifact a = result.getArtifact(); -663 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); -664 d.addAsEvidence("pom", ma, Confidence.HIGHEST); -665 d.addProjectReference(project.getName() + ":" + dependencyNode.getArtifact().getScope()); -666 if (getLog().isDebugEnabled()) { -667 getLog().debug(String.format("Adding project reference %s on dependency %s", -668 project.getName(), d.getDisplayFileName())); -669 } -670 } -671 } else if (getLog().isDebugEnabled()) { -672 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s' in project %s", -673 dependencyNode.getArtifact().getId(), project.getName()); -674 getLog().debug(msg); -675 } -676 } else { -677 final String msg = String.format("Error resolving '%s' in project %s", -678 dependencyNode.getArtifact().getId(), project.getName()); -679 if (exCol == null) { -680 exCol = new ExceptionCollection(); -681 } -682 getLog().error(msg); -683 for (Exception ex : result.getExceptions()) { -684 exCol.addException(ex); -685 } -686 } -687 } else { -688 final String msg = String.format("Unable to resolve '%s' in project %s", -689 dependencyNode.getArtifact().getId(), project.getName()); -690 getLog().debug(msg); -691 if (exCol == null) { -692 exCol = new ExceptionCollection(); +621 } else if (getLog().isDebugEnabled()) { +622 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", +623 a.getGroupId(), a.getArtifactId(), a.getVersion()); +624 getLog().debug(msg); +625 } +626 } +627 } +628 */ +629 // </editor-fold> +630 try { +631 final DependencyNode dn = dependencyGraphBuilder.buildDependencyGraph(project, null, reactorProjects); +632 return collectDependencies(engine, project, dn.getChildren()); +633 } catch (DependencyGraphBuilderException ex) { +634 final String msg = String.format("Unable to build dependency graph on project %s", project.getName()); +635 getLog().debug(msg, ex); +636 return new ExceptionCollection(msg, ex); +637 } +638 } +639 +640 /** +641 * Resolves the projects artifacts using Aether and scans the resulting +642 * dependencies. +643 * +644 * @param engine the core dependency-check engine +645 * @param project the project being scanned +646 * @param nodes the list of dependency nodes, generally obtained via the +647 * DependencyGraphBuilder +648 * @return a collection of exceptions that may have occurred while resolving +649 * and scanning the dependencies +650 */ +651 private ExceptionCollection collectDependencies(MavenEngine engine, MavenProject project, List<DependencyNode> nodes) { +652 ExceptionCollection exCol = null; +653 for (DependencyNode dependencyNode : nodes) { +654 exCol = collectDependencies(engine, project, dependencyNode.getChildren()); +655 if (excludeFromScan(dependencyNode.getArtifact().getScope())) { +656 continue; +657 } +658 final ArtifactRequest request = new ArtifactRequest(); +659 request.setArtifact(new DefaultArtifact(dependencyNode.getArtifact().getId())); +660 request.setRepositories(remoteRepos); +661 try { +662 final ArtifactResult result = repoSystem.resolveArtifact(repoSession, request); +663 if (result.isResolved() && result.getArtifact() != null && result.getArtifact().getFile() != null) { +664 final List<Dependency> deps = engine.scan(result.getArtifact().getFile().getAbsoluteFile(), +665 project.getName() + ":" + dependencyNode.getArtifact().getScope()); +666 if (deps != null) { +667 if (deps.size() == 1) { +668 final Dependency d = deps.get(0); +669 if (d != null) { +670 final Artifact a = result.getArtifact(); +671 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); +672 d.addAsEvidence("pom", ma, Confidence.HIGHEST); +673 if (getLog().isDebugEnabled()) { +674 getLog().debug(String.format("Adding project reference %s on dependency %s", +675 project.getName(), d.getDisplayFileName())); +676 } +677 } +678 } else if (getLog().isDebugEnabled()) { +679 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s' in project %s", +680 dependencyNode.getArtifact().getId(), project.getName()); +681 getLog().debug(msg); +682 } +683 } else { +684 final String msg = String.format("Error resolving '%s' in project %s", +685 dependencyNode.getArtifact().getId(), project.getName()); +686 if (exCol == null) { +687 exCol = new ExceptionCollection(); +688 } +689 getLog().error(msg); +690 for (Exception ex : result.getExceptions()) { +691 exCol.addException(ex); +692 } 693 } -694 for (Exception ex : result.getExceptions()) { -695 exCol.addException(ex); -696 } -697 } -698 } catch (ArtifactResolutionException ex) { -699 if (exCol == null) { -700 exCol = new ExceptionCollection(); -701 } -702 exCol.addException(ex); -703 } -704 } -705 return exCol; -706 } -707 -708 /** -709 * Executes the dependency-check scan and generates the necassary report. -710 * -711 * @throws MojoExecutionException thrown if there is an exception running -712 * the scan -713 * @throws MojoFailureException thrown if dependency-check is configured to -714 * fail the build -715 */ -716 public abstract void runCheck() throws MojoExecutionException, MojoFailureException; -717 -718 /** -719 * Sets the Reporting output directory. -720 * -721 * @param directory the output directory +694 } else { +695 final String msg = String.format("Unable to resolve '%s' in project %s", +696 dependencyNode.getArtifact().getId(), project.getName()); +697 getLog().debug(msg); +698 if (exCol == null) { +699 exCol = new ExceptionCollection(); +700 } +701 for (Exception ex : result.getExceptions()) { +702 exCol.addException(ex); +703 } +704 } +705 } catch (ArtifactResolutionException ex) { +706 if (exCol == null) { +707 exCol = new ExceptionCollection(); +708 } +709 exCol.addException(ex); +710 } +711 } +712 return exCol; +713 } +714 +715 /** +716 * Executes the dependency-check scan and generates the necassary report. +717 * +718 * @throws MojoExecutionException thrown if there is an exception running +719 * the scan +720 * @throws MojoFailureException thrown if dependency-check is configured to +721 * fail the build 722 */ -723 @Override -724 public void setReportOutputDirectory(File directory) { -725 reportOutputDirectory = directory; -726 } -727 -728 /** -729 * Returns the report output directory. -730 * -731 * @return the report output directory -732 */ -733 @Override -734 public File getReportOutputDirectory() { -735 return reportOutputDirectory; -736 } -737 -738 /** -739 * Returns the output directory. -740 * -741 * @return the output directory -742 */ -743 public File getOutputDirectory() { -744 return outputDirectory; -745 } -746 -747 /** -748 * Returns whether this is an external report. This method always returns -749 * true. -750 * -751 * @return <code>true</code> -752 */ -753 @Override -754 public final boolean isExternalReport() { -755 return true; -756 } -757 -758 /** -759 * Returns the output name. -760 * -761 * @return the output name -762 */ -763 @Override -764 public String getOutputName() { -765 if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) { -766 return "dependency-check-report"; -767 } else if ("XML".equalsIgnoreCase(this.format)) { -768 return "dependency-check-report.xml#"; -769 } else if ("VULN".equalsIgnoreCase(this.format)) { -770 return "dependency-check-vulnerability"; -771 } else { -772 getLog().warn("Unknown report format used during site generation."); +723 public abstract void runCheck() throws MojoExecutionException, MojoFailureException; +724 +725 /** +726 * Sets the Reporting output directory. +727 * +728 * @param directory the output directory +729 */ +730 @Override +731 public void setReportOutputDirectory(File directory) { +732 reportOutputDirectory = directory; +733 } +734 +735 /** +736 * Returns the report output directory. +737 * +738 * @return the report output directory +739 */ +740 @Override +741 public File getReportOutputDirectory() { +742 return reportOutputDirectory; +743 } +744 +745 /** +746 * Returns the output directory. +747 * +748 * @return the output directory +749 */ +750 public File getOutputDirectory() { +751 return outputDirectory; +752 } +753 +754 /** +755 * Returns whether this is an external report. This method always returns +756 * true. +757 * +758 * @return <code>true</code> +759 */ +760 @Override +761 public final boolean isExternalReport() { +762 return true; +763 } +764 +765 /** +766 * Returns the output name. +767 * +768 * @return the output name +769 */ +770 @Override +771 public String getOutputName() { +772 if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) { 773 return "dependency-check-report"; -774 } -775 } -776 -777 /** -778 * Returns the category name. -779 * -780 * @return the category name -781 */ -782 @Override -783 public String getCategoryName() { -784 return MavenReport.CATEGORY_PROJECT_REPORTS; -785 } -786 //</editor-fold> -787 -788 /** -789 * Initializes a new <code>MavenEngine</code> that can be used for scanning. -790 * -791 * @return a newly instantiated <code>MavenEngine</code> -792 * @throws DatabaseException thrown if there is a database exception -793 */ -794 protected MavenEngine initializeEngine() throws DatabaseException { -795 populateSettings(); -796 return new MavenEngine(this.project, this.reactorProjects); -797 } -798 -799 /** -800 * Takes the properties supplied and updates the dependency-check settings. -801 * Additionally, this sets the system properties required to change the -802 * proxy url, port, and connection timeout. -803 */ -804 protected void populateSettings() { -805 Settings.initialize(); -806 InputStream mojoProperties = null; -807 try { -808 mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); -809 Settings.mergeProperties(mojoProperties); -810 } catch (IOException ex) { -811 getLog().warn("Unable to load the dependency-check ant task.properties file."); -812 if (getLog().isDebugEnabled()) { -813 getLog().debug("", ex); -814 } -815 } finally { -816 if (mojoProperties != null) { -817 try { -818 mojoProperties.close(); -819 } catch (IOException ex) { -820 if (getLog().isDebugEnabled()) { -821 getLog().debug("", ex); -822 } -823 } -824 } -825 } -826 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); -827 -828 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); -829 -830 if (externalReport != null) { -831 getLog().warn("The 'externalReport' option was set; this configuration option has been removed. " -832 + "Please update the dependency-check-maven plugin's configuration"); -833 } +774 } else if ("XML".equalsIgnoreCase(this.format)) { +775 return "dependency-check-report.xml#"; +776 } else if ("VULN".equalsIgnoreCase(this.format)) { +777 return "dependency-check-vulnerability"; +778 } else { +779 getLog().warn("Unknown report format used during site generation."); +780 return "dependency-check-report"; +781 } +782 } +783 +784 /** +785 * Returns the category name. +786 * +787 * @return the category name +788 */ +789 @Override +790 public String getCategoryName() { +791 return MavenReport.CATEGORY_PROJECT_REPORTS; +792 } +793 //</editor-fold> +794 +795 /** +796 * Initializes a new <code>MavenEngine</code> that can be used for scanning. +797 * +798 * @return a newly instantiated <code>MavenEngine</code> +799 * @throws DatabaseException thrown if there is a database exception +800 */ +801 protected MavenEngine initializeEngine() throws DatabaseException { +802 populateSettings(); +803 return new MavenEngine(this.project, this.reactorProjects); +804 } +805 +806 /** +807 * Takes the properties supplied and updates the dependency-check settings. +808 * Additionally, this sets the system properties required to change the +809 * proxy url, port, and connection timeout. +810 */ +811 protected void populateSettings() { +812 Settings.initialize(); +813 InputStream mojoProperties = null; +814 try { +815 mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); +816 Settings.mergeProperties(mojoProperties); +817 } catch (IOException ex) { +818 getLog().warn("Unable to load the dependency-check ant task.properties file."); +819 if (getLog().isDebugEnabled()) { +820 getLog().debug("", ex); +821 } +822 } finally { +823 if (mojoProperties != null) { +824 try { +825 mojoProperties.close(); +826 } catch (IOException ex) { +827 if (getLog().isDebugEnabled()) { +828 getLog().debug("", ex); +829 } +830 } +831 } +832 } +833 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); 834 -835 if (proxyUrl != null && !proxyUrl.isEmpty()) { -836 getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead"); -837 } -838 final Proxy proxy = getMavenProxy(); -839 if (proxy != null) { -840 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost()); -841 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort())); -842 final String userName = proxy.getUsername(); -843 final String password = proxy.getPassword(); -844 Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName); -845 Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password); -846 Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts()); -847 } -848 -849 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); -850 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); -851 -852 //File Type Analyzer Settings -853 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); -854 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); -855 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); -856 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); -857 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); -858 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); -859 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); -860 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); -861 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); -862 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); -863 -864 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); -865 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); -866 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); -867 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); -868 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); -869 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); -870 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); -871 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); -872 -873 //Database configuration -874 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); -875 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); -876 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); -877 -878 if (databaseUser == null && databasePassword == null && serverId != null) { -879 final Server server = settingsXml.getServer(serverId); -880 if (server != null) { -881 databaseUser = server.getUsername(); -882 try { -883 //The following fix was copied from: -884 // https://github.com/bsorrentino/maven-confluence-plugin/blob/master/maven-confluence-reporting-plugin/src/main/java/org/bsc/maven/confluence/plugin/AbstractBaseConfluenceMojo.java -885 // -886 // FIX to resolve -887 // org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: -888 // java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory) -889 // -890 if (securityDispatcher instanceof DefaultSecDispatcher) { -891 ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml"); -892 } -893 -894 databasePassword = securityDispatcher.decrypt(server.getPassword()); -895 } catch (SecDispatcherException ex) { -896 if (ex.getCause() instanceof FileNotFoundException -897 || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) { -898 //maybe its not encrypted? -899 final String tmp = server.getPassword(); -900 if (tmp.startsWith("{") && tmp.endsWith("}")) { -901 getLog().error(String.format( -902 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", -903 serverId, ex.getMessage())); -904 } else { -905 databasePassword = tmp; -906 } -907 } else { -908 getLog().error(String.format( -909 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", -910 serverId, ex.getMessage())); -911 } -912 } -913 } else { -914 getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId)); -915 } -916 } -917 -918 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); -919 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); -920 Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory); -921 -922 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); -923 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); -924 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); -925 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); -926 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); -927 -928 } +835 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); +836 +837 if (externalReport != null) { +838 getLog().warn("The 'externalReport' option was set; this configuration option has been removed. " +839 + "Please update the dependency-check-maven plugin's configuration"); +840 } +841 +842 if (proxyUrl != null && !proxyUrl.isEmpty()) { +843 getLog().warn("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead"); +844 } +845 final Proxy proxy = getMavenProxy(); +846 if (proxy != null) { +847 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost()); +848 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort())); +849 final String userName = proxy.getUsername(); +850 final String password = proxy.getPassword(); +851 Settings.setStringIfNotNull(Settings.KEYS.PROXY_USERNAME, userName); +852 Settings.setStringIfNotNull(Settings.KEYS.PROXY_PASSWORD, password); +853 Settings.setStringIfNotNull(Settings.KEYS.PROXY_NON_PROXY_HOSTS, proxy.getNonProxyHosts()); +854 } +855 +856 Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); +857 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); +858 Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile); +859 +860 //File Type Analyzer Settings +861 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); +862 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); +863 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); +864 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); +865 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); +866 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); +867 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); +868 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); +869 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); +870 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); +871 +872 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); +873 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); +874 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); +875 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); +876 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); +877 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); +878 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); +879 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); +880 +881 //Database configuration +882 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); +883 Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); +884 Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString); +885 +886 if (databaseUser == null && databasePassword == null && serverId != null) { +887 final Server server = settingsXml.getServer(serverId); +888 if (server != null) { +889 databaseUser = server.getUsername(); +890 try { +891 //The following fix was copied from: +892 // https://github.com/bsorrentino/maven-confluence-plugin/blob/master/maven-confluence-reporting-plugin/src/main/java/org/bsc/maven/confluence/plugin/AbstractBaseConfluenceMojo.java +893 // +894 // FIX to resolve +895 // org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: +896 // java.io.FileNotFoundException: ~/.settings-security.xml (No such file or directory) +897 // +898 if (securityDispatcher instanceof DefaultSecDispatcher) { +899 ((DefaultSecDispatcher) securityDispatcher).setConfigurationFile("~/.m2/settings-security.xml"); +900 } +901 +902 databasePassword = securityDispatcher.decrypt(server.getPassword()); +903 } catch (SecDispatcherException ex) { +904 if (ex.getCause() instanceof FileNotFoundException +905 || (ex.getCause() != null && ex.getCause().getCause() instanceof FileNotFoundException)) { +906 //maybe its not encrypted? +907 final String tmp = server.getPassword(); +908 if (tmp.startsWith("{") && tmp.endsWith("}")) { +909 getLog().error(String.format( +910 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", +911 serverId, ex.getMessage())); +912 } else { +913 databasePassword = tmp; +914 } +915 } else { +916 getLog().error(String.format( +917 "Unable to decrypt the server password for server id '%s' in settings.xml%n\tCause: %s", +918 serverId, ex.getMessage())); +919 } +920 } +921 } else { +922 getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId)); +923 } +924 } +925 +926 Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser); +927 Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword); +928 Settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory); 929 -930 /** -931 * Returns the maven proxy. -932 * -933 * @return the maven proxy -934 */ -935 private Proxy getMavenProxy() { -936 if (mavenSettings != null) { -937 final List<Proxy> proxies = mavenSettings.getProxies(); -938 if (proxies != null && !proxies.isEmpty()) { -939 if (mavenSettingsProxyId != null) { -940 for (Proxy proxy : proxies) { -941 if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) { -942 return proxy; -943 } -944 } -945 } else if (proxies.size() == 1) { -946 return proxies.get(0); -947 } else { -948 getLog().warn("Multiple proxy definitions exist in the Maven settings. In the dependency-check " -949 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used."); -950 throw new IllegalStateException("Ambiguous proxy definition"); -951 } -952 } -953 } -954 return null; -955 } -956 -957 /** -958 * Tests is the artifact should be included in the scan (i.e. is the -959 * dependency in a scope that is being scanned). -960 * -961 * @param scope the scope of the artifact to test -962 * @return <code>true</code> if the artifact is in an excluded scope; -963 * otherwise <code>false</code> -964 */ -965 protected boolean excludeFromScan(String scope) { -966 if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) { -967 return true; -968 } -969 if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) { -970 return true; -971 } -972 if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) { -973 return true; -974 } -975 return false; -976 } -977 -978 /** -979 * Returns a reference to the current project. This method is used instead -980 * of auto-binding the project via component annotation in concrete -981 * implementations of this. If the child has a -982 * <code>@Component MavenProject project;</code> defined then the abstract -983 * class (i.e. this class) will not have access to the current project (just -984 * the way Maven works with the binding). -985 * -986 * @return returns a reference to the current project -987 */ -988 protected MavenProject getProject() { -989 return project; -990 } -991 -992 /** -993 * Returns the list of Maven Projects in this build. -994 * -995 * @return the list of Maven Projects in this build -996 */ -997 protected List<MavenProject> getReactorProjects() { -998 return reactorProjects; -999 } -1000 -1001 /** -1002 * Returns the report format. -1003 * -1004 * @return the report format -1005 */ -1006 protected String getFormat() { -1007 return format; -1008 } -1009 -1010 /** -1011 * Generates the reports for a given dependency-check engine. -1012 * -1013 * @param engine a dependency-check engine -1014 * @param p the Maven project -1015 * @param outputDir the directory path to write the report(s) -1016 * @throws ReportException thrown if there is an error writing the report -1017 */ -1018 protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException { -1019 DatabaseProperties prop = null; -1020 CveDB cve = null; -1021 try { -1022 cve = new CveDB(); -1023 cve.open(); -1024 prop = cve.getDatabaseProperties(); -1025 } catch (DatabaseException ex) { -1026 if (getLog().isDebugEnabled()) { -1027 getLog().debug("Unable to retrieve DB Properties", ex); -1028 } -1029 } finally { -1030 if (cve != null) { -1031 cve.close(); -1032 } -1033 } -1034 final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop); -1035 try { -1036 r.generateReports(outputDir.getAbsolutePath(), format); -1037 } catch (ReportException ex) { -1038 final String msg = String.format("Error generating the report for %s", p.getName()); -1039 throw new ReportException(msg, ex); -1040 } -1041 -1042 } -1043 -1044 //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary"> -1045 /** -1046 * Checks to see if a vulnerability has been identified with a CVSS score -1047 * that is above the threshold set in the configuration. -1048 * -1049 * @param dependencies the list of dependency objects -1050 * @throws MojoFailureException thrown if a CVSS score is found that is -1051 * higher then the threshold set -1052 */ -1053 protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException { -1054 if (failBuildOnCVSS <= 10) { -1055 final StringBuilder ids = new StringBuilder(); -1056 for (Dependency d : dependencies) { -1057 boolean addName = true; -1058 for (Vulnerability v : d.getVulnerabilities()) { -1059 if (v.getCvssScore() >= failBuildOnCVSS) { -1060 if (addName) { -1061 addName = false; -1062 ids.append(NEW_LINE).append(d.getFileName()).append(": "); -1063 ids.append(v.getName()); -1064 } else { -1065 ids.append(", ").append(v.getName()); -1066 } -1067 } -1068 } -1069 } -1070 if (ids.length() > 0) { -1071 final String msg = String.format("%n%nDependency-Check Failure:%n" -1072 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" -1073 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); -1074 throw new MojoFailureException(msg); -1075 } -1076 } -1077 } -1078 -1079 /** -1080 * Generates a warning message listing a summary of dependencies and their -1081 * associated CPE and CVE entries. -1082 * -1083 * @param mp the Maven project for which the summary is shown -1084 * @param dependencies a list of dependency objects -1085 */ -1086 protected void showSummary(MavenProject mp, List<Dependency> dependencies) { -1087 if (showSummary) { -1088 final StringBuilder summary = new StringBuilder(); -1089 for (Dependency d : dependencies) { -1090 boolean firstEntry = true; -1091 final StringBuilder ids = new StringBuilder(); -1092 for (Vulnerability v : d.getVulnerabilities()) { -1093 if (firstEntry) { -1094 firstEntry = false; -1095 } else { -1096 ids.append(", "); -1097 } -1098 ids.append(v.getName()); -1099 } -1100 if (ids.length() > 0) { -1101 summary.append(d.getFileName()).append(" ("); -1102 firstEntry = true; -1103 for (Identifier id : d.getIdentifiers()) { -1104 if (firstEntry) { -1105 firstEntry = false; -1106 } else { -1107 summary.append(", "); -1108 } -1109 summary.append(id.getValue()); -1110 } -1111 summary.append(") : ").append(ids).append(NEW_LINE); -1112 } -1113 } -1114 if (summary.length() > 0) { -1115 final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s" -1116 + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString()); -1117 getLog().warn(msg); -1118 } -1119 } -1120 } -1121 -1122 //</editor-fold> -1123 //<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file"> -1124 /** -1125 * Returns the key used to store the path to the data file that is saved by -1126 * <code>writeDataFile()</code>. This key is used in the -1127 * <code>MavenProject.(set|get)ContextValue</code>. -1128 * -1129 * @return the key used to store the path to the data file -1130 */ -1131 protected String getDataFileContextKey() { -1132 return "dependency-check-path-" + dataFileName; -1133 } -1134 -1135 /** -1136 * Returns the key used to store the path to the output directory. When -1137 * generating the report in the <code>executeAggregateReport()</code> the -1138 * output directory should be obtained by using this key. -1139 * -1140 * @return the key used to store the path to the output directory -1141 */ -1142 protected String getOutputDirectoryContextKey() { -1143 return "dependency-output-dir-" + dataFileName; -1144 } -1145 -1146 /** -1147 * Writes the scan data to disk. This is used to serialize the scan data -1148 * between the "check" and "aggregate" phase. -1149 * -1150 * @param mp the mMven project for which the data file was created -1151 * @param writeTo the directory to write the data file -1152 * @param dependencies the list of dependencies to serialize -1153 */ -1154 protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) { -1155 File file; -1156 //check to see if this was already written out -1157 if (mp.getContextValue(this.getDataFileContextKey()) == null) { -1158 if (writeTo == null) { -1159 file = new File(mp.getBuild().getDirectory()); -1160 file = new File(file, dataFileName); -1161 } else { -1162 file = new File(writeTo, dataFileName); -1163 } -1164 final File parent = file.getParentFile(); -1165 if (!parent.isDirectory() && !parent.mkdirs()) { -1166 getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.", -1167 parent.getAbsolutePath())); -1168 } -1169 -1170 ObjectOutputStream out = null; -1171 try { -1172 if (dependencies != null) { -1173 out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); -1174 out.writeObject(dependencies); -1175 } -1176 if (getLog().isDebugEnabled()) { -1177 getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s", -1178 file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey())); -1179 } -1180 mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath()); -1181 } catch (IOException ex) { -1182 getLog().warn("Unable to create data file used for report aggregation; " -1183 + "if report aggregation is being used the results may be incomplete."); +930 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); +931 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); +932 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); +933 Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); +934 Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours); +935 +936 } +937 +938 /** +939 * Returns the maven proxy. +940 * +941 * @return the maven proxy +942 */ +943 private Proxy getMavenProxy() { +944 if (mavenSettings != null) { +945 final List<Proxy> proxies = mavenSettings.getProxies(); +946 if (proxies != null && !proxies.isEmpty()) { +947 if (mavenSettingsProxyId != null) { +948 for (Proxy proxy : proxies) { +949 if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) { +950 return proxy; +951 } +952 } +953 } else if (proxies.size() == 1) { +954 return proxies.get(0); +955 } else { +956 getLog().warn("Multiple proxy definitions exist in the Maven settings. In the dependency-check " +957 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used."); +958 throw new IllegalStateException("Ambiguous proxy definition"); +959 } +960 } +961 } +962 return null; +963 } +964 +965 /** +966 * Tests is the artifact should be included in the scan (i.e. is the +967 * dependency in a scope that is being scanned). +968 * +969 * @param scope the scope of the artifact to test +970 * @return <code>true</code> if the artifact is in an excluded scope; +971 * otherwise <code>false</code> +972 */ +973 protected boolean excludeFromScan(String scope) { +974 if (skipTestScope && org.apache.maven.artifact.Artifact.SCOPE_TEST.equals(scope)) { +975 return true; +976 } +977 if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) { +978 return true; +979 } +980 if (skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope)) { +981 return true; +982 } +983 return false; +984 } +985 +986 /** +987 * Returns a reference to the current project. This method is used instead +988 * of auto-binding the project via component annotation in concrete +989 * implementations of this. If the child has a +990 * <code>@Component MavenProject project;</code> defined then the abstract +991 * class (i.e. this class) will not have access to the current project (just +992 * the way Maven works with the binding). +993 * +994 * @return returns a reference to the current project +995 */ +996 protected MavenProject getProject() { +997 return project; +998 } +999 +1000 /** +1001 * Returns the list of Maven Projects in this build. +1002 * +1003 * @return the list of Maven Projects in this build +1004 */ +1005 protected List<MavenProject> getReactorProjects() { +1006 return reactorProjects; +1007 } +1008 +1009 /** +1010 * Returns the report format. +1011 * +1012 * @return the report format +1013 */ +1014 protected String getFormat() { +1015 return format; +1016 } +1017 +1018 /** +1019 * Generates the reports for a given dependency-check engine. +1020 * +1021 * @param engine a dependency-check engine +1022 * @param p the Maven project +1023 * @param outputDir the directory path to write the report(s) +1024 * @throws ReportException thrown if there is an error writing the report +1025 */ +1026 protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException { +1027 DatabaseProperties prop = null; +1028 CveDB cve = null; +1029 try { +1030 cve = new CveDB(); +1031 cve.open(); +1032 prop = cve.getDatabaseProperties(); +1033 } catch (DatabaseException ex) { +1034 if (getLog().isDebugEnabled()) { +1035 getLog().debug("Unable to retrieve DB Properties", ex); +1036 } +1037 } finally { +1038 if (cve != null) { +1039 cve.close(); +1040 } +1041 } +1042 final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop); +1043 try { +1044 r.generateReports(outputDir.getAbsolutePath(), format); +1045 } catch (ReportException ex) { +1046 final String msg = String.format("Error generating the report for %s", p.getName()); +1047 throw new ReportException(msg, ex); +1048 } +1049 +1050 } +1051 +1052 //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary"> +1053 /** +1054 * Checks to see if a vulnerability has been identified with a CVSS score +1055 * that is above the threshold set in the configuration. +1056 * +1057 * @param dependencies the list of dependency objects +1058 * @throws MojoFailureException thrown if a CVSS score is found that is +1059 * higher then the threshold set +1060 */ +1061 protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException { +1062 if (failBuildOnCVSS <= 10) { +1063 final StringBuilder ids = new StringBuilder(); +1064 for (Dependency d : dependencies) { +1065 boolean addName = true; +1066 for (Vulnerability v : d.getVulnerabilities()) { +1067 if (v.getCvssScore() >= failBuildOnCVSS) { +1068 if (addName) { +1069 addName = false; +1070 ids.append(NEW_LINE).append(d.getFileName()).append(": "); +1071 ids.append(v.getName()); +1072 } else { +1073 ids.append(", ").append(v.getName()); +1074 } +1075 } +1076 } +1077 } +1078 if (ids.length() > 0) { +1079 final String msg = String.format("%n%nDependency-Check Failure:%n" +1080 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" +1081 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); +1082 throw new MojoFailureException(msg); +1083 } +1084 } +1085 } +1086 +1087 /** +1088 * Generates a warning message listing a summary of dependencies and their +1089 * associated CPE and CVE entries. +1090 * +1091 * @param mp the Maven project for which the summary is shown +1092 * @param dependencies a list of dependency objects +1093 */ +1094 protected void showSummary(MavenProject mp, List<Dependency> dependencies) { +1095 if (showSummary) { +1096 final StringBuilder summary = new StringBuilder(); +1097 for (Dependency d : dependencies) { +1098 boolean firstEntry = true; +1099 final StringBuilder ids = new StringBuilder(); +1100 for (Vulnerability v : d.getVulnerabilities()) { +1101 if (firstEntry) { +1102 firstEntry = false; +1103 } else { +1104 ids.append(", "); +1105 } +1106 ids.append(v.getName()); +1107 } +1108 if (ids.length() > 0) { +1109 summary.append(d.getFileName()).append(" ("); +1110 firstEntry = true; +1111 for (Identifier id : d.getIdentifiers()) { +1112 if (firstEntry) { +1113 firstEntry = false; +1114 } else { +1115 summary.append(", "); +1116 } +1117 summary.append(id.getValue()); +1118 } +1119 summary.append(") : ").append(ids).append(NEW_LINE); +1120 } +1121 } +1122 if (summary.length() > 0) { +1123 final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s" +1124 + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString()); +1125 getLog().warn(msg); +1126 } +1127 } +1128 } +1129 +1130 //</editor-fold> +1131 //<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file"> +1132 /** +1133 * Returns the key used to store the path to the data file that is saved by +1134 * <code>writeDataFile()</code>. This key is used in the +1135 * <code>MavenProject.(set|get)ContextValue</code>. +1136 * +1137 * @return the key used to store the path to the data file +1138 */ +1139 protected String getDataFileContextKey() { +1140 return "dependency-check-path-" + dataFileName; +1141 } +1142 +1143 /** +1144 * Returns the key used to store the path to the output directory. When +1145 * generating the report in the <code>executeAggregateReport()</code> the +1146 * output directory should be obtained by using this key. +1147 * +1148 * @return the key used to store the path to the output directory +1149 */ +1150 protected String getOutputDirectoryContextKey() { +1151 return "dependency-output-dir-" + dataFileName; +1152 } +1153 +1154 /** +1155 * Writes the scan data to disk. This is used to serialize the scan data +1156 * between the "check" and "aggregate" phase. +1157 * +1158 * @param mp the mMven project for which the data file was created +1159 * @param writeTo the directory to write the data file +1160 * @param dependencies the list of dependencies to serialize +1161 */ +1162 protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) { +1163 File file; +1164 //check to see if this was already written out +1165 if (mp.getContextValue(this.getDataFileContextKey()) == null) { +1166 if (writeTo == null) { +1167 file = new File(mp.getBuild().getDirectory()); +1168 file = new File(file, dataFileName); +1169 } else { +1170 file = new File(writeTo, dataFileName); +1171 } +1172 final File parent = file.getParentFile(); +1173 if (!parent.isDirectory() && !parent.mkdirs()) { +1174 getLog().error(String.format("Directory '%s' does not exist and cannot be created; unable to write data file.", +1175 parent.getAbsolutePath())); +1176 } +1177 +1178 ObjectOutputStream out = null; +1179 try { +1180 if (dependencies != null) { +1181 out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); +1182 out.writeObject(dependencies); +1183 } 1184 if (getLog().isDebugEnabled()) { -1185 getLog().debug(ex.getMessage(), ex); -1186 } -1187 } finally { -1188 if (out != null) { -1189 try { -1190 out.close(); -1191 } catch (IOException ex) { -1192 if (getLog().isDebugEnabled()) { -1193 getLog().debug("ignore", ex); -1194 } -1195 } -1196 } -1197 } -1198 } -1199 } -1200 -1201 /** -1202 * Reads the serialized scan data from disk. This is used to serialize the -1203 * scan data between the "check" and "aggregate" phase. -1204 * -1205 * @param project the Maven project to read the data file from -1206 * @return a <code>MavenEngine</code> object populated with dependencies if -1207 * the serialized data file exists; otherwise <code>null</code> is returned -1208 */ -1209 protected List<Dependency> readDataFile(MavenProject project) { -1210 final Object oPath = project.getContextValue(this.getDataFileContextKey()); -1211 if (oPath == null) { -1212 return null; -1213 } -1214 List<Dependency> ret = null; -1215 final String path = (String) oPath; -1216 //ObjectInputStream ois = null; -1217 ExpectedOjectInputStream ois = null; -1218 try { -1219 //ois = new ObjectInputStream(new FileInputStream(path)); -1220 ois = new ExpectedOjectInputStream(new FileInputStream(path), -1221 "java.util.ArrayList", -1222 "java.util.HashSet", -1223 "java.util.TreeSet", -1224 "java.lang.AbstractSet", -1225 "java.lang.AbstractCollection", -1226 "java.lang.Enum", -1227 "org.owasp.dependencycheck.dependency.Confidence", -1228 "org.owasp.dependencycheck.dependency.Dependency", -1229 "org.owasp.dependencycheck.dependency.Evidence", -1230 "org.owasp.dependencycheck.dependency.EvidenceCollection", -1231 "org.owasp.dependencycheck.dependency.Identifier", -1232 "org.owasp.dependencycheck.dependency.Reference", -1233 "org.owasp.dependencycheck.dependency.Vulnerability", -1234 "org.owasp.dependencycheck.dependency.VulnerabilityComparator", -1235 "org.owasp.dependencycheck.dependency.VulnerableSoftware", -1236 "org.owasp.dependencycheck.data.cpe.IndexEntry"); -1237 @SuppressWarnings("unchecked") -1238 final List<Dependency> depList = (List<Dependency>) ois.readObject(); -1239 ret = depList; -1240 } catch (FileNotFoundException ex) { -1241 //TODO fix logging -1242 getLog().error("", ex); -1243 } catch (IOException ex) { -1244 getLog().error("", ex); -1245 } catch (ClassNotFoundException ex) { -1246 getLog().error("", ex); -1247 } finally { -1248 if (ois != null) { -1249 try { -1250 ois.close(); -1251 } catch (IOException ex) { -1252 getLog().error("", ex); -1253 } -1254 } -1255 } -1256 return ret; -1257 } -1258 //</editor-fold> -1259 -1260 } +1185 getLog().debug(String.format("Serialized data file written to '%s' for %s, referenced by key %s", +1186 file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey())); +1187 } +1188 mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath()); +1189 } catch (IOException ex) { +1190 getLog().warn("Unable to create data file used for report aggregation; " +1191 + "if report aggregation is being used the results may be incomplete."); +1192 if (getLog().isDebugEnabled()) { +1193 getLog().debug(ex.getMessage(), ex); +1194 } +1195 } finally { +1196 if (out != null) { +1197 try { +1198 out.close(); +1199 } catch (IOException ex) { +1200 if (getLog().isDebugEnabled()) { +1201 getLog().debug("ignore", ex); +1202 } +1203 } +1204 } +1205 } +1206 } +1207 } +1208 +1209 /** +1210 * Reads the serialized scan data from disk. This is used to serialize the +1211 * scan data between the "check" and "aggregate" phase. +1212 * +1213 * @param project the Maven project to read the data file from +1214 * @return a <code>MavenEngine</code> object populated with dependencies if +1215 * the serialized data file exists; otherwise <code>null</code> is returned +1216 */ +1217 protected List<Dependency> readDataFile(MavenProject project) { +1218 final Object oPath = project.getContextValue(this.getDataFileContextKey()); +1219 if (oPath == null) { +1220 return null; +1221 } +1222 List<Dependency> ret = null; +1223 final String path = (String) oPath; +1224 //ObjectInputStream ois = null; +1225 ExpectedOjectInputStream ois = null; +1226 try { +1227 //ois = new ObjectInputStream(new FileInputStream(path)); +1228 ois = new ExpectedOjectInputStream(new FileInputStream(path), +1229 "java.util.ArrayList", +1230 "java.util.HashSet", +1231 "java.util.TreeSet", +1232 "java.lang.AbstractSet", +1233 "java.lang.AbstractCollection", +1234 "java.lang.Enum", +1235 "org.owasp.dependencycheck.dependency.Confidence", +1236 "org.owasp.dependencycheck.dependency.Dependency", +1237 "org.owasp.dependencycheck.dependency.Evidence", +1238 "org.owasp.dependencycheck.dependency.EvidenceCollection", +1239 "org.owasp.dependencycheck.dependency.Identifier", +1240 "org.owasp.dependencycheck.dependency.Reference", +1241 "org.owasp.dependencycheck.dependency.Vulnerability", +1242 "org.owasp.dependencycheck.dependency.VulnerabilityComparator", +1243 "org.owasp.dependencycheck.dependency.VulnerableSoftware", +1244 "org.owasp.dependencycheck.data.cpe.IndexEntry"); +1245 @SuppressWarnings("unchecked") +1246 final List<Dependency> depList = (List<Dependency>) ois.readObject(); +1247 ret = depList; +1248 } catch (FileNotFoundException ex) { +1249 //TODO fix logging +1250 getLog().error("", ex); +1251 } catch (IOException ex) { +1252 getLog().error("", ex); +1253 } catch (ClassNotFoundException ex) { +1254 getLog().error("", ex); +1255 } finally { +1256 if (ois != null) { +1257 try { +1258 ois.close(); +1259 } catch (IOException ex) { +1260 getLog().error("", ex); +1261 } +1262 } +1263 } +1264 return ret; +1265 } +1266 //</editor-fold> +1267 +1268 }
      diff --git a/xref/org/owasp/dependencycheck/maven/CheckMojo.html b/xref/org/owasp/dependencycheck/maven/CheckMojo.html index 4f9851398..fa87ff359 100644 --- a/xref/org/owasp/dependencycheck/maven/CheckMojo.html +++ b/xref/org/owasp/dependencycheck/maven/CheckMojo.html @@ -89,7 +89,7 @@ 81 if (getLog().isDebugEnabled()) { 82 getLog().debug("Database connection error", ex); 83 } -84 final String msg = "An exception occured connecting to the local database. Please see the log file for more details."; +84 final String msg = "An exception occurred connecting to the local database. Please see the log file for more details."; 85 if (this.isFailOnError()) { 86 throw new MojoExecutionException(msg, ex); 87 } @@ -104,7 +104,7 @@ 96 engine.analyzeDependencies(); 97 } catch (ExceptionCollection ex) { 98 if (this.isFailOnError() && ex.isFatal()) { -99 throw new MojoExecutionException("One or more exceptions occured during analysis", ex); +99 throw new MojoExecutionException("One or more exceptions occurred during analysis", ex); 100 } 101 exCol = ex; 102 } @@ -120,11 +120,11 @@ 112 } 113 } 114 } -115 writeDataFile(getProject(), null, engine.getDependencies()); +115 //writeDataFile(getProject(), null, engine.getDependencies()); 116 showSummary(getProject(), engine.getDependencies()); 117 checkForFailure(engine.getDependencies()); 118 if (exCol != null && this.isFailOnError()) { -119 throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol); +119 throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol); 120 } 121 } 122 } diff --git a/xref/org/owasp/dependencycheck/maven/UpdateMojo.html b/xref/org/owasp/dependencycheck/maven/UpdateMojo.html index 1bb793f02..3983f9900 100644 --- a/xref/org/owasp/dependencycheck/maven/UpdateMojo.html +++ b/xref/org/owasp/dependencycheck/maven/UpdateMojo.html @@ -79,13 +79,13 @@ 71 if (getLog().isDebugEnabled()) { 72 getLog().debug("Database connection error", ex); 73 } -74 final String msg = "An exception occured connecting to the local database. Please see the log file for more details."; +74 final String msg = "An exception occurred connecting to the local database. Please see the log file for more details."; 75 if (this.isFailOnError()) { 76 throw new MojoExecutionException(msg, ex); 77 } 78 getLog().error(msg); 79 } catch (UpdateException ex) { -80 final String msg = "An exception occured while downloading updates. Please see the log file for more details."; +80 final String msg = "An exception occurred while downloading updates. Please see the log file for more details."; 81 if (this.isFailOnError()) { 82 throw new MojoExecutionException(msg, ex); 83 } diff --git a/xref/org/owasp/dependencycheck/maven/package-frame.html b/xref/org/owasp/dependencycheck/maven/package-frame.html index 51cfc30b4..ba8c45509 100644 --- a/xref/org/owasp/dependencycheck/maven/package-frame.html +++ b/xref/org/owasp/dependencycheck/maven/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.maven + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.maven diff --git a/xref/org/owasp/dependencycheck/maven/package-summary.html b/xref/org/owasp/dependencycheck/maven/package-summary.html index 7150b5b8f..fcf508eb1 100644 --- a/xref/org/owasp/dependencycheck/maven/package-summary.html +++ b/xref/org/owasp/dependencycheck/maven/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.maven + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.maven diff --git a/xref/org/owasp/dependencycheck/package-frame.html b/xref/org/owasp/dependencycheck/package-frame.html index 42790602d..bde00f860 100644 --- a/xref/org/owasp/dependencycheck/package-frame.html +++ b/xref/org/owasp/dependencycheck/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck @@ -17,6 +17,9 @@
      • ARGUMENT +
      • +
      • + AnalysisTask
      • App diff --git a/xref/org/owasp/dependencycheck/package-summary.html b/xref/org/owasp/dependencycheck/package-summary.html index 85a2b8438..bf2e74adf 100644 --- a/xref/org/owasp/dependencycheck/package-summary.html +++ b/xref/org/owasp/dependencycheck/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck @@ -39,6 +39,11 @@
    213. + + +
      ARGUMENT
      + AnalysisTask +
      diff --git a/xref/org/owasp/dependencycheck/reporting/package-frame.html b/xref/org/owasp/dependencycheck/reporting/package-frame.html index 1d597656d..d98666b8d 100644 --- a/xref/org/owasp/dependencycheck/reporting/package-frame.html +++ b/xref/org/owasp/dependencycheck/reporting/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.reporting diff --git a/xref/org/owasp/dependencycheck/reporting/package-summary.html b/xref/org/owasp/dependencycheck/reporting/package-summary.html index 08c09f52c..89ef91b01 100644 --- a/xref/org/owasp/dependencycheck/reporting/package-summary.html +++ b/xref/org/owasp/dependencycheck/reporting/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.reporting + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.reporting diff --git a/xref/org/owasp/dependencycheck/taskdefs/Check.html b/xref/org/owasp/dependencycheck/taskdefs/Check.html index 806c8cc4b..8650e9713 100644 --- a/xref/org/owasp/dependencycheck/taskdefs/Check.html +++ b/xref/org/owasp/dependencycheck/taskdefs/Check.html @@ -355,677 +355,700 @@ 347 this.suppressionFile = suppressionFile; 348 } 349 /** -350 * flag indicating whether or not to show a summary of findings. +350 * The path to the suppression file. 351 */ -352 private boolean showSummary = true; +352 private String hintsFile; 353 354 /** -355 * Get the value of showSummary. +355 * Get the value of hintsFile. 356 * -357 * @return the value of showSummary +357 * @return the value of hintsFile 358 */ -359 public boolean isShowSummary() { -360 return showSummary; +359 public String getHintsFile() { +360 return hintsFile; 361 } 362 363 /** -364 * Set the value of showSummary. +364 * Set the value of hintsFile. 365 * -366 * @param showSummary new value of showSummary +366 * @param hintsFile new value of hintsFile 367 */ -368 public void setShowSummary(boolean showSummary) { -369 this.showSummary = showSummary; +368 public void setHintsFile(String hintsFile) { +369 this.hintsFile = hintsFile; 370 } -371 -372 /** -373 * Whether experimental analyzers are enabled. -374 */ -375 private Boolean enableExperimental; -376 -377 /** -378 * Get the value of enableExperimental. -379 * -380 * @return the value of enableExperimental -381 */ -382 public Boolean isEnableExperimental() { -383 return enableExperimental; -384 } -385 -386 /** -387 * Set the value of enableExperimental. -388 * -389 * @param enableExperimental new value of enableExperimental -390 */ -391 public void setEnableExperimental(Boolean enableExperimental) { -392 this.enableExperimental = enableExperimental; -393 } -394 -395 /** -396 * Whether or not the Jar Analyzer is enabled. -397 */ -398 private Boolean jarAnalyzerEnabled; -399 -400 /** -401 * Returns whether or not the analyzer is enabled. -402 * -403 * @return true if the analyzer is enabled -404 */ -405 public Boolean isJarAnalyzerEnabled() { -406 return jarAnalyzerEnabled; -407 } -408 -409 /** -410 * Sets whether or not the analyzer is enabled. -411 * -412 * @param jarAnalyzerEnabled the value of the new setting -413 */ -414 public void setJarAnalyzerEnabled(Boolean jarAnalyzerEnabled) { -415 this.jarAnalyzerEnabled = jarAnalyzerEnabled; -416 } +371 /** +372 * flag indicating whether or not to show a summary of findings. +373 */ +374 private boolean showSummary = true; +375 +376 /** +377 * Get the value of showSummary. +378 * +379 * @return the value of showSummary +380 */ +381 public boolean isShowSummary() { +382 return showSummary; +383 } +384 +385 /** +386 * Set the value of showSummary. +387 * +388 * @param showSummary new value of showSummary +389 */ +390 public void setShowSummary(boolean showSummary) { +391 this.showSummary = showSummary; +392 } +393 +394 /** +395 * Whether experimental analyzers are enabled. +396 */ +397 private Boolean enableExperimental; +398 +399 /** +400 * Get the value of enableExperimental. +401 * +402 * @return the value of enableExperimental +403 */ +404 public Boolean isEnableExperimental() { +405 return enableExperimental; +406 } +407 +408 /** +409 * Set the value of enableExperimental. +410 * +411 * @param enableExperimental new value of enableExperimental +412 */ +413 public void setEnableExperimental(Boolean enableExperimental) { +414 this.enableExperimental = enableExperimental; +415 } +416 417 /** -418 * Whether or not the Archive Analyzer is enabled. +418 * Whether or not the Jar Analyzer is enabled. 419 */ -420 private Boolean archiveAnalyzerEnabled; +420 private Boolean jarAnalyzerEnabled; 421 422 /** 423 * Returns whether or not the analyzer is enabled. 424 * 425 * @return true if the analyzer is enabled 426 */ -427 public Boolean isArchiveAnalyzerEnabled() { -428 return archiveAnalyzerEnabled; +427 public Boolean isJarAnalyzerEnabled() { +428 return jarAnalyzerEnabled; 429 } -430 /** -431 * Whether or not the .NET Assembly Analyzer is enabled. -432 */ -433 private Boolean assemblyAnalyzerEnabled; -434 -435 /** -436 * Sets whether or not the analyzer is enabled. -437 * -438 * @param archiveAnalyzerEnabled the value of the new setting -439 */ -440 public void setArchiveAnalyzerEnabled(Boolean archiveAnalyzerEnabled) { -441 this.archiveAnalyzerEnabled = archiveAnalyzerEnabled; -442 } +430 +431 /** +432 * Sets whether or not the analyzer is enabled. +433 * +434 * @param jarAnalyzerEnabled the value of the new setting +435 */ +436 public void setJarAnalyzerEnabled(Boolean jarAnalyzerEnabled) { +437 this.jarAnalyzerEnabled = jarAnalyzerEnabled; +438 } +439 /** +440 * Whether or not the Archive Analyzer is enabled. +441 */ +442 private Boolean archiveAnalyzerEnabled; 443 444 /** 445 * Returns whether or not the analyzer is enabled. 446 * 447 * @return true if the analyzer is enabled 448 */ -449 public Boolean isAssemblyAnalyzerEnabled() { -450 return assemblyAnalyzerEnabled; +449 public Boolean isArchiveAnalyzerEnabled() { +450 return archiveAnalyzerEnabled; 451 } -452 -453 /** -454 * Sets whether or not the analyzer is enabled. -455 * -456 * @param assemblyAnalyzerEnabled the value of the new setting -457 */ -458 public void setAssemblyAnalyzerEnabled(Boolean assemblyAnalyzerEnabled) { -459 this.assemblyAnalyzerEnabled = assemblyAnalyzerEnabled; -460 } -461 /** -462 * Whether or not the .NET Nuspec Analyzer is enabled. -463 */ -464 private Boolean nuspecAnalyzerEnabled; +452 /** +453 * Whether or not the .NET Assembly Analyzer is enabled. +454 */ +455 private Boolean assemblyAnalyzerEnabled; +456 +457 /** +458 * Sets whether or not the analyzer is enabled. +459 * +460 * @param archiveAnalyzerEnabled the value of the new setting +461 */ +462 public void setArchiveAnalyzerEnabled(Boolean archiveAnalyzerEnabled) { +463 this.archiveAnalyzerEnabled = archiveAnalyzerEnabled; +464 } 465 466 /** 467 * Returns whether or not the analyzer is enabled. 468 * 469 * @return true if the analyzer is enabled 470 */ -471 public Boolean isNuspecAnalyzerEnabled() { -472 return nuspecAnalyzerEnabled; +471 public Boolean isAssemblyAnalyzerEnabled() { +472 return assemblyAnalyzerEnabled; 473 } 474 475 /** 476 * Sets whether or not the analyzer is enabled. 477 * -478 * @param nuspecAnalyzerEnabled the value of the new setting +478 * @param assemblyAnalyzerEnabled the value of the new setting 479 */ -480 public void setNuspecAnalyzerEnabled(Boolean nuspecAnalyzerEnabled) { -481 this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled; +480 public void setAssemblyAnalyzerEnabled(Boolean assemblyAnalyzerEnabled) { +481 this.assemblyAnalyzerEnabled = assemblyAnalyzerEnabled; 482 } 483 /** -484 * Whether or not the PHP Composer Analyzer is enabled. +484 * Whether or not the .NET Nuspec Analyzer is enabled. 485 */ -486 private Boolean composerAnalyzerEnabled; +486 private Boolean nuspecAnalyzerEnabled; 487 488 /** -489 * Get the value of composerAnalyzerEnabled. +489 * Returns whether or not the analyzer is enabled. 490 * -491 * @return the value of composerAnalyzerEnabled +491 * @return true if the analyzer is enabled 492 */ -493 public Boolean isComposerAnalyzerEnabled() { -494 return composerAnalyzerEnabled; +493 public Boolean isNuspecAnalyzerEnabled() { +494 return nuspecAnalyzerEnabled; 495 } 496 497 /** -498 * Set the value of composerAnalyzerEnabled. +498 * Sets whether or not the analyzer is enabled. 499 * -500 * @param composerAnalyzerEnabled new value of composerAnalyzerEnabled +500 * @param nuspecAnalyzerEnabled the value of the new setting 501 */ -502 public void setComposerAnalyzerEnabled(Boolean composerAnalyzerEnabled) { -503 this.composerAnalyzerEnabled = composerAnalyzerEnabled; +502 public void setNuspecAnalyzerEnabled(Boolean nuspecAnalyzerEnabled) { +503 this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled; 504 } 505 /** -506 * Whether the autoconf analyzer should be enabled. +506 * Whether or not the PHP Composer Analyzer is enabled. 507 */ -508 private Boolean autoconfAnalyzerEnabled; +508 private Boolean composerAnalyzerEnabled; 509 510 /** -511 * Get the value of autoconfAnalyzerEnabled. +511 * Get the value of composerAnalyzerEnabled. 512 * -513 * @return the value of autoconfAnalyzerEnabled +513 * @return the value of composerAnalyzerEnabled 514 */ -515 public Boolean isAutoconfAnalyzerEnabled() { -516 return autoconfAnalyzerEnabled; +515 public Boolean isComposerAnalyzerEnabled() { +516 return composerAnalyzerEnabled; 517 } 518 519 /** -520 * Set the value of autoconfAnalyzerEnabled. +520 * Set the value of composerAnalyzerEnabled. 521 * -522 * @param autoconfAnalyzerEnabled new value of autoconfAnalyzerEnabled +522 * @param composerAnalyzerEnabled new value of composerAnalyzerEnabled 523 */ -524 public void setAutoconfAnalyzerEnabled(Boolean autoconfAnalyzerEnabled) { -525 this.autoconfAnalyzerEnabled = autoconfAnalyzerEnabled; +524 public void setComposerAnalyzerEnabled(Boolean composerAnalyzerEnabled) { +525 this.composerAnalyzerEnabled = composerAnalyzerEnabled; 526 } 527 /** -528 * Whether the CMake analyzer should be enabled. +528 * Whether the autoconf analyzer should be enabled. 529 */ -530 private Boolean cmakeAnalyzerEnabled; +530 private Boolean autoconfAnalyzerEnabled; 531 532 /** -533 * Get the value of cmakeAnalyzerEnabled. +533 * Get the value of autoconfAnalyzerEnabled. 534 * -535 * @return the value of cmakeAnalyzerEnabled +535 * @return the value of autoconfAnalyzerEnabled 536 */ -537 public Boolean isCMakeAnalyzerEnabled() { -538 return cmakeAnalyzerEnabled; +537 public Boolean isAutoconfAnalyzerEnabled() { +538 return autoconfAnalyzerEnabled; 539 } 540 541 /** -542 * Set the value of cmakeAnalyzerEnabled. +542 * Set the value of autoconfAnalyzerEnabled. 543 * -544 * @param cmakeAnalyzerEnabled new value of cmakeAnalyzerEnabled +544 * @param autoconfAnalyzerEnabled new value of autoconfAnalyzerEnabled 545 */ -546 public void setCMakeAnalyzerEnabled(Boolean cmakeAnalyzerEnabled) { -547 this.cmakeAnalyzerEnabled = cmakeAnalyzerEnabled; +546 public void setAutoconfAnalyzerEnabled(Boolean autoconfAnalyzerEnabled) { +547 this.autoconfAnalyzerEnabled = autoconfAnalyzerEnabled; 548 } 549 /** -550 * Whether or not the openssl analyzer is enabled. +550 * Whether the CMake analyzer should be enabled. 551 */ -552 private Boolean opensslAnalyzerEnabled; +552 private Boolean cmakeAnalyzerEnabled; 553 554 /** -555 * Get the value of opensslAnalyzerEnabled. +555 * Get the value of cmakeAnalyzerEnabled. 556 * -557 * @return the value of opensslAnalyzerEnabled +557 * @return the value of cmakeAnalyzerEnabled 558 */ -559 public Boolean isOpensslAnalyzerEnabled() { -560 return opensslAnalyzerEnabled; +559 public Boolean isCMakeAnalyzerEnabled() { +560 return cmakeAnalyzerEnabled; 561 } 562 563 /** -564 * Set the value of opensslAnalyzerEnabled. +564 * Set the value of cmakeAnalyzerEnabled. 565 * -566 * @param opensslAnalyzerEnabled new value of opensslAnalyzerEnabled +566 * @param cmakeAnalyzerEnabled new value of cmakeAnalyzerEnabled 567 */ -568 public void setOpensslAnalyzerEnabled(Boolean opensslAnalyzerEnabled) { -569 this.opensslAnalyzerEnabled = opensslAnalyzerEnabled; +568 public void setCMakeAnalyzerEnabled(Boolean cmakeAnalyzerEnabled) { +569 this.cmakeAnalyzerEnabled = cmakeAnalyzerEnabled; 570 } 571 /** -572 * Whether or not the Node.js Analyzer is enabled. +572 * Whether or not the openssl analyzer is enabled. 573 */ -574 private Boolean nodeAnalyzerEnabled; +574 private Boolean opensslAnalyzerEnabled; 575 576 /** -577 * Get the value of nodeAnalyzerEnabled. +577 * Get the value of opensslAnalyzerEnabled. 578 * -579 * @return the value of nodeAnalyzerEnabled +579 * @return the value of opensslAnalyzerEnabled 580 */ -581 public Boolean isNodeAnalyzerEnabled() { -582 return nodeAnalyzerEnabled; +581 public Boolean isOpensslAnalyzerEnabled() { +582 return opensslAnalyzerEnabled; 583 } 584 585 /** -586 * Set the value of nodeAnalyzerEnabled. +586 * Set the value of opensslAnalyzerEnabled. 587 * -588 * @param nodeAnalyzerEnabled new value of nodeAnalyzerEnabled +588 * @param opensslAnalyzerEnabled new value of opensslAnalyzerEnabled 589 */ -590 public void setNodeAnalyzerEnabled(Boolean nodeAnalyzerEnabled) { -591 this.nodeAnalyzerEnabled = nodeAnalyzerEnabled; +590 public void setOpensslAnalyzerEnabled(Boolean opensslAnalyzerEnabled) { +591 this.opensslAnalyzerEnabled = opensslAnalyzerEnabled; 592 } 593 /** -594 * Whether the ruby gemspec analyzer should be enabled. +594 * Whether or not the Node.js Analyzer is enabled. 595 */ -596 private Boolean rubygemsAnalyzerEnabled; +596 private Boolean nodeAnalyzerEnabled; 597 598 /** -599 * Get the value of rubygemsAnalyzerEnabled. +599 * Get the value of nodeAnalyzerEnabled. 600 * -601 * @return the value of rubygemsAnalyzerEnabled +601 * @return the value of nodeAnalyzerEnabled 602 */ -603 public Boolean isRubygemsAnalyzerEnabled() { -604 return rubygemsAnalyzerEnabled; +603 public Boolean isNodeAnalyzerEnabled() { +604 return nodeAnalyzerEnabled; 605 } 606 607 /** -608 * Set the value of rubygemsAnalyzerEnabled. +608 * Set the value of nodeAnalyzerEnabled. 609 * -610 * @param rubygemsAnalyzerEnabled new value of rubygemsAnalyzerEnabled +610 * @param nodeAnalyzerEnabled new value of nodeAnalyzerEnabled 611 */ -612 public void setRubygemsAnalyzerEnabled(Boolean rubygemsAnalyzerEnabled) { -613 this.rubygemsAnalyzerEnabled = rubygemsAnalyzerEnabled; +612 public void setNodeAnalyzerEnabled(Boolean nodeAnalyzerEnabled) { +613 this.nodeAnalyzerEnabled = nodeAnalyzerEnabled; 614 } 615 /** -616 * Whether the python package analyzer should be enabled. +616 * Whether the ruby gemspec analyzer should be enabled. 617 */ -618 private Boolean pyPackageAnalyzerEnabled; +618 private Boolean rubygemsAnalyzerEnabled; 619 620 /** -621 * Get the value of pyPackageAnalyzerEnabled. +621 * Get the value of rubygemsAnalyzerEnabled. 622 * -623 * @return the value of pyPackageAnalyzerEnabled +623 * @return the value of rubygemsAnalyzerEnabled 624 */ -625 public Boolean isPyPackageAnalyzerEnabled() { -626 return pyPackageAnalyzerEnabled; +625 public Boolean isRubygemsAnalyzerEnabled() { +626 return rubygemsAnalyzerEnabled; 627 } 628 629 /** -630 * Set the value of pyPackageAnalyzerEnabled. +630 * Set the value of rubygemsAnalyzerEnabled. 631 * -632 * @param pyPackageAnalyzerEnabled new value of pyPackageAnalyzerEnabled +632 * @param rubygemsAnalyzerEnabled new value of rubygemsAnalyzerEnabled 633 */ -634 public void setPyPackageAnalyzerEnabled(Boolean pyPackageAnalyzerEnabled) { -635 this.pyPackageAnalyzerEnabled = pyPackageAnalyzerEnabled; +634 public void setRubygemsAnalyzerEnabled(Boolean rubygemsAnalyzerEnabled) { +635 this.rubygemsAnalyzerEnabled = rubygemsAnalyzerEnabled; 636 } -637 -638 /** -639 * Whether the python distribution analyzer should be enabled. -640 */ -641 private Boolean pyDistributionAnalyzerEnabled; -642 -643 /** -644 * Get the value of pyDistributionAnalyzerEnabled. -645 * -646 * @return the value of pyDistributionAnalyzerEnabled -647 */ -648 public Boolean isPyDistributionAnalyzerEnabled() { -649 return pyDistributionAnalyzerEnabled; -650 } -651 -652 /** -653 * Set the value of pyDistributionAnalyzerEnabled. -654 * -655 * @param pyDistributionAnalyzerEnabled new value of -656 * pyDistributionAnalyzerEnabled -657 */ -658 public void setPyDistributionAnalyzerEnabled(Boolean pyDistributionAnalyzerEnabled) { -659 this.pyDistributionAnalyzerEnabled = pyDistributionAnalyzerEnabled; -660 } -661 -662 /** -663 * Whether or not the central analyzer is enabled. -664 */ -665 private Boolean centralAnalyzerEnabled; -666 -667 /** -668 * Get the value of centralAnalyzerEnabled. -669 * -670 * @return the value of centralAnalyzerEnabled -671 */ -672 public Boolean isCentralAnalyzerEnabled() { -673 return centralAnalyzerEnabled; -674 } -675 -676 /** -677 * Set the value of centralAnalyzerEnabled. -678 * -679 * @param centralAnalyzerEnabled new value of centralAnalyzerEnabled -680 */ -681 public void setCentralAnalyzerEnabled(Boolean centralAnalyzerEnabled) { -682 this.centralAnalyzerEnabled = centralAnalyzerEnabled; -683 } -684 -685 /** -686 * Whether or not the nexus analyzer is enabled. -687 */ -688 private Boolean nexusAnalyzerEnabled; -689 -690 /** -691 * Get the value of nexusAnalyzerEnabled. -692 * -693 * @return the value of nexusAnalyzerEnabled -694 */ -695 public Boolean isNexusAnalyzerEnabled() { -696 return nexusAnalyzerEnabled; -697 } -698 -699 /** -700 * Set the value of nexusAnalyzerEnabled. -701 * -702 * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled -703 */ -704 public void setNexusAnalyzerEnabled(Boolean nexusAnalyzerEnabled) { -705 this.nexusAnalyzerEnabled = nexusAnalyzerEnabled; -706 } -707 -708 /** -709 * The URL of a Nexus server's REST API end point -710 * (http://domain/nexus/service/local). -711 */ -712 private String nexusUrl; -713 -714 /** -715 * Get the value of nexusUrl. -716 * -717 * @return the value of nexusUrl -718 */ -719 public String getNexusUrl() { -720 return nexusUrl; -721 } -722 -723 /** -724 * Set the value of nexusUrl. -725 * -726 * @param nexusUrl new value of nexusUrl -727 */ -728 public void setNexusUrl(String nexusUrl) { -729 this.nexusUrl = nexusUrl; -730 } -731 /** -732 * Whether or not the defined proxy should be used when connecting to Nexus. +637 /** +638 * Whether the python package analyzer should be enabled. +639 */ +640 private Boolean pyPackageAnalyzerEnabled; +641 +642 /** +643 * Get the value of pyPackageAnalyzerEnabled. +644 * +645 * @return the value of pyPackageAnalyzerEnabled +646 */ +647 public Boolean isPyPackageAnalyzerEnabled() { +648 return pyPackageAnalyzerEnabled; +649 } +650 +651 /** +652 * Set the value of pyPackageAnalyzerEnabled. +653 * +654 * @param pyPackageAnalyzerEnabled new value of pyPackageAnalyzerEnabled +655 */ +656 public void setPyPackageAnalyzerEnabled(Boolean pyPackageAnalyzerEnabled) { +657 this.pyPackageAnalyzerEnabled = pyPackageAnalyzerEnabled; +658 } +659 +660 /** +661 * Whether the python distribution analyzer should be enabled. +662 */ +663 private Boolean pyDistributionAnalyzerEnabled; +664 +665 /** +666 * Get the value of pyDistributionAnalyzerEnabled. +667 * +668 * @return the value of pyDistributionAnalyzerEnabled +669 */ +670 public Boolean isPyDistributionAnalyzerEnabled() { +671 return pyDistributionAnalyzerEnabled; +672 } +673 +674 /** +675 * Set the value of pyDistributionAnalyzerEnabled. +676 * +677 * @param pyDistributionAnalyzerEnabled new value of +678 * pyDistributionAnalyzerEnabled +679 */ +680 public void setPyDistributionAnalyzerEnabled(Boolean pyDistributionAnalyzerEnabled) { +681 this.pyDistributionAnalyzerEnabled = pyDistributionAnalyzerEnabled; +682 } +683 +684 /** +685 * Whether or not the central analyzer is enabled. +686 */ +687 private Boolean centralAnalyzerEnabled; +688 +689 /** +690 * Get the value of centralAnalyzerEnabled. +691 * +692 * @return the value of centralAnalyzerEnabled +693 */ +694 public Boolean isCentralAnalyzerEnabled() { +695 return centralAnalyzerEnabled; +696 } +697 +698 /** +699 * Set the value of centralAnalyzerEnabled. +700 * +701 * @param centralAnalyzerEnabled new value of centralAnalyzerEnabled +702 */ +703 public void setCentralAnalyzerEnabled(Boolean centralAnalyzerEnabled) { +704 this.centralAnalyzerEnabled = centralAnalyzerEnabled; +705 } +706 +707 /** +708 * Whether or not the nexus analyzer is enabled. +709 */ +710 private Boolean nexusAnalyzerEnabled; +711 +712 /** +713 * Get the value of nexusAnalyzerEnabled. +714 * +715 * @return the value of nexusAnalyzerEnabled +716 */ +717 public Boolean isNexusAnalyzerEnabled() { +718 return nexusAnalyzerEnabled; +719 } +720 +721 /** +722 * Set the value of nexusAnalyzerEnabled. +723 * +724 * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled +725 */ +726 public void setNexusAnalyzerEnabled(Boolean nexusAnalyzerEnabled) { +727 this.nexusAnalyzerEnabled = nexusAnalyzerEnabled; +728 } +729 +730 /** +731 * The URL of a Nexus server's REST API end point +732 * (http://domain/nexus/service/local). 733 */ -734 private Boolean nexusUsesProxy; +734 private String nexusUrl; 735 736 /** -737 * Get the value of nexusUsesProxy. +737 * Get the value of nexusUrl. 738 * -739 * @return the value of nexusUsesProxy +739 * @return the value of nexusUrl 740 */ -741 public Boolean isNexusUsesProxy() { -742 return nexusUsesProxy; +741 public String getNexusUrl() { +742 return nexusUrl; 743 } 744 745 /** -746 * Set the value of nexusUsesProxy. +746 * Set the value of nexusUrl. 747 * -748 * @param nexusUsesProxy new value of nexusUsesProxy +748 * @param nexusUrl new value of nexusUrl 749 */ -750 public void setNexusUsesProxy(Boolean nexusUsesProxy) { -751 this.nexusUsesProxy = nexusUsesProxy; +750 public void setNexusUrl(String nexusUrl) { +751 this.nexusUrl = nexusUrl; 752 } -753 -754 /** -755 * Additional ZIP File extensions to add analyze. This should be a -756 * comma-separated list of file extensions to treat like ZIP files. -757 */ -758 private String zipExtensions; -759 -760 /** -761 * Get the value of zipExtensions. -762 * -763 * @return the value of zipExtensions -764 */ -765 public String getZipExtensions() { -766 return zipExtensions; -767 } -768 -769 /** -770 * Set the value of zipExtensions. -771 * -772 * @param zipExtensions new value of zipExtensions -773 */ -774 public void setZipExtensions(String zipExtensions) { -775 this.zipExtensions = zipExtensions; -776 } -777 -778 /** -779 * The path to Mono for .NET assembly analysis on non-windows systems. -780 */ -781 private String pathToMono; -782 -783 /** -784 * Get the value of pathToMono. -785 * -786 * @return the value of pathToMono -787 */ -788 public String getPathToMono() { -789 return pathToMono; -790 } -791 -792 /** -793 * Set the value of pathToMono. -794 * -795 * @param pathToMono new value of pathToMono -796 */ -797 public void setPathToMono(String pathToMono) { -798 this.pathToMono = pathToMono; -799 } -800 -801 @Override -802 public void execute() throws BuildException { -803 dealWithReferences(); -804 validateConfiguration(); -805 populateSettings(); -806 Engine engine = null; -807 try { -808 engine = new Engine(Check.class.getClassLoader()); -809 if (isUpdateOnly()) { -810 log("Deprecated 'UpdateOnly' property set; please use the UpdateTask instead", Project.MSG_WARN); -811 try { -812 engine.doUpdates(); -813 } catch (UpdateException ex) { -814 if (this.isFailOnError()) { -815 throw new BuildException(ex); -816 } -817 log(ex.getMessage(), Project.MSG_ERR); -818 } -819 } else { -820 for (Resource resource : path) { -821 final FileProvider provider = resource.as(FileProvider.class); -822 if (provider != null) { -823 final File file = provider.getFile(); -824 if (file != null && file.exists()) { -825 engine.scan(file); -826 } -827 } -828 } -829 -830 try { -831 engine.analyzeDependencies(); -832 } catch (ExceptionCollection ex) { -833 if (this.isFailOnError()) { -834 throw new BuildException(ex); -835 } -836 } -837 DatabaseProperties prop = null; -838 CveDB cve = null; -839 try { -840 cve = new CveDB(); -841 cve.open(); -842 prop = cve.getDatabaseProperties(); -843 } catch (DatabaseException ex) { -844 log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG); -845 } finally { -846 if (cve != null) { -847 cve.close(); -848 } -849 } -850 final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop); -851 reporter.generateReports(reportOutputDirectory, reportFormat); -852 -853 if (this.failBuildOnCVSS <= 10) { -854 checkForFailure(engine.getDependencies()); -855 } -856 if (this.showSummary) { -857 showSummary(engine.getDependencies()); +753 /** +754 * Whether or not the defined proxy should be used when connecting to Nexus. +755 */ +756 private Boolean nexusUsesProxy; +757 +758 /** +759 * Get the value of nexusUsesProxy. +760 * +761 * @return the value of nexusUsesProxy +762 */ +763 public Boolean isNexusUsesProxy() { +764 return nexusUsesProxy; +765 } +766 +767 /** +768 * Set the value of nexusUsesProxy. +769 * +770 * @param nexusUsesProxy new value of nexusUsesProxy +771 */ +772 public void setNexusUsesProxy(Boolean nexusUsesProxy) { +773 this.nexusUsesProxy = nexusUsesProxy; +774 } +775 +776 /** +777 * Additional ZIP File extensions to add analyze. This should be a +778 * comma-separated list of file extensions to treat like ZIP files. +779 */ +780 private String zipExtensions; +781 +782 /** +783 * Get the value of zipExtensions. +784 * +785 * @return the value of zipExtensions +786 */ +787 public String getZipExtensions() { +788 return zipExtensions; +789 } +790 +791 /** +792 * Set the value of zipExtensions. +793 * +794 * @param zipExtensions new value of zipExtensions +795 */ +796 public void setZipExtensions(String zipExtensions) { +797 this.zipExtensions = zipExtensions; +798 } +799 +800 /** +801 * The path to Mono for .NET assembly analysis on non-windows systems. +802 */ +803 private String pathToMono; +804 +805 /** +806 * Get the value of pathToMono. +807 * +808 * @return the value of pathToMono +809 */ +810 public String getPathToMono() { +811 return pathToMono; +812 } +813 +814 /** +815 * Set the value of pathToMono. +816 * +817 * @param pathToMono new value of pathToMono +818 */ +819 public void setPathToMono(String pathToMono) { +820 this.pathToMono = pathToMono; +821 } +822 +823 @Override +824 public void execute() throws BuildException { +825 dealWithReferences(); +826 validateConfiguration(); +827 populateSettings(); +828 Engine engine = null; +829 try { +830 engine = new Engine(Check.class.getClassLoader()); +831 if (isUpdateOnly()) { +832 log("Deprecated 'UpdateOnly' property set; please use the UpdateTask instead", Project.MSG_WARN); +833 try { +834 engine.doUpdates(); +835 } catch (UpdateException ex) { +836 if (this.isFailOnError()) { +837 throw new BuildException(ex); +838 } +839 log(ex.getMessage(), Project.MSG_ERR); +840 } +841 } else { +842 for (Resource resource : path) { +843 final FileProvider provider = resource.as(FileProvider.class); +844 if (provider != null) { +845 final File file = provider.getFile(); +846 if (file != null && file.exists()) { +847 engine.scan(file); +848 } +849 } +850 } +851 +852 try { +853 engine.analyzeDependencies(); +854 } catch (ExceptionCollection ex) { +855 if (this.isFailOnError()) { +856 throw new BuildException(ex); +857 } 858 } -859 } -860 } catch (DatabaseException ex) { -861 final String msg = "Unable to connect to the dependency-check database; analysis has stopped"; -862 if (this.isFailOnError()) { -863 throw new BuildException(msg, ex); -864 } -865 log(msg, ex, Project.MSG_ERR); -866 } catch (ReportException ex) { -867 final String msg = "Unable to generate the dependency-check report"; -868 if (this.isFailOnError()) { -869 throw new BuildException(msg, ex); -870 } -871 log(msg, ex, Project.MSG_ERR); -872 } finally { -873 Settings.cleanup(true); -874 if (engine != null) { -875 engine.cleanup(); -876 } -877 } -878 } -879 -880 /** -881 * Validate the configuration to ensure the parameters have been properly -882 * configured/initialized. -883 * -884 * @throws BuildException if the task was not configured correctly. -885 */ -886 private void validateConfiguration() throws BuildException { -887 if (path == null) { -888 throw new BuildException("No project dependencies have been defined to analyze."); -889 } -890 if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) { -891 throw new BuildException("Invalid configuration, failBuildOnCVSS must be between 0 and 11."); -892 } -893 } -894 -895 /** -896 * Takes the properties supplied and updates the dependency-check settings. -897 * Additionally, this sets the system properties required to change the -898 * proxy server, port, and connection timeout. -899 * -900 * @throws BuildException thrown when an invalid setting is configured. -901 */ -902 @Override -903 protected void populateSettings() throws BuildException { -904 super.populateSettings(); -905 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); -906 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); -907 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); -908 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); -909 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); -910 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); -911 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); -912 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); -913 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); -914 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); -915 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); -916 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); -917 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); -918 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); -919 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); -920 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); -921 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); -922 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); -923 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); -924 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); -925 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); -926 } -927 -928 /** -929 * Checks to see if a vulnerability has been identified with a CVSS score -930 * that is above the threshold set in the configuration. -931 * -932 * @param dependencies the list of dependency objects -933 * @throws BuildException thrown if a CVSS score is found that is higher -934 * then the threshold set -935 */ -936 private void checkForFailure(List<Dependency> dependencies) throws BuildException { -937 final StringBuilder ids = new StringBuilder(); -938 for (Dependency d : dependencies) { -939 for (Vulnerability v : d.getVulnerabilities()) { -940 if (v.getCvssScore() >= failBuildOnCVSS) { -941 if (ids.length() == 0) { -942 ids.append(v.getName()); -943 } else { -944 ids.append(", ").append(v.getName()); -945 } -946 } -947 } -948 } -949 if (ids.length() > 0) { -950 final String msg = String.format("%n%nDependency-Check Failure:%n" -951 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" -952 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); -953 throw new BuildException(msg); -954 } -955 } -956 -957 /** -958 * Generates a warning message listing a summary of dependencies and their -959 * associated CPE and CVE entries. -960 * -961 * @param dependencies a list of dependency objects -962 */ -963 private void showSummary(List<Dependency> dependencies) { -964 final StringBuilder summary = new StringBuilder(); -965 for (Dependency d : dependencies) { -966 boolean firstEntry = true; -967 final StringBuilder ids = new StringBuilder(); -968 for (Vulnerability v : d.getVulnerabilities()) { -969 if (firstEntry) { -970 firstEntry = false; -971 } else { -972 ids.append(", "); -973 } -974 ids.append(v.getName()); -975 } -976 if (ids.length() > 0) { -977 summary.append(d.getFileName()).append(" ("); -978 firstEntry = true; -979 for (Identifier id : d.getIdentifiers()) { -980 if (firstEntry) { -981 firstEntry = false; -982 } else { -983 summary.append(", "); -984 } -985 summary.append(id.getValue()); -986 } -987 summary.append(") : ").append(ids).append(NEW_LINE); -988 } -989 } -990 if (summary.length() > 0) { -991 final String msg = String.format("%n%n" -992 + "One or more dependencies were identified with known vulnerabilities:%n%n%s" -993 + "%n%nSee the dependency-check report for more details.%n%n", summary.toString()); -994 log(msg, Project.MSG_WARN); -995 } -996 } -997 -998 /** -999 * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", -1000 * etc.. -1001 */ -1002 public static class ReportFormats extends EnumeratedAttribute { -1003 -1004 /** -1005 * Returns the list of values for the report format. -1006 * -1007 * @return the list of values for the report format -1008 */ -1009 @Override -1010 public String[] getValues() { -1011 int i = 0; -1012 final Format[] formats = Format.values(); -1013 final String[] values = new String[formats.length]; -1014 for (Format format : formats) { -1015 values[i++] = format.name(); -1016 } -1017 return values; +859 DatabaseProperties prop = null; +860 CveDB cve = null; +861 try { +862 cve = new CveDB(); +863 cve.open(); +864 prop = cve.getDatabaseProperties(); +865 } catch (DatabaseException ex) { +866 log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG); +867 } finally { +868 if (cve != null) { +869 cve.close(); +870 } +871 } +872 final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop); +873 reporter.generateReports(reportOutputDirectory, reportFormat); +874 +875 if (this.failBuildOnCVSS <= 10) { +876 checkForFailure(engine.getDependencies()); +877 } +878 if (this.showSummary) { +879 showSummary(engine.getDependencies()); +880 } +881 } +882 } catch (DatabaseException ex) { +883 final String msg = "Unable to connect to the dependency-check database; analysis has stopped"; +884 if (this.isFailOnError()) { +885 throw new BuildException(msg, ex); +886 } +887 log(msg, ex, Project.MSG_ERR); +888 } catch (ReportException ex) { +889 final String msg = "Unable to generate the dependency-check report"; +890 if (this.isFailOnError()) { +891 throw new BuildException(msg, ex); +892 } +893 log(msg, ex, Project.MSG_ERR); +894 } finally { +895 Settings.cleanup(true); +896 if (engine != null) { +897 engine.cleanup(); +898 } +899 } +900 } +901 +902 /** +903 * Validate the configuration to ensure the parameters have been properly +904 * configured/initialized. +905 * +906 * @throws BuildException if the task was not configured correctly. +907 */ +908 private void validateConfiguration() throws BuildException { +909 if (path == null) { +910 throw new BuildException("No project dependencies have been defined to analyze."); +911 } +912 if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) { +913 throw new BuildException("Invalid configuration, failBuildOnCVSS must be between 0 and 11."); +914 } +915 } +916 +917 /** +918 * Takes the properties supplied and updates the dependency-check settings. +919 * Additionally, this sets the system properties required to change the +920 * proxy server, port, and connection timeout. +921 * +922 * @throws BuildException thrown when an invalid setting is configured. +923 */ +924 @Override +925 protected void populateSettings() throws BuildException { +926 super.populateSettings(); +927 Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate); +928 Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); +929 Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile); +930 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental); +931 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); +932 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled); +933 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled); +934 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled); +935 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled); +936 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled); +937 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled); +938 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled); +939 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled); +940 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); +941 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled); +942 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); +943 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); +944 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); +945 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); +946 Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy); +947 Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); +948 Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); +949 } +950 +951 /** +952 * Checks to see if a vulnerability has been identified with a CVSS score +953 * that is above the threshold set in the configuration. +954 * +955 * @param dependencies the list of dependency objects +956 * @throws BuildException thrown if a CVSS score is found that is higher +957 * then the threshold set +958 */ +959 private void checkForFailure(List<Dependency> dependencies) throws BuildException { +960 final StringBuilder ids = new StringBuilder(); +961 for (Dependency d : dependencies) { +962 for (Vulnerability v : d.getVulnerabilities()) { +963 if (v.getCvssScore() >= failBuildOnCVSS) { +964 if (ids.length() == 0) { +965 ids.append(v.getName()); +966 } else { +967 ids.append(", ").append(v.getName()); +968 } +969 } +970 } +971 } +972 if (ids.length() > 0) { +973 final String msg = String.format("%n%nDependency-Check Failure:%n" +974 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" +975 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); +976 throw new BuildException(msg); +977 } +978 } +979 +980 /** +981 * Generates a warning message listing a summary of dependencies and their +982 * associated CPE and CVE entries. +983 * +984 * @param dependencies a list of dependency objects +985 */ +986 private void showSummary(List<Dependency> dependencies) { +987 final StringBuilder summary = new StringBuilder(); +988 for (Dependency d : dependencies) { +989 boolean firstEntry = true; +990 final StringBuilder ids = new StringBuilder(); +991 for (Vulnerability v : d.getVulnerabilities()) { +992 if (firstEntry) { +993 firstEntry = false; +994 } else { +995 ids.append(", "); +996 } +997 ids.append(v.getName()); +998 } +999 if (ids.length() > 0) { +1000 summary.append(d.getFileName()).append(" ("); +1001 firstEntry = true; +1002 for (Identifier id : d.getIdentifiers()) { +1003 if (firstEntry) { +1004 firstEntry = false; +1005 } else { +1006 summary.append(", "); +1007 } +1008 summary.append(id.getValue()); +1009 } +1010 summary.append(") : ").append(ids).append(NEW_LINE); +1011 } +1012 } +1013 if (summary.length() > 0) { +1014 final String msg = String.format("%n%n" +1015 + "One or more dependencies were identified with known vulnerabilities:%n%n%s" +1016 + "%n%nSee the dependency-check report for more details.%n%n", summary.toString()); +1017 log(msg, Project.MSG_WARN); 1018 } 1019 } -1020 } +1020 +1021 /** +1022 * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", +1023 * etc.. +1024 */ +1025 public static class ReportFormats extends EnumeratedAttribute { +1026 +1027 /** +1028 * Returns the list of values for the report format. +1029 * +1030 * @return the list of values for the report format +1031 */ +1032 @Override +1033 public String[] getValues() { +1034 int i = 0; +1035 final Format[] formats = Format.values(); +1036 final String[] values = new String[formats.length]; +1037 for (Format format : formats) { +1038 values[i++] = format.name(); +1039 } +1040 return values; +1041 } +1042 } +1043 }
      diff --git a/xref/org/owasp/dependencycheck/taskdefs/package-frame.html b/xref/org/owasp/dependencycheck/taskdefs/package-frame.html index a1e7231b0..c5775904c 100644 --- a/xref/org/owasp/dependencycheck/taskdefs/package-frame.html +++ b/xref/org/owasp/dependencycheck/taskdefs/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.taskdefs diff --git a/xref/org/owasp/dependencycheck/taskdefs/package-summary.html b/xref/org/owasp/dependencycheck/taskdefs/package-summary.html index 909fc4d45..bce254225 100644 --- a/xref/org/owasp/dependencycheck/taskdefs/package-summary.html +++ b/xref/org/owasp/dependencycheck/taskdefs/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.taskdefs + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.taskdefs diff --git a/xref/org/owasp/dependencycheck/utils/Checksum.html b/xref/org/owasp/dependencycheck/utils/Checksum.html index 1ca6881e7..2ed3cd4cc 100644 --- a/xref/org/owasp/dependencycheck/utils/Checksum.html +++ b/xref/org/owasp/dependencycheck/utils/Checksum.html @@ -31,7 +31,7 @@ 23 import java.io.File; 24 import java.io.FileInputStream; 25 import java.io.IOException; -26 import java.nio.MappedByteBuffer; +26 import java.nio.ByteBuffer; 27 import java.nio.channels.FileChannel; 28 import java.security.MessageDigest; 29 import java.security.NoSuchAlgorithmException; @@ -57,99 +57,104 @@ 49 50 /** 51 * <p> -52 * Creates the cryptographic checksum of a given file using the specified algorithm.</p> -53 * -54 * @param algorithm the algorithm to use to calculate the checksum -55 * @param file the file to calculate the checksum for -56 * @return the checksum -57 * @throws IOException when the file does not exist -58 * @throws NoSuchAlgorithmException when an algorithm is specified that does not exist -59 */ -60 public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException { -61 final MessageDigest digest = MessageDigest.getInstance(algorithm); -62 FileInputStream fis = null; -63 try { -64 fis = new FileInputStream(file); -65 final FileChannel ch = fis.getChannel(); -66 long remainingToRead = file.length(); -67 long start = 0; -68 while (remainingToRead > 0) { -69 long amountToRead; -70 if (remainingToRead > Integer.MAX_VALUE) { -71 remainingToRead -= Integer.MAX_VALUE; -72 amountToRead = Integer.MAX_VALUE; -73 } else { -74 amountToRead = remainingToRead; -75 remainingToRead = 0; -76 } -77 final MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, start, amountToRead); -78 digest.update(byteBuffer); -79 start += amountToRead; -80 } -81 } finally { -82 if (fis != null) { -83 try { -84 fis.close(); -85 } catch (IOException ex) { -86 LOGGER.trace("Error closing file '{}'.", file.getName(), ex); -87 } -88 } -89 } -90 return digest.digest(); -91 } -92 -93 /** -94 * Calculates the MD5 checksum of a specified file. -95 * -96 * @param file the file to generate the MD5 checksum -97 * @return the hex representation of the MD5 hash -98 * @throws IOException when the file passed in does not exist -99 * @throws NoSuchAlgorithmException when the MD5 algorithm is not available -100 */ -101 public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException { -102 final byte[] b = getChecksum("MD5", file); -103 return getHex(b); -104 } -105 -106 /** -107 * Calculates the SHA1 checksum of a specified file. -108 * -109 * @param file the file to generate the MD5 checksum -110 * @return the hex representation of the SHA1 hash -111 * @throws IOException when the file passed in does not exist -112 * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available -113 */ -114 public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException { -115 final byte[] b = getChecksum("SHA1", file); -116 return getHex(b); -117 } -118 /** -119 * Hex code characters used in getHex. -120 */ -121 private static final String HEXES = "0123456789abcdef"; -122 +52 * Creates the cryptographic checksum of a given file using the specified +53 * algorithm.</p> +54 * +55 * @param algorithm the algorithm to use to calculate the checksum +56 * @param file the file to calculate the checksum for +57 * @return the checksum +58 * @throws IOException when the file does not exist +59 * @throws NoSuchAlgorithmException when an algorithm is specified that does +60 * not exist +61 */ +62 public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException { +63 final MessageDigest md = MessageDigest.getInstance(algorithm); +64 FileInputStream fis = null; +65 FileChannel ch = null; +66 try { +67 fis = new FileInputStream(file); +68 ch = fis.getChannel(); +69 final ByteBuffer buf = ByteBuffer.allocateDirect(8192); +70 int b = ch.read(buf); +71 while ((b != -1) && (b != 0)) { +72 buf.flip(); +73 final byte[] bytes = new byte[b]; +74 buf.get(bytes); +75 md.update(bytes, 0, b); +76 buf.clear(); +77 b = ch.read(buf); +78 } +79 return md.digest(); +80 } finally { +81 if (ch != null) { +82 try { +83 ch.close(); +84 } catch (IOException ex) { +85 LOGGER.trace("Error closing channel '{}'.", file.getName(), ex); +86 } +87 } +88 if (fis != null) { +89 try { +90 fis.close(); +91 } catch (IOException ex) { +92 LOGGER.trace("Error closing file '{}'.", file.getName(), ex); +93 } +94 } +95 } +96 } +97 +98 /** +99 * Calculates the MD5 checksum of a specified file. +100 * +101 * @param file the file to generate the MD5 checksum +102 * @return the hex representation of the MD5 hash +103 * @throws IOException when the file passed in does not exist +104 * @throws NoSuchAlgorithmException when the MD5 algorithm is not available +105 */ +106 public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException { +107 final byte[] b = getChecksum("MD5", file); +108 return getHex(b); +109 } +110 +111 /** +112 * Calculates the SHA1 checksum of a specified file. +113 * +114 * @param file the file to generate the MD5 checksum +115 * @return the hex representation of the SHA1 hash +116 * @throws IOException when the file passed in does not exist +117 * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available +118 */ +119 public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException { +120 final byte[] b = getChecksum("SHA1", file); +121 return getHex(b); +122 } 123 /** -124 * <p> -125 * Converts a byte array into a hex string.</p> -126 * -127 * <p> -128 * This method was copied from <a -129 * href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p> -130 * -131 * @param raw a byte array -132 * @return the hex representation of the byte array -133 */ -134 public static String getHex(byte[] raw) { -135 if (raw == null) { -136 return null; -137 } -138 final StringBuilder hex = new StringBuilder(2 * raw.length); -139 for (final byte b : raw) { -140 hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F)); -141 } -142 return hex.toString(); -143 } -144 } +124 * Hex code characters used in getHex. +125 */ +126 private static final String HEXES = "0123456789abcdef"; +127 +128 /** +129 * <p> +130 * Converts a byte array into a hex string.</p> +131 * +132 * <p> +133 * This method was copied from <a +134 * href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p> +135 * +136 * @param raw a byte array +137 * @return the hex representation of the byte array +138 */ +139 public static String getHex(byte[] raw) { +140 if (raw == null) { +141 return null; +142 } +143 final StringBuilder hex = new StringBuilder(2 * raw.length); +144 for (final byte b : raw) { +145 hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F)); +146 } +147 return hex.toString(); +148 } +149 }
      diff --git a/xref/org/owasp/dependencycheck/utils/DependencyVersion.html b/xref/org/owasp/dependencycheck/utils/DependencyVersion.html index baa7d9ced..2d6813654 100644 --- a/xref/org/owasp/dependencycheck/utils/DependencyVersion.html +++ b/xref/org/owasp/dependencycheck/utils/DependencyVersion.html @@ -34,236 +34,247 @@ 26 27 /** 28 * <p> -29 * Simple object to track the parts of a version number. The parts are contained in a List such that version 1.2.3 will -30 * be stored as: <code>versionParts[0] = 1; +29 * Simple object to track the parts of a version number. The parts are contained +30 * in a List such that version 1.2.3 will be stored as: <code>versionParts[0] = 1; 31 * versionParts[1] = 2; 32 * versionParts[2] = 3; 33 * </code></p> 34 * <p> -35 * Note, the parser contained in this class expects the version numbers to be separated by periods. If a different -36 * separator is used the parser will likely fail.</p> -37 * -38 * @author Jeremy Long -39 */ -40 public class DependencyVersion implements Iterable<String>, Comparable<DependencyVersion> { -41 -42 /** -43 * Constructor for a empty DependencyVersion. -44 */ -45 public DependencyVersion() { -46 } -47 -48 /** -49 * Constructor for a DependencyVersion that will parse a version string. -50 * <b>Note</b>, this should only be used when the version passed in is already known to be a well formatted version -51 * number. Otherwise, DependencyVersionUtil.parseVersion() should be used instead. -52 * -53 * @param version the well formatted version number to parse -54 */ -55 public DependencyVersion(String version) { -56 parseVersion(version); -57 } -58 -59 /** -60 * Parses a version string into its sub parts: major, minor, revision, build, etc. <b>Note</b>, this should only be -61 * used to parse something that is already known to be a version number. -62 * -63 * @param version the version string to parse -64 */ -65 public final void parseVersion(String version) { -66 versionParts = new ArrayList<String>(); -67 if (version != null) { -68 final Pattern rx = Pattern.compile("(\\d+[a-z]{1,3}$|[a-z]+\\d+|\\d+|(release|beta|alpha)$)"); -69 final Matcher matcher = rx.matcher(version.toLowerCase()); -70 while (matcher.find()) { -71 versionParts.add(matcher.group()); -72 } -73 if (versionParts.isEmpty()) { -74 versionParts.add(version); +35 * Note, the parser contained in this class expects the version numbers to be +36 * separated by periods. If a different separator is used the parser will likely +37 * fail.</p> +38 * +39 * @author Jeremy Long +40 */ +41 public class DependencyVersion implements Iterable<String>, Comparable<DependencyVersion> { +42 +43 /** +44 * Constructor for a empty DependencyVersion. +45 */ +46 public DependencyVersion() { +47 } +48 +49 /** +50 * Constructor for a DependencyVersion that will parse a version string. +51 * <b>Note</b>, this should only be used when the version passed in is +52 * already known to be a well formatted version number. Otherwise, +53 * DependencyVersionUtil.parseVersion() should be used instead. +54 * +55 * @param version the well formatted version number to parse +56 */ +57 public DependencyVersion(String version) { +58 parseVersion(version); +59 } +60 +61 /** +62 * Parses a version string into its sub parts: major, minor, revision, +63 * build, etc. <b>Note</b>, this should only be used to parse something that +64 * is already known to be a version number. +65 * +66 * @param version the version string to parse +67 */ +68 public final void parseVersion(String version) { +69 versionParts = new ArrayList<String>(); +70 if (version != null) { +71 final Pattern rx = Pattern.compile("(\\d+[a-z]{1,3}$|[a-z]+\\d+|\\d+|(release|beta|alpha)$)"); +72 final Matcher matcher = rx.matcher(version.toLowerCase()); +73 while (matcher.find()) { +74 versionParts.add(matcher.group()); 75 } -76 } -77 } -78 /** -79 * A list of the version parts. -80 */ -81 private List<String> versionParts; -82 -83 /** -84 * Get the value of versionParts. -85 * -86 * @return the value of versionParts -87 */ -88 public List<String> getVersionParts() { -89 return versionParts; -90 } -91 -92 /** -93 * Set the value of versionParts. -94 * -95 * @param versionParts new value of versionParts -96 */ -97 public void setVersionParts(List<String> versionParts) { -98 this.versionParts = versionParts; -99 } -100 -101 /** -102 * Retrieves an iterator for the version parts. -103 * -104 * @return an iterator for the version parts -105 */ -106 @Override -107 public Iterator<String> iterator() { -108 return versionParts.iterator(); -109 } -110 -111 /** -112 * Reconstructs the version string from the split version parts. -113 * -114 * @return a string representing the version. -115 */ -116 @Override -117 public String toString() { -118 return StringUtils.join(versionParts, '.'); -119 } -120 -121 /** -122 * Compares the equality of this object to the one passed in as a parameter. -123 * -124 * @param obj the object to compare equality -125 * @return returns true only if the two objects are equal, otherwise false -126 */ -127 @Override -128 public boolean equals(Object obj) { -129 if (obj == null) { -130 return false; -131 } -132 if (getClass() != obj.getClass()) { +76 if (versionParts.isEmpty()) { +77 versionParts.add(version); +78 } +79 } +80 } +81 /** +82 * A list of the version parts. +83 */ +84 private List<String> versionParts; +85 +86 /** +87 * Get the value of versionParts. +88 * +89 * @return the value of versionParts +90 */ +91 public List<String> getVersionParts() { +92 return versionParts; +93 } +94 +95 /** +96 * Set the value of versionParts. +97 * +98 * @param versionParts new value of versionParts +99 */ +100 public void setVersionParts(List<String> versionParts) { +101 this.versionParts = versionParts; +102 } +103 +104 /** +105 * Retrieves an iterator for the version parts. +106 * +107 * @return an iterator for the version parts +108 */ +109 @Override +110 public Iterator<String> iterator() { +111 return versionParts.iterator(); +112 } +113 +114 /** +115 * Reconstructs the version string from the split version parts. +116 * +117 * @return a string representing the version. +118 */ +119 @Override +120 public String toString() { +121 return StringUtils.join(versionParts, '.'); +122 } +123 +124 /** +125 * Compares the equality of this object to the one passed in as a parameter. +126 * +127 * @param obj the object to compare equality +128 * @return returns true only if the two objects are equal, otherwise false +129 */ +130 @Override +131 public boolean equals(Object obj) { +132 if (obj == null) { 133 return false; 134 } -135 final DependencyVersion other = (DependencyVersion) obj; -136 final int max = (this.versionParts.size() < other.versionParts.size()) -137 ? this.versionParts.size() : other.versionParts.size(); -138 //TODO steal better version of code from compareTo -139 for (int i = 0; i < max; i++) { -140 final String thisPart = this.versionParts.get(i); -141 final String otherPart = other.versionParts.get(i); -142 if (!thisPart.equals(otherPart)) { -143 return false; -144 } -145 } -146 if (this.versionParts.size() > max) { -147 for (int i = max; i < this.versionParts.size(); i++) { -148 if (!"0".equals(this.versionParts.get(i))) { -149 return false; -150 } -151 } -152 } -153 -154 if (other.versionParts.size() > max) { -155 for (int i = max; i < other.versionParts.size(); i++) { -156 if (!"0".equals(other.versionParts.get(i))) { -157 return false; -158 } -159 } -160 } -161 -162 /* -163 * if (this.versionParts != other.versionParts && (this.versionParts == null || !this.versionParts.equals(other.versionParts))) { -164 * return false; -165 * } -166 */ -167 return true; -168 } -169 -170 /** -171 * Calculates the hashCode for this object. -172 * -173 * @return the hashCode -174 */ -175 @Override -176 public int hashCode() { -177 int hash = 5; -178 hash = 71 * hash + (this.versionParts != null ? this.versionParts.hashCode() : 0); -179 return hash; -180 } -181 -182 /** -183 * Determines if the three most major major version parts are identical. For instances, if version 1.2.3.4 was -184 * compared to 1.2.3 this function would return true. -185 * -186 * @param version the version number to compare -187 * @return true if the first three major parts of the version are identical -188 */ -189 public boolean matchesAtLeastThreeLevels(DependencyVersion version) { -190 if (version == null) { -191 return false; -192 } -193 if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) { -194 return false; -195 } -196 -197 final int max = (this.versionParts.size() < version.versionParts.size()) -198 ? this.versionParts.size() : version.versionParts.size(); -199 -200 boolean ret = true; -201 for (int i = 0; i < max; i++) { -202 final String thisVersion = this.versionParts.get(i); -203 final String otherVersion = version.getVersionParts().get(i); -204 if (i >= 3) { -205 if (thisVersion.compareToIgnoreCase(otherVersion) >= 0) { -206 ret = false; -207 break; -208 } -209 } else if (!thisVersion.equals(otherVersion)) { -210 ret = false; -211 break; -212 } -213 } -214 -215 return ret; -216 } -217 -218 @Override -219 public int compareTo(DependencyVersion version) { -220 if (version == null) { -221 return 1; -222 } -223 final List<String> left = this.getVersionParts(); -224 final List<String> right = version.getVersionParts(); -225 final int max = left.size() < right.size() ? left.size() : right.size(); -226 -227 for (int i = 0; i < max; i++) { -228 final String lStr = left.get(i); -229 final String rStr = right.get(i); -230 if (lStr.equals(rStr)) { -231 continue; -232 } -233 try { -234 final int l = Integer.parseInt(lStr); -235 final int r = Integer.parseInt(rStr); -236 if (l < r) { -237 return -1; -238 } else if (l > r) { -239 return 1; -240 } -241 } catch (NumberFormatException ex) { -242 final int comp = left.get(i).compareTo(right.get(i)); -243 if (comp < 0) { -244 return -1; -245 } else if (comp > 0) { -246 return 1; -247 } -248 } -249 } -250 if (left.size() < right.size()) { -251 return -1; -252 } else if (left.size() > right.size()) { -253 return 1; -254 } else { -255 return 0; -256 } -257 } -258 } +135 if (getClass() != obj.getClass()) { +136 return false; +137 } +138 final DependencyVersion other = (DependencyVersion) obj; +139 final int minVersionMatchLength = (this.versionParts.size() < other.versionParts.size()) +140 ? this.versionParts.size() : other.versionParts.size(); +141 final int maxVersionMatchLength = (this.versionParts.size() > other.versionParts.size()) +142 ? this.versionParts.size() : other.versionParts.size(); +143 +144 if (minVersionMatchLength == 1 && maxVersionMatchLength >= 3) { +145 return false; +146 } +147 +148 //TODO steal better version of code from compareTo +149 for (int i = 0; i < minVersionMatchLength; i++) { +150 final String thisPart = this.versionParts.get(i); +151 final String otherPart = other.versionParts.get(i); +152 if (!thisPart.equals(otherPart)) { +153 return false; +154 } +155 } +156 if (this.versionParts.size() > minVersionMatchLength) { +157 for (int i = minVersionMatchLength; i < this.versionParts.size(); i++) { +158 if (!"0".equals(this.versionParts.get(i))) { +159 return false; +160 } +161 } +162 } +163 +164 if (other.versionParts.size() > minVersionMatchLength) { +165 for (int i = minVersionMatchLength; i < other.versionParts.size(); i++) { +166 if (!"0".equals(other.versionParts.get(i))) { +167 return false; +168 } +169 } +170 } +171 +172 /* +173 * if (this.versionParts != other.versionParts && (this.versionParts == null || !this.versionParts.equals(other.versionParts))) { +174 * return false; +175 * } +176 */ +177 return true; +178 } +179 +180 /** +181 * Calculates the hashCode for this object. +182 * +183 * @return the hashCode +184 */ +185 @Override +186 public int hashCode() { +187 int hash = 5; +188 hash = 71 * hash + (this.versionParts != null ? this.versionParts.hashCode() : 0); +189 return hash; +190 } +191 +192 /** +193 * Determines if the three most major major version parts are identical. For +194 * instances, if version 1.2.3.4 was compared to 1.2.3 this function would +195 * return true. +196 * +197 * @param version the version number to compare +198 * @return true if the first three major parts of the version are identical +199 */ +200 public boolean matchesAtLeastThreeLevels(DependencyVersion version) { +201 if (version == null) { +202 return false; +203 } +204 if (Math.abs(this.versionParts.size() - version.versionParts.size()) >= 3) { +205 return false; +206 } +207 +208 final int max = (this.versionParts.size() < version.versionParts.size()) +209 ? this.versionParts.size() : version.versionParts.size(); +210 +211 boolean ret = true; +212 for (int i = 0; i < max; i++) { +213 final String thisVersion = this.versionParts.get(i); +214 final String otherVersion = version.getVersionParts().get(i); +215 if (i >= 3) { +216 if (thisVersion.compareToIgnoreCase(otherVersion) >= 0) { +217 ret = false; +218 break; +219 } +220 } else if (!thisVersion.equals(otherVersion)) { +221 ret = false; +222 break; +223 } +224 } +225 +226 return ret; +227 } +228 +229 @Override +230 public int compareTo(DependencyVersion version) { +231 if (version == null) { +232 return 1; +233 } +234 final List<String> left = this.getVersionParts(); +235 final List<String> right = version.getVersionParts(); +236 final int max = left.size() < right.size() ? left.size() : right.size(); +237 +238 for (int i = 0; i < max; i++) { +239 final String lStr = left.get(i); +240 final String rStr = right.get(i); +241 if (lStr.equals(rStr)) { +242 continue; +243 } +244 try { +245 final int l = Integer.parseInt(lStr); +246 final int r = Integer.parseInt(rStr); +247 if (l < r) { +248 return -1; +249 } else if (l > r) { +250 return 1; +251 } +252 } catch (NumberFormatException ex) { +253 final int comp = left.get(i).compareTo(right.get(i)); +254 if (comp < 0) { +255 return -1; +256 } else if (comp > 0) { +257 return 1; +258 } +259 } +260 } +261 if (left.size() < right.size()) { +262 return -1; +263 } else if (left.size() > right.size()) { +264 return 1; +265 } else { +266 return 0; +267 } +268 } +269 }
      diff --git a/xref/org/owasp/dependencycheck/utils/Downloader.html b/xref/org/owasp/dependencycheck/utils/Downloader.html index 1be66e97c..1009b1619 100644 --- a/xref/org/owasp/dependencycheck/utils/Downloader.html +++ b/xref/org/owasp/dependencycheck/utils/Downloader.html @@ -159,204 +159,211 @@ 151 } finally { 152 conn = null; 153 } -154 final String msg = format("Error downloading file %s; unable to connect.", url.toString()); -155 throw new DownloadFailedException(msg, ex); -156 } -157 -158 final String encoding = conn.getContentEncoding(); -159 BufferedOutputStream writer = null; -160 InputStream reader = null; -161 try { -162 if (encoding != null && "gzip".equalsIgnoreCase(encoding)) { -163 reader = new GZIPInputStream(conn.getInputStream()); -164 } else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) { -165 reader = new InflaterInputStream(conn.getInputStream()); -166 } else { -167 reader = conn.getInputStream(); -168 } -169 -170 writer = new BufferedOutputStream(new FileOutputStream(outputPath)); -171 final byte[] buffer = new byte[4096]; -172 int bytesRead; -173 while ((bytesRead = reader.read(buffer)) > 0) { -174 writer.write(buffer, 0, bytesRead); +154 if ("Connection reset".equalsIgnoreCase(ex.getMessage())) { +155 final String msg = format("TLS Connection Reset%nPlease see " +156 + "http://jeremylong.github.io/DependencyCheck/general/tlsfailures.html " +157 + "for more information regarding how to resolve the issue."); +158 LOGGER.error(msg); +159 throw new DownloadFailedException(msg, ex); +160 } +161 final String msg = format("Error downloading file %s; unable to connect.", url.toString()); +162 throw new DownloadFailedException(msg, ex); +163 } +164 +165 final String encoding = conn.getContentEncoding(); +166 BufferedOutputStream writer = null; +167 InputStream reader = null; +168 try { +169 if (encoding != null && "gzip".equalsIgnoreCase(encoding)) { +170 reader = new GZIPInputStream(conn.getInputStream()); +171 } else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) { +172 reader = new InflaterInputStream(conn.getInputStream()); +173 } else { +174 reader = conn.getInputStream(); 175 } -176 LOGGER.debug("Download of {} complete", url.toString()); -177 } catch (IOException ex) { -178 checkForCommonExceptionTypes(ex); -179 final String msg = format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n", -180 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); -181 throw new DownloadFailedException(msg, ex); -182 } catch (Throwable ex) { -183 final String msg = format("Unexpected exception saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n", -184 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); -185 throw new DownloadFailedException(msg, ex); -186 } finally { -187 if (writer != null) { -188 try { -189 writer.close(); -190 } catch (IOException ex) { -191 LOGGER.trace("Error closing the writer in Downloader.", ex); -192 } -193 } -194 if (reader != null) { +176 +177 writer = new BufferedOutputStream(new FileOutputStream(outputPath)); +178 final byte[] buffer = new byte[4096]; +179 int bytesRead; +180 while ((bytesRead = reader.read(buffer)) > 0) { +181 writer.write(buffer, 0, bytesRead); +182 } +183 LOGGER.debug("Download of {} complete", url.toString()); +184 } catch (IOException ex) { +185 checkForCommonExceptionTypes(ex); +186 final String msg = format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n", +187 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); +188 throw new DownloadFailedException(msg, ex); +189 } catch (Throwable ex) { +190 final String msg = format("Unexpected exception saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n", +191 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); +192 throw new DownloadFailedException(msg, ex); +193 } finally { +194 if (writer != null) { 195 try { -196 reader.close(); +196 writer.close(); 197 } catch (IOException ex) { -198 LOGGER.trace("Error closing the reader in Downloader.", ex); +198 LOGGER.trace("Error closing the writer in Downloader.", ex); 199 } 200 } -201 try { -202 conn.disconnect(); -203 } finally { -204 conn = null; -205 } -206 } -207 } -208 } -209 -210 /** -211 * Makes an HTTP Head request to retrieve the last modified date of the -212 * given URL. If the file:// protocol is specified, then the lastTimestamp -213 * of the file is returned. -214 * -215 * @param url the URL to retrieve the timestamp from -216 * @return an epoch timestamp -217 * @throws DownloadFailedException is thrown if an exception occurs making -218 * the HTTP request -219 */ -220 public static long getLastModified(URL url) throws DownloadFailedException { -221 return getLastModified(url, false); -222 } -223 -224 /** -225 * Makes an HTTP Head request to retrieve the last modified date of the -226 * given URL. If the file:// protocol is specified, then the lastTimestamp -227 * of the file is returned. -228 * -229 * @param url the URL to retrieve the timestamp from -230 * @param isRetry indicates if this is a retry - to prevent endless loop and -231 * stack overflow -232 * @return an epoch timestamp -233 * @throws DownloadFailedException is thrown if an exception occurs making -234 * the HTTP request -235 */ -236 private static long getLastModified(URL url, boolean isRetry) throws DownloadFailedException { -237 long timestamp = 0; -238 //TODO add the FTP protocol? -239 if ("file".equalsIgnoreCase(url.getProtocol())) { -240 File lastModifiedFile; -241 try { -242 lastModifiedFile = new File(url.toURI()); -243 } catch (URISyntaxException ex) { -244 final String msg = format("Unable to locate '%s'", url.toString()); -245 throw new DownloadFailedException(msg); -246 } -247 timestamp = lastModifiedFile.lastModified(); -248 } else { -249 final String httpMethod = determineHttpMethod(); -250 HttpURLConnection conn = null; -251 try { -252 conn = URLConnectionFactory.createHttpURLConnection(url); -253 conn.setRequestMethod(httpMethod); -254 conn.connect(); -255 final int t = conn.getResponseCode(); -256 if (t >= 200 && t < 300) { -257 timestamp = conn.getLastModified(); -258 } else { -259 throw new DownloadFailedException(format("%s request returned a non-200 status code", httpMethod)); -260 } -261 } catch (URLConnectionFailureException ex) { -262 throw new DownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex); -263 } catch (IOException ex) { -264 checkForCommonExceptionTypes(ex); -265 LOGGER.error("IO Exception: " + ex.getMessage()); -266 LOGGER.debug("Exception details", ex); -267 if (ex.getCause() != null) { -268 LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause()); -269 } -270 try { -271 //retry -272 if (!isRetry && Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP)) { -273 Settings.setBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, false); -274 return getLastModified(url, true); -275 } -276 } catch (InvalidSettingException ex1) { -277 LOGGER.debug("invalid setting?", ex); -278 } -279 throw new DownloadFailedException(format("Error making HTTP %s request.", httpMethod), ex); -280 } finally { -281 if (conn != null) { -282 try { -283 conn.disconnect(); -284 } finally { -285 conn = null; -286 } -287 } -288 } -289 } -290 return timestamp; -291 } -292 -293 /** -294 * Analyzes the IOException, logs the appropriate information for debugging -295 * purposes, and then throws a DownloadFailedException that wraps the IO -296 * Exception for common IO Exceptions. This is to provide additional details -297 * to assist in resolution of the exception. -298 * -299 * @param ex the original exception -300 * @throws DownloadFailedException a wrapper exception that contains the -301 * original exception as the cause -302 */ -303 protected static synchronized void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException { -304 Throwable cause = ex; -305 while (cause != null) { -306 if (cause instanceof java.net.UnknownHostException) { -307 final String msg = format("Unable to resolve domain '%s'", cause.getMessage()); -308 LOGGER.error(msg); -309 throw new DownloadFailedException(msg); -310 } -311 if (cause instanceof InvalidAlgorithmParameterException) { -312 final String keystore = System.getProperty("javax.net.ssl.keyStore"); -313 final String version = System.getProperty("java.version"); -314 final String vendor = System.getProperty("java.vendor"); -315 LOGGER.info("Error making HTTPS request - InvalidAlgorithmParameterException"); -316 LOGGER.info("There appears to be an issue with the installation of Java and the cacerts." -317 + "See closed issue #177 here: https://github.com/jeremylong/DependencyCheck/issues/177"); -318 LOGGER.info("Java Info:\njavax.net.ssl.keyStore='{}'\njava.version='{}'\njava.vendor='{}'", -319 keystore, version, vendor); -320 throw new DownloadFailedException("Error making HTTPS request. Please see the log for more details."); -321 } -322 cause = cause.getCause(); -323 } -324 } -325 -326 /** -327 * Returns the HEAD or GET HTTP method. HEAD is the default. -328 * -329 * @return the HTTP method to use -330 */ -331 private static String determineHttpMethod() { -332 return isQuickQuery() ? HEAD : GET; -333 } -334 -335 /** -336 * Determines if the HTTP method GET or HEAD should be used to check the -337 * timestamp on external resources. -338 * -339 * @return true if configured to use HEAD requests -340 */ -341 private static boolean isQuickQuery() { -342 boolean quickQuery; -343 -344 try { -345 quickQuery = Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, true); -346 } catch (InvalidSettingException e) { -347 quickQuery = true; -348 } -349 return quickQuery; -350 } -351 } +201 if (reader != null) { +202 try { +203 reader.close(); +204 } catch (IOException ex) { +205 LOGGER.trace("Error closing the reader in Downloader.", ex); +206 } +207 } +208 try { +209 conn.disconnect(); +210 } finally { +211 conn = null; +212 } +213 } +214 } +215 } +216 +217 /** +218 * Makes an HTTP Head request to retrieve the last modified date of the +219 * given URL. If the file:// protocol is specified, then the lastTimestamp +220 * of the file is returned. +221 * +222 * @param url the URL to retrieve the timestamp from +223 * @return an epoch timestamp +224 * @throws DownloadFailedException is thrown if an exception occurs making +225 * the HTTP request +226 */ +227 public static long getLastModified(URL url) throws DownloadFailedException { +228 return getLastModified(url, false); +229 } +230 +231 /** +232 * Makes an HTTP Head request to retrieve the last modified date of the +233 * given URL. If the file:// protocol is specified, then the lastTimestamp +234 * of the file is returned. +235 * +236 * @param url the URL to retrieve the timestamp from +237 * @param isRetry indicates if this is a retry - to prevent endless loop and +238 * stack overflow +239 * @return an epoch timestamp +240 * @throws DownloadFailedException is thrown if an exception occurs making +241 * the HTTP request +242 */ +243 private static long getLastModified(URL url, boolean isRetry) throws DownloadFailedException { +244 long timestamp = 0; +245 //TODO add the FTP protocol? +246 if ("file".equalsIgnoreCase(url.getProtocol())) { +247 File lastModifiedFile; +248 try { +249 lastModifiedFile = new File(url.toURI()); +250 } catch (URISyntaxException ex) { +251 final String msg = format("Unable to locate '%s'", url.toString()); +252 throw new DownloadFailedException(msg); +253 } +254 timestamp = lastModifiedFile.lastModified(); +255 } else { +256 final String httpMethod = determineHttpMethod(); +257 HttpURLConnection conn = null; +258 try { +259 conn = URLConnectionFactory.createHttpURLConnection(url); +260 conn.setRequestMethod(httpMethod); +261 conn.connect(); +262 final int t = conn.getResponseCode(); +263 if (t >= 200 && t < 300) { +264 timestamp = conn.getLastModified(); +265 } else { +266 throw new DownloadFailedException(format("%s request returned a non-200 status code", httpMethod)); +267 } +268 } catch (URLConnectionFailureException ex) { +269 throw new DownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex); +270 } catch (IOException ex) { +271 checkForCommonExceptionTypes(ex); +272 LOGGER.error("IO Exception: " + ex.getMessage()); +273 LOGGER.debug("Exception details", ex); +274 if (ex.getCause() != null) { +275 LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause()); +276 } +277 try { +278 //retry +279 if (!isRetry && Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP)) { +280 Settings.setBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, false); +281 return getLastModified(url, true); +282 } +283 } catch (InvalidSettingException ex1) { +284 LOGGER.debug("invalid setting?", ex); +285 } +286 throw new DownloadFailedException(format("Error making HTTP %s request.", httpMethod), ex); +287 } finally { +288 if (conn != null) { +289 try { +290 conn.disconnect(); +291 } finally { +292 conn = null; +293 } +294 } +295 } +296 } +297 return timestamp; +298 } +299 +300 /** +301 * Analyzes the IOException, logs the appropriate information for debugging +302 * purposes, and then throws a DownloadFailedException that wraps the IO +303 * Exception for common IO Exceptions. This is to provide additional details +304 * to assist in resolution of the exception. +305 * +306 * @param ex the original exception +307 * @throws DownloadFailedException a wrapper exception that contains the +308 * original exception as the cause +309 */ +310 protected static synchronized void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException { +311 Throwable cause = ex; +312 while (cause != null) { +313 if (cause instanceof java.net.UnknownHostException) { +314 final String msg = format("Unable to resolve domain '%s'", cause.getMessage()); +315 LOGGER.error(msg); +316 throw new DownloadFailedException(msg); +317 } +318 if (cause instanceof InvalidAlgorithmParameterException) { +319 final String keystore = System.getProperty("javax.net.ssl.keyStore"); +320 final String version = System.getProperty("java.version"); +321 final String vendor = System.getProperty("java.vendor"); +322 LOGGER.info("Error making HTTPS request - InvalidAlgorithmParameterException"); +323 LOGGER.info("There appears to be an issue with the installation of Java and the cacerts." +324 + "See closed issue #177 here: https://github.com/jeremylong/DependencyCheck/issues/177"); +325 LOGGER.info("Java Info:\njavax.net.ssl.keyStore='{}'\njava.version='{}'\njava.vendor='{}'", +326 keystore, version, vendor); +327 throw new DownloadFailedException("Error making HTTPS request. Please see the log for more details."); +328 } +329 cause = cause.getCause(); +330 } +331 } +332 +333 /** +334 * Returns the HEAD or GET HTTP method. HEAD is the default. +335 * +336 * @return the HTTP method to use +337 */ +338 private static String determineHttpMethod() { +339 return isQuickQuery() ? HEAD : GET; +340 } +341 +342 /** +343 * Determines if the HTTP method GET or HEAD should be used to check the +344 * timestamp on external resources. +345 * +346 * @return true if configured to use HEAD requests +347 */ +348 private static boolean isQuickQuery() { +349 boolean quickQuery; +350 +351 try { +352 quickQuery = Settings.getBoolean(Settings.KEYS.DOWNLOADER_QUICK_QUERY_TIMESTAMP, true); +353 } catch (InvalidSettingException e) { +354 quickQuery = true; +355 } +356 return quickQuery; +357 } +358 }
      diff --git a/xref/org/owasp/dependencycheck/utils/FileUtils.html b/xref/org/owasp/dependencycheck/utils/FileUtils.html index 3c7a93528..1c80c2f61 100644 --- a/xref/org/owasp/dependencycheck/utils/FileUtils.html +++ b/xref/org/owasp/dependencycheck/utils/FileUtils.html @@ -73,51 +73,73 @@ 65 } 66 67 /** -68 * Deletes a file. If the File is a directory it will recursively delete the contents. -69 * -70 * @param file the File to delete -71 * @return true if the file was deleted successfully, otherwise false -72 */ -73 public static boolean delete(File file) { -74 final boolean success = org.apache.commons.io.FileUtils.deleteQuietly(file); -75 if (!success) { -76 LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath()); -77 file.deleteOnExit(); -78 } -79 return success; -80 } -81 -82 /** -83 * Generates a new temporary file name that is guaranteed to be unique. -84 * -85 * @param prefix the prefix for the file name to generate -86 * @param extension the extension of the generated file name -87 * @return a temporary File -88 * @throws java.io.IOException thrown if the temporary folder could not be created -89 */ -90 public static File getTempFile(String prefix, String extension) throws IOException { -91 final File dir = Settings.getTempDirectory(); -92 final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension); -93 final File tempFile = new File(dir, tempFileName); -94 if (tempFile.exists()) { -95 return getTempFile(prefix, extension); -96 } -97 return tempFile; -98 } -99 -100 /** -101 * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for Windows -102 * -103 * @return a String containing the bit bucket -104 */ -105 public static String getBitBucket() { -106 if (SystemUtils.IS_OS_WINDOWS) { -107 return BIT_BUCKET_WIN; -108 } else { -109 return BIT_BUCKET_UNIX; -110 } -111 } -112 } +68 * Deletes a file. If the File is a directory it will recursively delete the +69 * contents. +70 * +71 * @param file the File to delete +72 * @return true if the file was deleted successfully, otherwise false +73 */ +74 public static boolean delete(File file) { +75 final boolean success = org.apache.commons.io.FileUtils.deleteQuietly(file); +76 if (!success) { +77 LOGGER.debug("Failed to delete file: {}; attempting to delete on exit.", file.getPath()); +78 file.deleteOnExit(); +79 } +80 return success; +81 } +82 +83 /** +84 * Creates a unique temporary directory in the given directory. +85 * +86 * @param base the base directory to create a temporary directory within +87 * @return the temporary directory +88 * @throws IOException thrown when a directory cannot be created within the +89 * base directory +90 */ +91 public static File createTempDirectory(File base) throws IOException { +92 final File tempDir = new File(base, "dctemp" + UUID.randomUUID().toString()); +93 if (tempDir.exists()) { +94 return createTempDirectory(base); +95 } +96 if (!tempDir.mkdirs()) { +97 throw new IOException("Could not create temp directory `" + tempDir.getAbsolutePath() + "`"); +98 } +99 return tempDir; +100 } +101 +102 /** +103 * Generates a new temporary file name that is guaranteed to be unique. +104 * +105 * @param prefix the prefix for the file name to generate +106 * @param extension the extension of the generated file name +107 * @return a temporary File +108 * @throws java.io.IOException thrown if the temporary folder could not be +109 * created +110 */ +111 public static File getTempFile(String prefix, String extension) throws IOException { +112 final File dir = Settings.getTempDirectory(); +113 final String tempFileName = String.format("%s%s.%s", prefix, UUID.randomUUID().toString(), extension); +114 final File tempFile = new File(dir, tempFileName); +115 if (tempFile.exists()) { +116 return getTempFile(prefix, extension); +117 } +118 return tempFile; +119 } +120 +121 /** +122 * Return the bit bucket for the OS. '/dev/null' for Unix and 'NUL' for +123 * Windows +124 * +125 * @return a String containing the bit bucket +126 */ +127 public static String getBitBucket() { +128 if (SystemUtils.IS_OS_WINDOWS) { +129 return BIT_BUCKET_WIN; +130 } else { +131 return BIT_BUCKET_UNIX; +132 } +133 } +134 }
      diff --git a/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html b/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html index cd0018537..60955f064 100644 --- a/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html +++ b/xref/org/owasp/dependencycheck/utils/SSLSocketFactoryEx.html @@ -251,50 +251,57 @@ 243 * @return the protocol list 244 */ 245 protected String[] getProtocolList() { -246 final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"}; +246 SSLSocket socket = null; 247 String[] availableProtocols = null; -248 -249 SSLSocket socket = null; -250 -251 try { -252 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); -253 socket = (SSLSocket) factory.createSocket(); -254 -255 availableProtocols = socket.getSupportedProtocols(); -256 Arrays.sort(availableProtocols); -257 } catch (Exception ex) { -258 LOGGER.debug("Error getting protocol list, using TLSv1", ex); -259 return new String[]{"TLSv1"}; -260 } finally { -261 if (socket != null) { -262 try { -263 socket.close(); -264 } catch (IOException ex) { -265 LOGGER.trace("Error closing socket", ex); -266 } -267 } -268 } -269 -270 final List<String> aa = new ArrayList<String>(); -271 for (String preferredProtocol : preferredProtocols) { -272 final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol); -273 if (idx >= 0) { -274 aa.add(preferredProtocol); -275 } -276 } -277 -278 return aa.toArray(new String[0]); -279 } -280 -281 /** -282 * The SSL context. -283 */ -284 private SSLContext sslCtxt; -285 /** -286 * The protocols. -287 */ -288 private String[] protocols; -289 } +248 final String[] preferredProtocols = Settings.getString( +249 Settings.KEYS.DOWNLOADER_TLS_PROTOCOL_LIST, +250 "TLSv1,TLSv1.1,TLSv1.2,TLSv1.3") +251 .split(","); +252 try { +253 final SSLSocketFactory factory = sslCtxt.getSocketFactory(); +254 socket = (SSLSocket) factory.createSocket(); +255 +256 availableProtocols = socket.getSupportedProtocols(); +257 Arrays.sort(availableProtocols); +258 if (LOGGER.isDebugEnabled()) { +259 LOGGER.debug("Available Protocols:"); +260 for (String p : availableProtocols) { +261 LOGGER.debug(p); +262 } +263 } +264 } catch (Exception ex) { +265 LOGGER.debug("Error getting protocol list, using TLSv1", ex); +266 return new String[]{"TLSv1"}; +267 } finally { +268 if (socket != null) { +269 try { +270 socket.close(); +271 } catch (IOException ex) { +272 LOGGER.trace("Error closing socket", ex); +273 } +274 } +275 } +276 +277 final List<String> aa = new ArrayList<String>(); +278 for (String preferredProtocol : preferredProtocols) { +279 final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol); +280 if (idx >= 0) { +281 aa.add(preferredProtocol); +282 } +283 } +284 +285 return aa.toArray(new String[0]); +286 } +287 +288 /** +289 * The SSL context. +290 */ +291 private SSLContext sslCtxt; +292 /** +293 * The protocols. +294 */ +295 private String[] protocols; +296 }
      diff --git a/xref/org/owasp/dependencycheck/utils/Settings.html b/xref/org/owasp/dependencycheck/utils/Settings.html index db25a5eb5..dc706e95e 100644 --- a/xref/org/owasp/dependencycheck/utils/Settings.html +++ b/xref/org/owasp/dependencycheck/utils/Settings.html @@ -301,644 +301,643 @@ 293 */ 294 public static final String ANALYZER_COCOAPODS_ENABLED = "analyzer.cocoapods.enabled"; 295 /** -296 * The properties key for whether the SWIFT package manager analyzer is enabled. -297 */ -298 public static final String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled"; -299 /** -300 * The properties key for the Central search URL. -301 */ -302 public static final String ANALYZER_CENTRAL_URL = "analyzer.central.url"; -303 /** -304 * The path to mono, if available. -305 */ -306 public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path"; -307 /** -308 * The path to bundle-audit, if available. -309 */ -310 public static final String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path"; -311 /** -312 * The additional configured zip file extensions, if available. -313 */ -314 public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip"; -315 /** -316 * The key to obtain the path to the VFEED data file. -317 */ -318 public static final String VFEED_DATA_FILE = "vfeed.data_file"; -319 /** -320 * The key to obtain the VFEED connection string. -321 */ -322 public static final String VFEED_CONNECTION_STRING = "vfeed.connection_string"; -323 -324 /** -325 * The key to obtain the base download URL for the VFeed data file. -326 */ -327 public static final String VFEED_DOWNLOAD_URL = "vfeed.download_url"; -328 /** -329 * The key to obtain the download file name for the VFeed data. -330 */ -331 public static final String VFEED_DOWNLOAD_FILE = "vfeed.download_file"; -332 /** -333 * The key to obtain the VFeed update status. -334 */ -335 public static final String VFEED_UPDATE_STATUS = "vfeed.update_status"; -336 -337 /** -338 * The HTTP request method for query last modified date. -339 */ -340 public static final String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp"; -341 } -342 //</editor-fold> -343 -344 /** -345 * The logger. -346 */ -347 private static final Logger LOGGER = LoggerFactory.getLogger(Settings.class); -348 /** -349 * The properties file location. -350 */ -351 private static final String PROPERTIES_FILE = "dependencycheck.properties"; -352 /** -353 * Thread local settings. -354 */ -355 private static final ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>(); -356 /** -357 * The properties. -358 */ -359 private Properties props = null; -360 +296 * The properties key for whether the SWIFT package manager analyzer is +297 * enabled. +298 */ +299 public static final String ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED = "analyzer.swift.package.manager.enabled"; +300 /** +301 * The properties key for the Central search URL. +302 */ +303 public static final String ANALYZER_CENTRAL_URL = "analyzer.central.url"; +304 /** +305 * The path to mono, if available. +306 */ +307 public static final String ANALYZER_ASSEMBLY_MONO_PATH = "analyzer.assembly.mono.path"; +308 /** +309 * The path to bundle-audit, if available. +310 */ +311 public static final String ANALYZER_BUNDLE_AUDIT_PATH = "analyzer.bundle.audit.path"; +312 /** +313 * The additional configured zip file extensions, if available. +314 */ +315 public static final String ADDITIONAL_ZIP_EXTENSIONS = "extensions.zip"; +316 /** +317 * The key to obtain the path to the VFEED data file. +318 */ +319 public static final String VFEED_DATA_FILE = "vfeed.data_file"; +320 /** +321 * The key to obtain the VFEED connection string. +322 */ +323 public static final String VFEED_CONNECTION_STRING = "vfeed.connection_string"; +324 +325 /** +326 * The key to obtain the base download URL for the VFeed data file. +327 */ +328 public static final String VFEED_DOWNLOAD_URL = "vfeed.download_url"; +329 /** +330 * The key to obtain the download file name for the VFeed data. +331 */ +332 public static final String VFEED_DOWNLOAD_FILE = "vfeed.download_file"; +333 /** +334 * The key to obtain the VFeed update status. +335 */ +336 public static final String VFEED_UPDATE_STATUS = "vfeed.update_status"; +337 +338 /** +339 * The HTTP request method for query last modified date. +340 */ +341 public static final String DOWNLOADER_QUICK_QUERY_TIMESTAMP = "downloader.quick.query.timestamp"; +342 /** +343 * The HTTP protocol list to use. +344 */ +345 public static final String DOWNLOADER_TLS_PROTOCOL_LIST = "downloader.tls.protocols"; +346 } +347 //</editor-fold> +348 +349 /** +350 * The logger. +351 */ +352 private static final Logger LOGGER = LoggerFactory.getLogger(Settings.class); +353 /** +354 * The properties file location. +355 */ +356 private static final String PROPERTIES_FILE = "dependencycheck.properties"; +357 /** +358 * Thread local settings. +359 */ +360 private static final ThreadLocal<Settings> LOCAL_SETTINGS = new ThreadLocal<Settings>(); 361 /** -362 * Private constructor for the Settings class. This class loads the -363 * properties files. -364 * -365 * @param propertiesFilePath the path to the base properties file to load -366 */ -367 private Settings(String propertiesFilePath) { -368 InputStream in = null; -369 props = new Properties(); -370 try { -371 in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath); -372 props.load(in); -373 } catch (IOException ex) { -374 LOGGER.error("Unable to load default settings."); -375 LOGGER.debug("", ex); -376 } finally { -377 if (in != null) { -378 try { -379 in.close(); -380 } catch (IOException ex) { -381 LOGGER.trace("", ex); -382 } -383 } -384 } -385 logProperties("Properties loaded", props); -386 } -387 -388 /** -389 * Initializes the thread local settings object. Note, to use the settings -390 * object you must call this method. However, you must also call -391 * Settings.cleanup() to properly release resources. -392 */ -393 public static void initialize() { -394 LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE)); -395 } -396 -397 /** -398 * Initializes the thread local settings object. Note, to use the settings -399 * object you must call this method. However, you must also call -400 * Settings.cleanup() to properly release resources. -401 * -402 * @param propertiesFilePath the path to the base properties file to load -403 */ -404 public static void initialize(String propertiesFilePath) { -405 LOCAL_SETTINGS.set(new Settings(propertiesFilePath)); -406 } -407 -408 /** -409 * Cleans up resources to prevent memory leaks. -410 * +362 * The properties. +363 */ +364 private Properties props = null; +365 +366 /** +367 * Private constructor for the Settings class. This class loads the +368 * properties files. +369 * +370 * @param propertiesFilePath the path to the base properties file to load +371 */ +372 private Settings(String propertiesFilePath) { +373 InputStream in = null; +374 props = new Properties(); +375 try { +376 in = this.getClass().getClassLoader().getResourceAsStream(propertiesFilePath); +377 props.load(in); +378 } catch (NullPointerException ex) { +379 LOGGER.error("Did not find settings file '{}'.", propertiesFilePath); +380 LOGGER.debug("", ex); +381 } catch (IOException ex) { +382 LOGGER.error("Unable to load settings from '{}'.", propertiesFilePath); +383 LOGGER.debug("", ex); +384 } finally { +385 if (in != null) { +386 try { +387 in.close(); +388 } catch (IOException ex) { +389 LOGGER.trace("", ex); +390 } +391 } +392 } +393 logProperties("Properties loaded", props); +394 } +395 +396 /** +397 * Initializes the thread local settings object. Note, to use the settings +398 * object you must call this method. However, you must also call +399 * Settings.cleanup() to properly release resources. +400 */ +401 public static void initialize() { +402 LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE)); +403 } +404 +405 /** +406 * Initializes the thread local settings object. Note, to use the settings +407 * object you must call this method. However, you must also call +408 * Settings.cleanup() to properly release resources. +409 * +410 * @param propertiesFilePath the path to the base properties file to load 411 */ -412 public static void cleanup() { -413 cleanup(true); +412 public static void initialize(String propertiesFilePath) { +413 LOCAL_SETTINGS.set(new Settings(propertiesFilePath)); 414 } 415 416 /** 417 * Cleans up resources to prevent memory leaks. 418 * -419 * @param deleteTemporary flag indicating whether any temporary directories -420 * generated should be removed -421 */ -422 public static void cleanup(boolean deleteTemporary) { -423 if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) { -424 FileUtils.delete(tempDirectory); -425 if (tempDirectory.exists()) { -426 try { -427 Thread.sleep(2000); -428 } catch (InterruptedException ex) { -429 LOGGER.trace("ignore", ex); -430 } -431 FileUtils.delete(tempDirectory); -432 } -433 } -434 try { -435 LOCAL_SETTINGS.remove(); -436 } catch (Throwable ex) { -437 LOGGER.debug("Error cleaning up Settings", ex); -438 } -439 } -440 -441 /** -442 * Gets the underlying instance of the Settings object. -443 * -444 * @return the Settings object -445 */ -446 public static Settings getInstance() { -447 return LOCAL_SETTINGS.get(); -448 } -449 -450 /** -451 * Sets the instance of the Settings object to use in this thread. -452 * -453 * @param instance the instance of the settings object to use in this thread -454 */ -455 public static void setInstance(Settings instance) { -456 LOCAL_SETTINGS.set(instance); -457 } -458 -459 /** -460 * Logs the properties. This will not log any properties that contain -461 * 'password' in the key. -462 * -463 * @param header the header to print with the log message -464 * @param properties the properties to log -465 */ -466 private static void logProperties(String header, Properties properties) { -467 if (LOGGER.isDebugEnabled()) { -468 final StringWriter sw = new StringWriter(); -469 PrintWriter pw = null; -470 try { -471 pw = new PrintWriter(sw); -472 pw.format("%s:%n%n", header); -473 final Enumeration<?> e = properties.propertyNames(); -474 while (e.hasMoreElements()) { -475 final String key = (String) e.nextElement(); -476 if (key.contains("password")) { -477 pw.format("%s='*****'%n", key); -478 } else { -479 final String value = properties.getProperty(key); -480 if (value != null) { -481 pw.format("%s='%s'%n", key, value); -482 } -483 } -484 } -485 pw.flush(); -486 LOGGER.debug(sw.toString()); -487 } finally { -488 if (pw != null) { -489 pw.close(); -490 } -491 } -492 -493 } -494 } -495 -496 /** -497 * Sets a property value. -498 * -499 * @param key the key for the property -500 * @param value the value for the property -501 */ -502 public static void setString(String key, String value) { -503 LOCAL_SETTINGS.get().props.setProperty(key, value); -504 LOGGER.debug("Setting: {}='{}'", key, value); -505 } -506 -507 /** -508 * Sets a property value only if the value is not null. -509 * -510 * @param key the key for the property -511 * @param value the value for the property -512 */ -513 public static void setStringIfNotNull(String key, String value) { -514 if (null != value) { -515 setString(key, value); -516 } -517 } -518 -519 /** -520 * Sets a property value only if the value is not null and not empty. -521 * -522 * @param key the key for the property -523 * @param value the value for the property -524 */ -525 public static void setStringIfNotEmpty(String key, String value) { -526 if (null != value && !value.isEmpty()) { -527 setString(key, value); -528 } -529 } -530 -531 /** -532 * Sets a property value. -533 * -534 * @param key the key for the property -535 * @param value the value for the property -536 */ -537 public static void setBoolean(String key, boolean value) { -538 setString(key, Boolean.toString(value)); -539 } -540 -541 /** -542 * Sets a property value only if the value is not null. -543 * -544 * @param key the key for the property -545 * @param value the value for the property -546 */ -547 public static void setBooleanIfNotNull(String key, Boolean value) { -548 if (null != value) { -549 setBoolean(key, value); -550 } -551 } -552 -553 /** -554 * Sets a property value. -555 * -556 * @param key the key for the property -557 * @param value the value for the property -558 */ -559 public static void setInt(String key, int value) { -560 LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value)); -561 LOGGER.debug("Setting: {}='{}'", key, value); -562 } -563 -564 /** -565 * Sets a property value only if the value is not null. -566 * -567 * @param key the key for the property -568 * @param value the value for the property -569 */ -570 public static void setIntIfNotNull(String key, Integer value) { -571 if (null != value) { -572 setInt(key, value); -573 } -574 } -575 -576 /** -577 * Merges a new properties file into the current properties. This method -578 * allows for the loading of a user provided properties file.<br><br> -579 * <b>Note</b>: even if using this method - system properties will be loaded -580 * before properties loaded from files. -581 * -582 * @param filePath the path to the properties file to merge. -583 * @throws FileNotFoundException is thrown when the filePath points to a -584 * non-existent file -585 * @throws IOException is thrown when there is an exception loading/merging -586 * the properties -587 */ -588 public static void mergeProperties(File filePath) throws FileNotFoundException, IOException { -589 FileInputStream fis = null; -590 try { -591 fis = new FileInputStream(filePath); -592 mergeProperties(fis); -593 } finally { -594 if (fis != null) { -595 try { -596 fis.close(); -597 } catch (IOException ex) { -598 LOGGER.trace("close error", ex); -599 } -600 } -601 } -602 } -603 -604 /** -605 * Merges a new properties file into the current properties. This method -606 * allows for the loading of a user provided properties file.<br><br> -607 * Note: even if using this method - system properties will be loaded before -608 * properties loaded from files. -609 * -610 * @param filePath the path to the properties file to merge. -611 * @throws FileNotFoundException is thrown when the filePath points to a -612 * non-existent file -613 * @throws IOException is thrown when there is an exception loading/merging -614 * the properties -615 */ -616 public static void mergeProperties(String filePath) throws FileNotFoundException, IOException { -617 FileInputStream fis = null; -618 try { -619 fis = new FileInputStream(filePath); -620 mergeProperties(fis); -621 } finally { -622 if (fis != null) { -623 try { -624 fis.close(); -625 } catch (IOException ex) { -626 LOGGER.trace("close error", ex); -627 } -628 } -629 } -630 } -631 -632 /** -633 * Merges a new properties file into the current properties. This method -634 * allows for the loading of a user provided properties file.<br><br> -635 * <b>Note</b>: even if using this method - system properties will be loaded -636 * before properties loaded from files. -637 * -638 * @param stream an Input Stream pointing at a properties file to merge -639 * @throws IOException is thrown when there is an exception loading/merging -640 * the properties -641 */ -642 public static void mergeProperties(InputStream stream) throws IOException { -643 LOCAL_SETTINGS.get().props.load(stream); -644 logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props); -645 } -646 -647 /** -648 * Returns a value from the properties file as a File object. If the value -649 * was specified as a system property or passed in via the -Dprop=value -650 * argument - this method will return the value from the system properties -651 * before the values in the contained configuration file. -652 * -653 * @param key the key to lookup within the properties file -654 * @return the property from the properties file converted to a File object -655 */ -656 public static File getFile(String key) { -657 final String file = getString(key); -658 if (file == null) { -659 return null; -660 } -661 return new File(file); -662 } -663 -664 /** -665 * Returns a value from the properties file as a File object. If the value -666 * was specified as a system property or passed in via the -Dprop=value -667 * argument - this method will return the value from the system properties -668 * before the values in the contained configuration file. -669 * -670 * This method will check the configured base directory and will use this as -671 * the base of the file path. Additionally, if the base directory begins -672 * with a leading "[JAR]\" sequence with the path to the folder containing -673 * the JAR file containing this class. -674 * -675 * @param key the key to lookup within the properties file -676 * @return the property from the properties file converted to a File object -677 */ -678 protected static File getDataFile(String key) { -679 final String file = getString(key); -680 LOGGER.debug("Settings.getDataFile() - file: '{}'", file); -681 if (file == null) { -682 return null; -683 } -684 if (file.startsWith("[JAR]")) { -685 LOGGER.debug("Settings.getDataFile() - transforming filename"); -686 final File jarPath = getJarPath(); -687 LOGGER.debug("Settings.getDataFile() - jar file: '{}'", jarPath.toString()); -688 final File retVal = new File(jarPath, file.substring(6)); -689 LOGGER.debug("Settings.getDataFile() - returning: '{}'", retVal.toString()); -690 return retVal; -691 } -692 return new File(file); -693 } -694 -695 /** -696 * Attempts to retrieve the folder containing the Jar file containing the -697 * Settings class. -698 * -699 * @return a File object -700 */ -701 private static File getJarPath() { -702 final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath(); -703 String decodedPath = "."; -704 try { -705 decodedPath = URLDecoder.decode(jarPath, "UTF-8"); -706 } catch (UnsupportedEncodingException ex) { -707 LOGGER.trace("", ex); -708 } -709 -710 final File path = new File(decodedPath); -711 if (path.getName().toLowerCase().endsWith(".jar")) { -712 return path.getParentFile(); -713 } else { -714 return new File("."); -715 } -716 } -717 -718 /** -719 * Returns a value from the properties file. If the value was specified as a -720 * system property or passed in via the -Dprop=value argument - this method -721 * will return the value from the system properties before the values in the -722 * contained configuration file. -723 * -724 * @param key the key to lookup within the properties file -725 * @param defaultValue the default value for the requested property -726 * @return the property from the properties file -727 */ -728 public static String getString(String key, String defaultValue) { -729 final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue)); -730 return str; -731 } -732 -733 /** -734 * A reference to the temporary directory; used incase it needs to be -735 * deleted during cleanup. -736 */ -737 private static File tempDirectory = null; -738 -739 /** -740 * Returns the temporary directory. -741 * -742 * @return the temporary directory -743 * @throws java.io.IOException thrown if the temporary directory does not -744 * exist and cannot be created -745 */ -746 public static File getTempDirectory() throws IOException { -747 final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")), "dctemp"); -748 if (!tmpDir.exists() && !tmpDir.mkdirs()) { -749 final String msg = String.format("Unable to make a temporary folder '%s'", tmpDir.getPath()); -750 throw new IOException(msg); +419 */ +420 public static void cleanup() { +421 cleanup(true); +422 } +423 +424 /** +425 * Cleans up resources to prevent memory leaks. +426 * +427 * @param deleteTemporary flag indicating whether any temporary directories +428 * generated should be removed +429 */ +430 public static synchronized void cleanup(boolean deleteTemporary) { +431 if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) { +432 FileUtils.delete(tempDirectory); +433 tempDirectory = null; +434 } +435 try { +436 LOCAL_SETTINGS.remove(); +437 } catch (Throwable ex) { +438 LOGGER.debug("Error cleaning up Settings", ex); +439 } +440 } +441 +442 /** +443 * Gets the underlying instance of the Settings object. +444 * +445 * @return the Settings object +446 */ +447 public static Settings getInstance() { +448 return LOCAL_SETTINGS.get(); +449 } +450 +451 /** +452 * Sets the instance of the Settings object to use in this thread. +453 * +454 * @param instance the instance of the settings object to use in this thread +455 */ +456 public static void setInstance(Settings instance) { +457 LOCAL_SETTINGS.set(instance); +458 } +459 +460 /** +461 * Logs the properties. This will not log any properties that contain +462 * 'password' in the key. +463 * +464 * @param header the header to print with the log message +465 * @param properties the properties to log +466 */ +467 private static void logProperties(String header, Properties properties) { +468 if (LOGGER.isDebugEnabled()) { +469 final StringWriter sw = new StringWriter(); +470 PrintWriter pw = null; +471 try { +472 pw = new PrintWriter(sw); +473 pw.format("%s:%n%n", header); +474 final Enumeration<?> e = properties.propertyNames(); +475 while (e.hasMoreElements()) { +476 final String key = (String) e.nextElement(); +477 if (key.contains("password")) { +478 pw.format("%s='*****'%n", key); +479 } else { +480 final String value = properties.getProperty(key); +481 if (value != null) { +482 pw.format("%s='%s'%n", key, value); +483 } +484 } +485 } +486 pw.flush(); +487 LOGGER.debug(sw.toString()); +488 } finally { +489 if (pw != null) { +490 pw.close(); +491 } +492 } +493 +494 } +495 } +496 +497 /** +498 * Sets a property value. +499 * +500 * @param key the key for the property +501 * @param value the value for the property +502 */ +503 public static void setString(String key, String value) { +504 LOCAL_SETTINGS.get().props.setProperty(key, value); +505 LOGGER.debug("Setting: {}='{}'", key, value); +506 } +507 +508 /** +509 * Sets a property value only if the value is not null. +510 * +511 * @param key the key for the property +512 * @param value the value for the property +513 */ +514 public static void setStringIfNotNull(String key, String value) { +515 if (null != value) { +516 setString(key, value); +517 } +518 } +519 +520 /** +521 * Sets a property value only if the value is not null and not empty. +522 * +523 * @param key the key for the property +524 * @param value the value for the property +525 */ +526 public static void setStringIfNotEmpty(String key, String value) { +527 if (null != value && !value.isEmpty()) { +528 setString(key, value); +529 } +530 } +531 +532 /** +533 * Sets a property value. +534 * +535 * @param key the key for the property +536 * @param value the value for the property +537 */ +538 public static void setBoolean(String key, boolean value) { +539 setString(key, Boolean.toString(value)); +540 } +541 +542 /** +543 * Sets a property value only if the value is not null. +544 * +545 * @param key the key for the property +546 * @param value the value for the property +547 */ +548 public static void setBooleanIfNotNull(String key, Boolean value) { +549 if (null != value) { +550 setBoolean(key, value); +551 } +552 } +553 +554 /** +555 * Sets a property value. +556 * +557 * @param key the key for the property +558 * @param value the value for the property +559 */ +560 public static void setInt(String key, int value) { +561 LOCAL_SETTINGS.get().props.setProperty(key, String.valueOf(value)); +562 LOGGER.debug("Setting: {}='{}'", key, value); +563 } +564 +565 /** +566 * Sets a property value only if the value is not null. +567 * +568 * @param key the key for the property +569 * @param value the value for the property +570 */ +571 public static void setIntIfNotNull(String key, Integer value) { +572 if (null != value) { +573 setInt(key, value); +574 } +575 } +576 +577 /** +578 * Merges a new properties file into the current properties. This method +579 * allows for the loading of a user provided properties file.<br><br> +580 * <b>Note</b>: even if using this method - system properties will be loaded +581 * before properties loaded from files. +582 * +583 * @param filePath the path to the properties file to merge. +584 * @throws FileNotFoundException is thrown when the filePath points to a +585 * non-existent file +586 * @throws IOException is thrown when there is an exception loading/merging +587 * the properties +588 */ +589 public static void mergeProperties(File filePath) throws FileNotFoundException, IOException { +590 FileInputStream fis = null; +591 try { +592 fis = new FileInputStream(filePath); +593 mergeProperties(fis); +594 } finally { +595 if (fis != null) { +596 try { +597 fis.close(); +598 } catch (IOException ex) { +599 LOGGER.trace("close error", ex); +600 } +601 } +602 } +603 } +604 +605 /** +606 * Merges a new properties file into the current properties. This method +607 * allows for the loading of a user provided properties file.<br><br> +608 * Note: even if using this method - system properties will be loaded before +609 * properties loaded from files. +610 * +611 * @param filePath the path to the properties file to merge. +612 * @throws FileNotFoundException is thrown when the filePath points to a +613 * non-existent file +614 * @throws IOException is thrown when there is an exception loading/merging +615 * the properties +616 */ +617 public static void mergeProperties(String filePath) throws FileNotFoundException, IOException { +618 FileInputStream fis = null; +619 try { +620 fis = new FileInputStream(filePath); +621 mergeProperties(fis); +622 } finally { +623 if (fis != null) { +624 try { +625 fis.close(); +626 } catch (IOException ex) { +627 LOGGER.trace("close error", ex); +628 } +629 } +630 } +631 } +632 +633 /** +634 * Merges a new properties file into the current properties. This method +635 * allows for the loading of a user provided properties file.<br><br> +636 * <b>Note</b>: even if using this method - system properties will be loaded +637 * before properties loaded from files. +638 * +639 * @param stream an Input Stream pointing at a properties file to merge +640 * @throws IOException is thrown when there is an exception loading/merging +641 * the properties +642 */ +643 public static void mergeProperties(InputStream stream) throws IOException { +644 LOCAL_SETTINGS.get().props.load(stream); +645 logProperties("Properties updated via merge", LOCAL_SETTINGS.get().props); +646 } +647 +648 /** +649 * Returns a value from the properties file as a File object. If the value +650 * was specified as a system property or passed in via the -Dprop=value +651 * argument - this method will return the value from the system properties +652 * before the values in the contained configuration file. +653 * +654 * @param key the key to lookup within the properties file +655 * @return the property from the properties file converted to a File object +656 */ +657 public static File getFile(String key) { +658 final String file = getString(key); +659 if (file == null) { +660 return null; +661 } +662 return new File(file); +663 } +664 +665 /** +666 * Returns a value from the properties file as a File object. If the value +667 * was specified as a system property or passed in via the -Dprop=value +668 * argument - this method will return the value from the system properties +669 * before the values in the contained configuration file. +670 * +671 * This method will check the configured base directory and will use this as +672 * the base of the file path. Additionally, if the base directory begins +673 * with a leading "[JAR]\" sequence with the path to the folder containing +674 * the JAR file containing this class. +675 * +676 * @param key the key to lookup within the properties file +677 * @return the property from the properties file converted to a File object +678 */ +679 protected static File getDataFile(String key) { +680 final String file = getString(key); +681 LOGGER.debug("Settings.getDataFile() - file: '{}'", file); +682 if (file == null) { +683 return null; +684 } +685 if (file.startsWith("[JAR]")) { +686 LOGGER.debug("Settings.getDataFile() - transforming filename"); +687 final File jarPath = getJarPath(); +688 LOGGER.debug("Settings.getDataFile() - jar file: '{}'", jarPath.toString()); +689 final File retVal = new File(jarPath, file.substring(6)); +690 LOGGER.debug("Settings.getDataFile() - returning: '{}'", retVal.toString()); +691 return retVal; +692 } +693 return new File(file); +694 } +695 +696 /** +697 * Attempts to retrieve the folder containing the Jar file containing the +698 * Settings class. +699 * +700 * @return a File object +701 */ +702 private static File getJarPath() { +703 final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath(); +704 String decodedPath = "."; +705 try { +706 decodedPath = URLDecoder.decode(jarPath, "UTF-8"); +707 } catch (UnsupportedEncodingException ex) { +708 LOGGER.trace("", ex); +709 } +710 +711 final File path = new File(decodedPath); +712 if (path.getName().toLowerCase().endsWith(".jar")) { +713 return path.getParentFile(); +714 } else { +715 return new File("."); +716 } +717 } +718 +719 /** +720 * Returns a value from the properties file. If the value was specified as a +721 * system property or passed in via the -Dprop=value argument - this method +722 * will return the value from the system properties before the values in the +723 * contained configuration file. +724 * +725 * @param key the key to lookup within the properties file +726 * @param defaultValue the default value for the requested property +727 * @return the property from the properties file +728 */ +729 public static String getString(String key, String defaultValue) { +730 final String str = System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key, defaultValue)); +731 return str; +732 } +733 +734 /** +735 * A reference to the temporary directory; used incase it needs to be +736 * deleted during cleanup. +737 */ +738 private static File tempDirectory = null; +739 +740 /** +741 * Returns the temporary directory. +742 * +743 * @return the temporary directory +744 * @throws java.io.IOException thrown if the temporary directory does not +745 * exist and cannot be created +746 */ +747 public static synchronized File getTempDirectory() throws IOException { +748 if (tempDirectory == null) { +749 final File baseTemp = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir"))); +750 tempDirectory = FileUtils.createTempDirectory(baseTemp); 751 } -752 tempDirectory = tmpDir; -753 return tmpDir; -754 } -755 -756 /** -757 * Returns a value from the properties file. If the value was specified as a -758 * system property or passed in via the -Dprop=value argument - this method -759 * will return the value from the system properties before the values in the -760 * contained configuration file. -761 * -762 * @param key the key to lookup within the properties file -763 * @return the property from the properties file -764 */ -765 public static String getString(String key) { -766 return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key)); -767 } -768 -769 /** -770 * Removes a property from the local properties collection. This is mainly -771 * used in test cases. -772 * -773 * @param key the property key to remove -774 */ -775 public static void removeProperty(String key) { -776 LOCAL_SETTINGS.get().props.remove(key); -777 } -778 -779 /** -780 * Returns an int value from the properties file. If the value was specified -781 * as a system property or passed in via the -Dprop=value argument - this -782 * method will return the value from the system properties before the values -783 * in the contained configuration file. -784 * -785 * @param key the key to lookup within the properties file -786 * @return the property from the properties file -787 * @throws InvalidSettingException is thrown if there is an error retrieving -788 * the setting -789 */ -790 public static int getInt(String key) throws InvalidSettingException { -791 try { -792 return Integer.parseInt(Settings.getString(key)); -793 } catch (NumberFormatException ex) { -794 throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex); -795 } -796 } -797 -798 /** -799 * Returns an int value from the properties file. If the value was specified -800 * as a system property or passed in via the -Dprop=value argument - this -801 * method will return the value from the system properties before the values -802 * in the contained configuration file. -803 * -804 * @param key the key to lookup within the properties file -805 * @param defaultValue the default value to return -806 * @return the property from the properties file or the defaultValue if the -807 * property does not exist or cannot be converted to an integer -808 */ -809 public static int getInt(String key, int defaultValue) { -810 int value; -811 try { -812 value = Integer.parseInt(Settings.getString(key)); -813 } catch (NumberFormatException ex) { -814 if (!Settings.getString(key, "").isEmpty()) { -815 LOGGER.debug("Could not convert property '{}={}' to an int; using {} instead.", key, Settings.getString(key), defaultValue); -816 } -817 value = defaultValue; -818 } -819 return value; -820 } -821 -822 /** -823 * Returns a long value from the properties file. If the value was specified -824 * as a system property or passed in via the -Dprop=value argument - this -825 * method will return the value from the system properties before the values -826 * in the contained configuration file. -827 * -828 * @param key the key to lookup within the properties file -829 * @return the property from the properties file -830 * @throws InvalidSettingException is thrown if there is an error retrieving -831 * the setting -832 */ -833 public static long getLong(String key) throws InvalidSettingException { -834 try { -835 return Long.parseLong(Settings.getString(key)); -836 } catch (NumberFormatException ex) { -837 throw new InvalidSettingException("Could not convert property '" + key + "' to a long.", ex); -838 } -839 } -840 -841 /** -842 * Returns a boolean value from the properties file. If the value was -843 * specified as a system property or passed in via the -844 * <code>-Dprop=value</code> argument this method will return the value from -845 * the system properties before the values in the contained configuration -846 * file. -847 * -848 * @param key the key to lookup within the properties file -849 * @return the property from the properties file -850 * @throws InvalidSettingException is thrown if there is an error retrieving -851 * the setting -852 */ -853 public static boolean getBoolean(String key) throws InvalidSettingException { -854 return Boolean.parseBoolean(Settings.getString(key)); -855 } -856 -857 /** -858 * Returns a boolean value from the properties file. If the value was -859 * specified as a system property or passed in via the -860 * <code>-Dprop=value</code> argument this method will return the value from -861 * the system properties before the values in the contained configuration -862 * file. -863 * -864 * @param key the key to lookup within the properties file -865 * @param defaultValue the default value to return if the setting does not -866 * exist -867 * @return the property from the properties file -868 * @throws InvalidSettingException is thrown if there is an error retrieving -869 * the setting -870 */ -871 public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException { -872 return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue))); -873 } -874 -875 /** -876 * Returns a connection string from the configured properties. If the -877 * connection string contains a %s, this method will determine the 'data' -878 * directory and replace the %s with the path to the data directory. If the -879 * data directory does not exists it will be created. -880 * -881 * @param connectionStringKey the property file key for the connection -882 * string -883 * @param dbFileNameKey the settings key for the db filename -884 * @return the connection string -885 * @throws IOException thrown the data directory cannot be created -886 * @throws InvalidSettingException thrown if there is an invalid setting -887 */ -888 public static String getConnectionString(String connectionStringKey, String dbFileNameKey) -889 throws IOException, InvalidSettingException { -890 final String connStr = Settings.getString(connectionStringKey); -891 if (connStr == null) { -892 final String msg = String.format("Invalid properties file; %s is missing.", connectionStringKey); -893 throw new InvalidSettingException(msg); -894 } -895 if (connStr.contains("%s")) { -896 final File directory = getDataDirectory(); -897 String fileName = null; -898 if (dbFileNameKey != null) { -899 fileName = Settings.getString(dbFileNameKey); -900 } -901 if (fileName == null) { -902 final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.", -903 dbFileNameKey); -904 throw new InvalidSettingException(msg); -905 } -906 if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) { -907 fileName = fileName.substring(0, fileName.length() - 6); -908 } -909 // yes, for H2 this path won't actually exists - but this is sufficient to get the value needed -910 final File dbFile = new File(directory, fileName); -911 final String cString = String.format(connStr, dbFile.getCanonicalPath()); -912 LOGGER.debug("Connection String: '{}'", cString); -913 return cString; -914 } -915 return connStr; -916 } -917 -918 /** -919 * Retrieves the directory that the JAR file exists in so that we can ensure -920 * we always use a common data directory for the embedded H2 database. This -921 * is public solely for some unit tests; otherwise this should be private. -922 * -923 * @return the data directory to store data files -924 * @throws IOException is thrown if an IOException occurs of course... -925 */ -926 public static File getDataDirectory() throws IOException { -927 final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY); -928 if (path.exists() || path.mkdirs()) { -929 return path; -930 } -931 throw new IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath())); -932 } -933 } +752 return tempDirectory; +753 } +754 +755 /** +756 * Returns a value from the properties file. If the value was specified as a +757 * system property or passed in via the -Dprop=value argument - this method +758 * will return the value from the system properties before the values in the +759 * contained configuration file. +760 * +761 * @param key the key to lookup within the properties file +762 * @return the property from the properties file +763 */ +764 public static String getString(String key) { +765 return System.getProperty(key, LOCAL_SETTINGS.get().props.getProperty(key)); +766 } +767 +768 /** +769 * Removes a property from the local properties collection. This is mainly +770 * used in test cases. +771 * +772 * @param key the property key to remove +773 */ +774 public static void removeProperty(String key) { +775 LOCAL_SETTINGS.get().props.remove(key); +776 } +777 +778 /** +779 * Returns an int value from the properties file. If the value was specified +780 * as a system property or passed in via the -Dprop=value argument - this +781 * method will return the value from the system properties before the values +782 * in the contained configuration file. +783 * +784 * @param key the key to lookup within the properties file +785 * @return the property from the properties file +786 * @throws InvalidSettingException is thrown if there is an error retrieving +787 * the setting +788 */ +789 public static int getInt(String key) throws InvalidSettingException { +790 try { +791 return Integer.parseInt(Settings.getString(key)); +792 } catch (NumberFormatException ex) { +793 throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex); +794 } +795 } +796 +797 /** +798 * Returns an int value from the properties file. If the value was specified +799 * as a system property or passed in via the -Dprop=value argument - this +800 * method will return the value from the system properties before the values +801 * in the contained configuration file. +802 * +803 * @param key the key to lookup within the properties file +804 * @param defaultValue the default value to return +805 * @return the property from the properties file or the defaultValue if the +806 * property does not exist or cannot be converted to an integer +807 */ +808 public static int getInt(String key, int defaultValue) { +809 int value; +810 try { +811 value = Integer.parseInt(Settings.getString(key)); +812 } catch (NumberFormatException ex) { +813 if (!Settings.getString(key, "").isEmpty()) { +814 LOGGER.debug("Could not convert property '{}={}' to an int; using {} instead.", key, Settings.getString(key), defaultValue); +815 } +816 value = defaultValue; +817 } +818 return value; +819 } +820 +821 /** +822 * Returns a long value from the properties file. If the value was specified +823 * as a system property or passed in via the -Dprop=value argument - this +824 * method will return the value from the system properties before the values +825 * in the contained configuration file. +826 * +827 * @param key the key to lookup within the properties file +828 * @return the property from the properties file +829 * @throws InvalidSettingException is thrown if there is an error retrieving +830 * the setting +831 */ +832 public static long getLong(String key) throws InvalidSettingException { +833 try { +834 return Long.parseLong(Settings.getString(key)); +835 } catch (NumberFormatException ex) { +836 throw new InvalidSettingException("Could not convert property '" + key + "' to a long.", ex); +837 } +838 } +839 +840 /** +841 * Returns a boolean value from the properties file. If the value was +842 * specified as a system property or passed in via the +843 * <code>-Dprop=value</code> argument this method will return the value from +844 * the system properties before the values in the contained configuration +845 * file. +846 * +847 * @param key the key to lookup within the properties file +848 * @return the property from the properties file +849 * @throws InvalidSettingException is thrown if there is an error retrieving +850 * the setting +851 */ +852 public static boolean getBoolean(String key) throws InvalidSettingException { +853 return Boolean.parseBoolean(Settings.getString(key)); +854 } +855 +856 /** +857 * Returns a boolean value from the properties file. If the value was +858 * specified as a system property or passed in via the +859 * <code>-Dprop=value</code> argument this method will return the value from +860 * the system properties before the values in the contained configuration +861 * file. +862 * +863 * @param key the key to lookup within the properties file +864 * @param defaultValue the default value to return if the setting does not +865 * exist +866 * @return the property from the properties file +867 * @throws InvalidSettingException is thrown if there is an error retrieving +868 * the setting +869 */ +870 public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException { +871 return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue))); +872 } +873 +874 /** +875 * Returns a connection string from the configured properties. If the +876 * connection string contains a %s, this method will determine the 'data' +877 * directory and replace the %s with the path to the data directory. If the +878 * data directory does not exists it will be created. +879 * +880 * @param connectionStringKey the property file key for the connection +881 * string +882 * @param dbFileNameKey the settings key for the db filename +883 * @return the connection string +884 * @throws IOException thrown the data directory cannot be created +885 * @throws InvalidSettingException thrown if there is an invalid setting +886 */ +887 public static String getConnectionString(String connectionStringKey, String dbFileNameKey) +888 throws IOException, InvalidSettingException { +889 final String connStr = Settings.getString(connectionStringKey); +890 if (connStr == null) { +891 final String msg = String.format("Invalid properties file; %s is missing.", connectionStringKey); +892 throw new InvalidSettingException(msg); +893 } +894 if (connStr.contains("%s")) { +895 final File directory = getDataDirectory(); +896 String fileName = null; +897 if (dbFileNameKey != null) { +898 fileName = Settings.getString(dbFileNameKey); +899 } +900 if (fileName == null) { +901 final String msg = String.format("Invalid properties file to get a file based connection string; '%s' must be defined.", +902 dbFileNameKey); +903 throw new InvalidSettingException(msg); +904 } +905 if (connStr.startsWith("jdbc:h2:file:") && fileName.endsWith(".h2.db")) { +906 fileName = fileName.substring(0, fileName.length() - 6); +907 } +908 // yes, for H2 this path won't actually exists - but this is sufficient to get the value needed +909 final File dbFile = new File(directory, fileName); +910 final String cString = String.format(connStr, dbFile.getCanonicalPath()); +911 LOGGER.debug("Connection String: '{}'", cString); +912 return cString; +913 } +914 return connStr; +915 } +916 +917 /** +918 * Retrieves the directory that the JAR file exists in so that we can ensure +919 * we always use a common data directory for the embedded H2 database. This +920 * is public solely for some unit tests; otherwise this should be private. +921 * +922 * @return the data directory to store data files +923 * @throws IOException is thrown if an IOException occurs of course... +924 */ +925 public static File getDataDirectory() throws IOException { +926 final File path = Settings.getDataFile(Settings.KEYS.DATA_DIRECTORY); +927 if (path.exists() || path.mkdirs()) { +928 return path; +929 } +930 throw new IOException(String.format("Unable to create the data directory '%s'", path.getAbsolutePath())); +931 } +932 }
      diff --git a/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html b/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html index cbb6a4306..2066cc451 100644 --- a/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html +++ b/xref/org/owasp/dependencycheck/utils/URLConnectionFactory.html @@ -206,7 +206,7 @@ 198 } catch (NoSuchAlgorithmException ex) { 199 LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex); 200 } catch (KeyManagementException ex) { -201 LOGGER.debug("Key mnagement eception in SSLSocketFactoryEx", ex); +201 LOGGER.debug("Key management exception in SSLSocketFactoryEx", ex); 202 } 203 } 204 } diff --git a/xref/org/owasp/dependencycheck/utils/package-frame.html b/xref/org/owasp/dependencycheck/utils/package-frame.html index 510c411f0..0530b3e6e 100644 --- a/xref/org/owasp/dependencycheck/utils/package-frame.html +++ b/xref/org/owasp/dependencycheck/utils/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/xref/org/owasp/dependencycheck/utils/package-summary.html b/xref/org/owasp/dependencycheck/utils/package-summary.html index a1326aa1e..29f8cb6fa 100644 --- a/xref/org/owasp/dependencycheck/utils/package-summary.html +++ b/xref/org/owasp/dependencycheck/utils/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.utils + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.utils diff --git a/xref/org/owasp/dependencycheck/xml/hints/HintParser.html b/xref/org/owasp/dependencycheck/xml/hints/HintParser.html index 7ffb4ffda..bab80dd83 100644 --- a/xref/org/owasp/dependencycheck/xml/hints/HintParser.html +++ b/xref/org/owasp/dependencycheck/xml/hints/HintParser.html @@ -117,50 +117,51 @@ 109 schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA); 110 final HintHandler handler = new HintHandler(); 111 final SAXParserFactory factory = SAXParserFactory.newInstance(); -112 factory.setNamespaceAware(true); -113 factory.setValidating(true); -114 final SAXParser saxParser = factory.newSAXParser(); -115 saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA); -116 saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -117 final XMLReader xmlReader = saxParser.getXMLReader(); -118 xmlReader.setErrorHandler(new HintErrorHandler()); -119 xmlReader.setContentHandler(handler); -120 -121 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -122 final InputSource in = new InputSource(reader); -123 -124 xmlReader.parse(in); -125 final Hints hints = new Hints(); -126 hints.setHintRules(handler.getHintRules()); -127 hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules()); -128 return hints; -129 } catch (ParserConfigurationException ex) { -130 LOGGER.debug("", ex); -131 throw new HintParseException(ex); -132 } catch (SAXException ex) { -133 if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) { -134 throw ex; -135 } else { -136 LOGGER.debug("", ex); -137 throw new HintParseException(ex); -138 } -139 } catch (FileNotFoundException ex) { -140 LOGGER.debug("", ex); -141 throw new HintParseException(ex); -142 } catch (IOException ex) { -143 LOGGER.debug("", ex); -144 throw new HintParseException(ex); -145 } finally { -146 if (schemaStream != null) { -147 try { -148 schemaStream.close(); -149 } catch (IOException ex) { -150 LOGGER.debug("Error closing hint file stream", ex); -151 } -152 } -153 } -154 } -155 } +112 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +113 factory.setNamespaceAware(true); +114 factory.setValidating(true); +115 final SAXParser saxParser = factory.newSAXParser(); +116 saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA); +117 saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); +118 final XMLReader xmlReader = saxParser.getXMLReader(); +119 xmlReader.setErrorHandler(new HintErrorHandler()); +120 xmlReader.setContentHandler(handler); +121 +122 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); +123 final InputSource in = new InputSource(reader); +124 +125 xmlReader.parse(in); +126 final Hints hints = new Hints(); +127 hints.setHintRules(handler.getHintRules()); +128 hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules()); +129 return hints; +130 } catch (ParserConfigurationException ex) { +131 LOGGER.debug("", ex); +132 throw new HintParseException(ex); +133 } catch (SAXException ex) { +134 if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) { +135 throw ex; +136 } else { +137 LOGGER.debug("", ex); +138 throw new HintParseException(ex); +139 } +140 } catch (FileNotFoundException ex) { +141 LOGGER.debug("", ex); +142 throw new HintParseException(ex); +143 } catch (IOException ex) { +144 LOGGER.debug("", ex); +145 throw new HintParseException(ex); +146 } finally { +147 if (schemaStream != null) { +148 try { +149 schemaStream.close(); +150 } catch (IOException ex) { +151 LOGGER.debug("Error closing hint file stream", ex); +152 } +153 } +154 } +155 } +156 }
      diff --git a/xref/org/owasp/dependencycheck/xml/hints/package-frame.html b/xref/org/owasp/dependencycheck/xml/hints/package-frame.html index 5f8695c7e..8bc59978b 100644 --- a/xref/org/owasp/dependencycheck/xml/hints/package-frame.html +++ b/xref/org/owasp/dependencycheck/xml/hints/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/xref/org/owasp/dependencycheck/xml/hints/package-summary.html b/xref/org/owasp/dependencycheck/xml/hints/package-summary.html index 69804e1a0..1591d84d4 100644 --- a/xref/org/owasp/dependencycheck/xml/hints/package-summary.html +++ b/xref/org/owasp/dependencycheck/xml/hints/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.hints + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.xml.hints diff --git a/xref/org/owasp/dependencycheck/xml/pom/Model.html b/xref/org/owasp/dependencycheck/xml/pom/Model.html index ae086b16f..448a24c5d 100644 --- a/xref/org/owasp/dependencycheck/xml/pom/Model.html +++ b/xref/org/owasp/dependencycheck/xml/pom/Model.html @@ -356,7 +356,7 @@ 348 * Utility class that can provide values from a Properties object to a 349 * StrSubstitutor. 350 */ -351 private static class PropertyLookup extends StrLookup { +351 private static class PropertyLookup extends StrLookup<String> { 352 353 /** 354 * Reference to the properties to lookup. diff --git a/xref/org/owasp/dependencycheck/xml/pom/PomParser.html b/xref/org/owasp/dependencycheck/xml/pom/PomParser.html index daa097f12..1cdc873b2 100644 --- a/xref/org/owasp/dependencycheck/xml/pom/PomParser.html +++ b/xref/org/owasp/dependencycheck/xml/pom/PomParser.html @@ -55,70 +55,74 @@ 47 private static final Logger LOGGER = LoggerFactory.getLogger(PomParser.class); 48 49 /** -50 * Parses the given xml file and returns a Model object containing only the fields dependency-check requires. -51 * -52 * @param file a pom.xml -53 * @return a Model object containing only the fields dependency-check requires -54 * @throws PomParseException thrown if the xml file cannot be parsed -55 */ -56 public Model parse(File file) throws PomParseException { -57 FileInputStream fis = null; -58 try { -59 fis = new FileInputStream(file); -60 return parse(fis); -61 } catch (IOException ex) { -62 LOGGER.debug("", ex); -63 throw new PomParseException(ex); -64 } finally { -65 if (fis != null) { -66 try { -67 fis.close(); -68 } catch (IOException ex) { -69 LOGGER.debug("Unable to close stream", ex); -70 } -71 } -72 } -73 } -74 -75 /** -76 * Parses the given XML file and returns a Model object containing only the fields dependency-check requires. -77 * -78 * @param inputStream an InputStream containing suppression rues -79 * @return a list of suppression rules -80 * @throws PomParseException if the XML cannot be parsed -81 */ -82 public Model parse(InputStream inputStream) throws PomParseException { -83 try { -84 final PomHandler handler = new PomHandler(); -85 final SAXParserFactory factory = SAXParserFactory.newInstance(); -86 // factory.setNamespaceAware(true); -87 // factory.setValidating(true); -88 final SAXParser saxParser = factory.newSAXParser(); -89 final XMLReader xmlReader = saxParser.getXMLReader(); -90 xmlReader.setContentHandler(handler); -91 -92 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -93 final InputSource in = new InputSource(reader); -94 //in.setEncoding("UTF-8"); +50 * Parses the given xml file and returns a Model object containing only the +51 * fields dependency-check requires. +52 * +53 * @param file a pom.xml +54 * @return a Model object containing only the fields dependency-check +55 * requires +56 * @throws PomParseException thrown if the xml file cannot be parsed +57 */ +58 public Model parse(File file) throws PomParseException { +59 FileInputStream fis = null; +60 try { +61 fis = new FileInputStream(file); +62 return parse(fis); +63 } catch (IOException ex) { +64 LOGGER.debug("", ex); +65 throw new PomParseException(ex); +66 } finally { +67 if (fis != null) { +68 try { +69 fis.close(); +70 } catch (IOException ex) { +71 LOGGER.debug("Unable to close stream", ex); +72 } +73 } +74 } +75 } +76 +77 /** +78 * Parses the given XML file and returns a Model object containing only the +79 * fields dependency-check requires. +80 * +81 * @param inputStream an InputStream containing suppression rues +82 * @return a list of suppression rules +83 * @throws PomParseException if the XML cannot be parsed +84 */ +85 public Model parse(InputStream inputStream) throws PomParseException { +86 try { +87 final PomHandler handler = new PomHandler(); +88 final SAXParserFactory factory = SAXParserFactory.newInstance(); +89 // factory.setNamespaceAware(true); +90 // factory.setValidating(true); +91 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +92 final SAXParser saxParser = factory.newSAXParser(); +93 final XMLReader xmlReader = saxParser.getXMLReader(); +94 xmlReader.setContentHandler(handler); 95 -96 xmlReader.parse(in); -97 -98 return handler.getModel(); -99 } catch (ParserConfigurationException ex) { -100 LOGGER.debug("", ex); -101 throw new PomParseException(ex); -102 } catch (SAXException ex) { -103 LOGGER.debug("", ex); -104 throw new PomParseException(ex); -105 } catch (FileNotFoundException ex) { -106 LOGGER.debug("", ex); -107 throw new PomParseException(ex); -108 } catch (IOException ex) { -109 LOGGER.debug("", ex); -110 throw new PomParseException(ex); -111 } -112 } -113 } +96 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); +97 final InputSource in = new InputSource(reader); +98 //in.setEncoding("UTF-8"); +99 +100 xmlReader.parse(in); +101 +102 return handler.getModel(); +103 } catch (ParserConfigurationException ex) { +104 LOGGER.debug("", ex); +105 throw new PomParseException(ex); +106 } catch (SAXException ex) { +107 LOGGER.debug("", ex); +108 throw new PomParseException(ex); +109 } catch (FileNotFoundException ex) { +110 LOGGER.debug("", ex); +111 throw new PomParseException(ex); +112 } catch (IOException ex) { +113 LOGGER.debug("", ex); +114 throw new PomParseException(ex); +115 } +116 } +117 }
      diff --git a/xref/org/owasp/dependencycheck/xml/pom/package-frame.html b/xref/org/owasp/dependencycheck/xml/pom/package-frame.html index fc7973b24..1e201a98f 100644 --- a/xref/org/owasp/dependencycheck/xml/pom/package-frame.html +++ b/xref/org/owasp/dependencycheck/xml/pom/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/xref/org/owasp/dependencycheck/xml/pom/package-summary.html b/xref/org/owasp/dependencycheck/xml/pom/package-summary.html index da664d834..1534fa8a2 100644 --- a/xref/org/owasp/dependencycheck/xml/pom/package-summary.html +++ b/xref/org/owasp/dependencycheck/xml/pom/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.pom + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.xml.pom diff --git a/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html b/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html index 584dfa251..f87b87fb0 100644 --- a/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html +++ b/xref/org/owasp/dependencycheck/xml/suppression/SuppressionParser.html @@ -136,99 +136,100 @@ 128 final SAXParserFactory factory = SAXParserFactory.newInstance(); 129 factory.setNamespaceAware(true); 130 factory.setValidating(true); -131 final SAXParser saxParser = factory.newSAXParser(); -132 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); -133 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -134 final XMLReader xmlReader = saxParser.getXMLReader(); -135 xmlReader.setErrorHandler(new SuppressionErrorHandler()); -136 xmlReader.setContentHandler(handler); -137 -138 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -139 final InputSource in = new InputSource(reader); -140 //in.setEncoding("UTF-8"); -141 -142 xmlReader.parse(in); -143 -144 return handler.getSuppressionRules(); -145 } catch (ParserConfigurationException ex) { -146 LOGGER.debug("", ex); -147 throw new SuppressionParseException(ex); -148 } catch (SAXException ex) { -149 if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) { -150 throw ex; -151 } else { -152 LOGGER.debug("", ex); -153 throw new SuppressionParseException(ex); -154 } -155 } catch (FileNotFoundException ex) { -156 LOGGER.debug("", ex); -157 throw new SuppressionParseException(ex); -158 } catch (IOException ex) { -159 LOGGER.debug("", ex); -160 throw new SuppressionParseException(ex); -161 } finally { -162 if (schemaStream != null) { -163 try { -164 schemaStream.close(); -165 } catch (IOException ex) { -166 LOGGER.debug("Error closing suppression file stream", ex); -167 } -168 } -169 } -170 } -171 -172 /** -173 * Parses the given XML stream and returns a list of the suppression rules -174 * contained. -175 * -176 * @param inputStream an InputStream containing suppression rues -177 * @return a list of suppression rules -178 * @throws SuppressionParseException if the XML cannot be parsed -179 */ -180 private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException { -181 InputStream schemaStream = null; -182 try { -183 schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA); -184 final SuppressionHandler handler = new SuppressionHandler(); -185 final SAXParserFactory factory = SAXParserFactory.newInstance(); -186 factory.setNamespaceAware(true); -187 factory.setValidating(true); -188 final SAXParser saxParser = factory.newSAXParser(); -189 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); -190 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); -191 final XMLReader xmlReader = saxParser.getXMLReader(); -192 xmlReader.setErrorHandler(new SuppressionErrorHandler()); -193 xmlReader.setContentHandler(handler); -194 -195 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); -196 final InputSource in = new InputSource(reader); -197 -198 xmlReader.parse(in); -199 -200 return handler.getSuppressionRules(); -201 } catch (ParserConfigurationException ex) { -202 LOGGER.debug("", ex); -203 throw new SuppressionParseException(ex); -204 } catch (SAXException ex) { -205 LOGGER.debug("", ex); -206 throw new SuppressionParseException(ex); -207 } catch (FileNotFoundException ex) { -208 LOGGER.debug("", ex); -209 throw new SuppressionParseException(ex); -210 } catch (IOException ex) { -211 LOGGER.debug("", ex); -212 throw new SuppressionParseException(ex); -213 } finally { -214 if (schemaStream != null) { -215 try { -216 schemaStream.close(); -217 } catch (IOException ex) { -218 LOGGER.debug("Error closing old suppression file stream", ex); -219 } -220 } -221 } -222 } -223 } +131 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); +132 final SAXParser saxParser = factory.newSAXParser(); +133 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); +134 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); +135 final XMLReader xmlReader = saxParser.getXMLReader(); +136 xmlReader.setErrorHandler(new SuppressionErrorHandler()); +137 xmlReader.setContentHandler(handler); +138 +139 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); +140 final InputSource in = new InputSource(reader); +141 //in.setEncoding("UTF-8"); +142 +143 xmlReader.parse(in); +144 +145 return handler.getSuppressionRules(); +146 } catch (ParserConfigurationException ex) { +147 LOGGER.debug("", ex); +148 throw new SuppressionParseException(ex); +149 } catch (SAXException ex) { +150 if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) { +151 throw ex; +152 } else { +153 LOGGER.debug("", ex); +154 throw new SuppressionParseException(ex); +155 } +156 } catch (FileNotFoundException ex) { +157 LOGGER.debug("", ex); +158 throw new SuppressionParseException(ex); +159 } catch (IOException ex) { +160 LOGGER.debug("", ex); +161 throw new SuppressionParseException(ex); +162 } finally { +163 if (schemaStream != null) { +164 try { +165 schemaStream.close(); +166 } catch (IOException ex) { +167 LOGGER.debug("Error closing suppression file stream", ex); +168 } +169 } +170 } +171 } +172 +173 /** +174 * Parses the given XML stream and returns a list of the suppression rules +175 * contained. +176 * +177 * @param inputStream an InputStream containing suppression rues +178 * @return a list of suppression rules +179 * @throws SuppressionParseException if the XML cannot be parsed +180 */ +181 private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException { +182 InputStream schemaStream = null; +183 try { +184 schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA); +185 final SuppressionHandler handler = new SuppressionHandler(); +186 final SAXParserFactory factory = SAXParserFactory.newInstance(); +187 factory.setNamespaceAware(true); +188 factory.setValidating(true); +189 final SAXParser saxParser = factory.newSAXParser(); +190 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA); +191 saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); +192 final XMLReader xmlReader = saxParser.getXMLReader(); +193 xmlReader.setErrorHandler(new SuppressionErrorHandler()); +194 xmlReader.setContentHandler(handler); +195 +196 final Reader reader = new InputStreamReader(inputStream, "UTF-8"); +197 final InputSource in = new InputSource(reader); +198 +199 xmlReader.parse(in); +200 +201 return handler.getSuppressionRules(); +202 } catch (ParserConfigurationException ex) { +203 LOGGER.debug("", ex); +204 throw new SuppressionParseException(ex); +205 } catch (SAXException ex) { +206 LOGGER.debug("", ex); +207 throw new SuppressionParseException(ex); +208 } catch (FileNotFoundException ex) { +209 LOGGER.debug("", ex); +210 throw new SuppressionParseException(ex); +211 } catch (IOException ex) { +212 LOGGER.debug("", ex); +213 throw new SuppressionParseException(ex); +214 } finally { +215 if (schemaStream != null) { +216 try { +217 schemaStream.close(); +218 } catch (IOException ex) { +219 LOGGER.debug("Error closing old suppression file stream", ex); +220 } +221 } +222 } +223 } +224 }
      diff --git a/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html b/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html index 676f27eb1..66154dff3 100644 --- a/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html +++ b/xref/org/owasp/dependencycheck/xml/suppression/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.xml.suppression diff --git a/xref/org/owasp/dependencycheck/xml/suppression/package-summary.html b/xref/org/owasp/dependencycheck/xml/suppression/package-summary.html index d5d784671..41a4c3efe 100644 --- a/xref/org/owasp/dependencycheck/xml/suppression/package-summary.html +++ b/xref/org/owasp/dependencycheck/xml/suppression/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.owasp.dependencycheck.xml.suppression + Dependency-Check 1.4.4 Reference Package org.owasp.dependencycheck.xml.suppression diff --git a/xref/org/slf4j/impl/StaticLoggerBinder.html b/xref/org/slf4j/impl/StaticLoggerBinder.html index 6d1ac7d75..fcae5d356 100644 --- a/xref/org/slf4j/impl/StaticLoggerBinder.html +++ b/xref/org/slf4j/impl/StaticLoggerBinder.html @@ -25,8 +25,8 @@ 17 */ 18 package org.slf4j.impl; 19 -20 import org.apache.maven.plugin.logging.Log; -21 import org.owasp.dependencycheck.maven.slf4j.MavenLoggerFactory; +20 import org.apache.tools.ant.Task; +21 import org.owasp.dependencycheck.ant.logging.AntLoggerFactory; 22 import org.slf4j.ILoggerFactory; 23 import org.slf4j.spi.LoggerFactoryBinder; 24 @@ -56,69 +56,70 @@ 48 } 49 50 /** -51 * Maven mojos have their own logger, so we'll use one of those. -52 */ -53 private Log log = null; -54 -55 /** -56 * Set the Task which will this is to log through. -57 * -58 * @param log the task through which to log -59 */ -60 public void setLog(Log log) { -61 this.log = log; -62 loggerFactory = new MavenLoggerFactory(log); -63 } -64 -65 /** -66 * Declare the version of the SLF4J API this implementation is compiled -67 * against. The value of this filed is usually modified with each release. -68 */ -69 // to avoid constant folding by the compiler, this field must *not* be final -70 //CSOFF: StaticVariableName -71 //CSOFF: VisibilityModifier -72 public static String REQUESTED_API_VERSION = "1.7.12"; // final -73 //CSON: VisibilityModifier -74 //CSON: StaticVariableName -75 -76 /** -77 * The logger factory class string. -78 */ -79 private static final String LOGGER_FACTORY_CLASS = MavenLoggerFactory.class.getName(); -80 -81 /** -82 * The ILoggerFactory instance returned by the {@link #getLoggerFactory} -83 * method should always be the same object -84 */ -85 private ILoggerFactory loggerFactory; -86 -87 /** -88 * Constructs the static logger factory. -89 */ -90 private StaticLoggerBinder() { -91 loggerFactory = new MavenLoggerFactory(log); -92 } -93 -94 /** -95 * Returns the logger factory. -96 * -97 * @return the logger factory -98 */ -99 @Override -100 public ILoggerFactory getLoggerFactory() { -101 return loggerFactory; -102 } -103 -104 /** -105 * Returns the logger factory class string. -106 * -107 * @return the logger factory class string -108 */ -109 @Override -110 public String getLoggerFactoryClassStr() { -111 return LOGGER_FACTORY_CLASS; -112 } -113 } +51 * Ant tasks have the log method we actually want to call. So we hang onto +52 * the task as a delegate +53 */ +54 private Task task = null; +55 +56 /** +57 * Set the Task which will this is to log through. +58 * +59 * @param task the task through which to log +60 */ +61 public void setTask(Task task) { +62 this.task = task; +63 loggerFactory = new AntLoggerFactory(task); +64 } +65 +66 /** +67 * Declare the version of the SLF4J API this implementation is compiled +68 * against. The value of this filed is usually modified with each release. +69 */ +70 // to avoid constant folding by the compiler, this field must *not* be final +71 //CSOFF: StaticVariableName +72 //CSOFF: VisibilityModifier +73 public static String REQUESTED_API_VERSION = "1.7.12"; // final +74 //CSON: VisibilityModifier +75 //CSON: StaticVariableName +76 +77 /** +78 * The logger factory class string. +79 */ +80 private static final String LOGGER_FACTORY_CLASS = AntLoggerFactory.class.getName(); +81 +82 /** +83 * The ILoggerFactory instance returned by the {@link #getLoggerFactory} +84 * method should always be the smae object +85 */ +86 private ILoggerFactory loggerFactory; +87 +88 /** +89 * Constructs a new static logger binder. +90 */ +91 private StaticLoggerBinder() { +92 loggerFactory = new AntLoggerFactory(task); +93 } +94 +95 /** +96 * Returns the logger factory. +97 * +98 * @return the logger factory +99 */ +100 @Override +101 public ILoggerFactory getLoggerFactory() { +102 return loggerFactory; +103 } +104 +105 /** +106 * Returns the logger factory class string. +107 * +108 * @return the logger factory class string +109 */ +110 @Override +111 public String getLoggerFactoryClassStr() { +112 return LOGGER_FACTORY_CLASS; +113 } +114 }
      diff --git a/xref/org/slf4j/impl/package-frame.html b/xref/org/slf4j/impl/package-frame.html index 02654a591..b0b9531a8 100644 --- a/xref/org/slf4j/impl/package-frame.html +++ b/xref/org/slf4j/impl/package-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.slf4j.impl + Dependency-Check 1.4.4 Reference Package org.slf4j.impl diff --git a/xref/org/slf4j/impl/package-summary.html b/xref/org/slf4j/impl/package-summary.html index 4b03c151d..5bb53ff57 100644 --- a/xref/org/slf4j/impl/package-summary.html +++ b/xref/org/slf4j/impl/package-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference Package org.slf4j.impl + Dependency-Check 1.4.4 Reference Package org.slf4j.impl diff --git a/xref/overview-frame.html b/xref/overview-frame.html index c5d7b4de7..32c6ec014 100644 --- a/xref/overview-frame.html +++ b/xref/overview-frame.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference + Dependency-Check 1.4.4 Reference @@ -74,9 +74,6 @@
    214. org.owasp.dependencycheck.maven -
    215. -
    216. - org.owasp.dependencycheck.maven.slf4j
    217. org.owasp.dependencycheck.reporting diff --git a/xref/overview-summary.html b/xref/overview-summary.html index 9ea5ea634..fc08388bf 100644 --- a/xref/overview-summary.html +++ b/xref/overview-summary.html @@ -3,7 +3,7 @@ - Dependency-Check 1.4.3 Reference + Dependency-Check 1.4.4 Reference @@ -24,7 +24,7 @@ -

      Dependency-Check 1.4.3 Reference

      +

      Dependency-Check 1.4.4 Reference

      @@ -132,11 +132,6 @@ - - -
      org.owasp.dependencycheck.maven
      - org.owasp.dependencycheck.maven.slf4j -